diff --git a/.github/release-nest-v3 b/.github/release-nest-v3 index e440e5c..bf0d87a 100644 --- a/.github/release-nest-v3 +++ b/.github/release-nest-v3 @@ -1 +1 @@ -3 \ No newline at end of file +4 \ No newline at end of file diff --git a/falcond/debian/changelog b/falcond/debian/changelog index 15138e8..520a20b 100644 --- a/falcond/debian/changelog +++ b/falcond/debian/changelog @@ -1,4 +1,4 @@ -falcond (1.0.0-101pika2) pika; urgency=low +falcond (1.0.0-101pika3) pika; urgency=low * Initial release diff --git a/falcond/debian/rules b/falcond/debian/rules index df3b001..826637d 100755 --- a/falcond/debian/rules +++ b/falcond/debian/rules @@ -27,7 +27,7 @@ override_dh_install: cp -r falcond-profiles/usr/share/falcond/profiles debian/falcond/usr/share/falcond/ override_dh_installsystemd: - dh_installsystemd --name=falcond --restart-after-upgrade + dh_installsystemd --name=falcond --restart-after-upgrade --start override_dh_clean: dh_clean diff --git a/falcond/src/config.zig b/falcond/src/config.zig index b491a07..3c352df 100644 --- a/falcond/src/config.zig +++ b/falcond/src/config.zig @@ -7,7 +7,7 @@ const scx_scheds = @import("scx_scheds.zig"); pub const Config = struct { enable_performance_mode: bool = true, scx_sched: scx_scheds.ScxScheduler = .none, - scx_sched_props: scx_scheds.ScxSchedModes = .gaming, + scx_sched_props: ?scx_scheds.ScxSchedModes = null, vcache_mode: vcache_setting.VCacheMode = .none, pub fn load(allocator: std.mem.Allocator) !Config { @@ -46,7 +46,6 @@ pub const Config = struct { try file.writer().print("enable_performance_mode = {}\n", .{self.enable_performance_mode}); try file.writer().print("scx_sched = {s}\n", .{@tagName(self.scx_sched)}); - try file.writer().print("scx_sched_props = {s}\n", .{@tagName(self.scx_sched_props)}); try file.writer().print("vcache_mode = {s}\n", .{@tagName(self.vcache_mode)}); } }; diff --git a/falcond/src/parser.zig b/falcond/src/parser.zig index 074b721..c2a58ce 100644 --- a/falcond/src/parser.zig +++ b/falcond/src/parser.zig @@ -236,6 +236,20 @@ pub fn Parser(comptime T: type) type { } } }, + .optional => |opt_info| { + switch (@typeInfo(opt_info.child)) { + .@"enum" => { + const ident = try self.parseIdentifier(); + inline for (std.meta.fields(opt_info.child)) |enum_field| { + if (std.mem.eql(u8, ident, enum_field.name)) { + @field(result, field.name) = @field(opt_info.child, enum_field.name); + break; + } + } + }, + else => return error.InvalidSyntax, + } + }, .pointer => |ptr_info| { if (ptr_info.size != .Slice) return error.InvalidSyntax; switch (ptr_info.child) { diff --git a/falcond/src/power_profiles.zig b/falcond/src/power_profiles.zig index 8f16fc5..c64f532 100644 --- a/falcond/src/power_profiles.zig +++ b/falcond/src/power_profiles.zig @@ -101,24 +101,30 @@ pub const PowerProfiles = struct { return result.toOwnedSlice(); } - pub fn enablePerformanceMode(self: *PowerProfiles) !void { - if (!self.has_performance) { - std.log.warn("Performance mode not available", .{}); - return; - } - - if (self.original_profile == null) { - self.original_profile = try self.dbus.getProperty("ActiveProfile"); - } - - try self.dbus.setProperty("ActiveProfile", "performance"); - } - - pub fn disablePerformanceMode(self: *PowerProfiles) !void { + pub fn enablePerformanceMode(self: *PowerProfiles) void { if (!self.has_performance) return; + if (self.dbus.getProperty("ActiveProfile")) |profile| { + defer self.allocator.free(profile); + if (!std.mem.eql(u8, profile, "performance")) { + self.original_profile = self.allocator.dupe(u8, profile) catch |err| { + std.log.err("Failed to store original power profile: {}", .{err}); + return; + }; + self.dbus.setProperty("ActiveProfile", "performance") catch |err| { + std.log.err("Failed to set performance mode: {}", .{err}); + }; + } + } else |err| { + std.log.err("Failed to get active power profile: {}", .{err}); + } + } + + pub fn disablePerformanceMode(self: *PowerProfiles) void { if (self.original_profile) |profile| { - try self.dbus.setProperty("ActiveProfile", profile); + self.dbus.setProperty("ActiveProfile", profile) catch |err| { + std.log.err("Failed to restore power profile: {}", .{err}); + }; self.allocator.free(profile); self.original_profile = null; } diff --git a/falcond/src/profile.zig b/falcond/src/profile.zig index 4f990af..29e3019 100644 --- a/falcond/src/profile.zig +++ b/falcond/src/profile.zig @@ -18,7 +18,7 @@ pub const Profile = struct { name: []const u8, performance_mode: bool = false, scx_sched: scx_scheds.ScxScheduler = .none, - scx_sched_props: scx_scheds.ScxSchedModes = .gaming, + scx_sched_props: ?scx_scheds.ScxSchedModes = null, vcache_mode: vcache_setting.VCacheMode = .cache, pub fn matches(self: *const Profile, process_name: []const u8) bool { @@ -67,6 +67,7 @@ pub const ProfileManager = struct { "REDEngineErrorReporter.exe", "REDprelauncher.exe", "SteamService.exe", + "UnityCrashHandler64.exe", "start.exe", }; @@ -88,25 +89,26 @@ pub const ProfileManager = struct { if (profile.performance_mode and self.power_profiles.isPerformanceAvailable()) { std.log.info("Enabling performance mode for profile: {s}", .{profile.name}); - try self.power_profiles.enablePerformanceMode(); + self.power_profiles.enablePerformanceMode(); } const effective_mode = if (self.config.vcache_mode != .none) self.config.vcache_mode else profile.vcache_mode; - try vcache_setting.applyVCacheMode(effective_mode); + vcache_setting.applyVCacheMode(effective_mode); - // Apply scheduler settings, using global config override if set const effective_sched = if (self.config.scx_sched != .none) self.config.scx_sched else profile.scx_sched; - const effective_sched_mode = if (self.config.scx_sched != .none) + + const effective_scx_mode = if (self.config.scx_sched != .none) self.config.scx_sched_props else profile.scx_sched_props; - try scx_scheds.applyScheduler(self.allocator, effective_sched, effective_sched_mode); + + scx_scheds.applyScheduler(self.allocator, effective_sched, effective_scx_mode); } else { std.log.info("Queueing profile: {s} (active: {s})", .{ profile.name, self.active_profile.?.name }); try self.queued_profiles.append(profile); @@ -120,12 +122,11 @@ pub const ProfileManager = struct { if (profile.performance_mode) { std.log.info("Disabling performance mode for profile: {s}", .{profile.name}); - try self.power_profiles.disablePerformanceMode(); + self.power_profiles.disablePerformanceMode(); } - try vcache_setting.applyVCacheMode(.none); - try scx_scheds.restorePreviousState(self.allocator); - + vcache_setting.applyVCacheMode(.none); + scx_scheds.restorePreviousState(self.allocator); if (self.queued_profiles.items.len > 0) { const next_profile = self.queued_profiles.orderedRemove(0); std.log.info("Activating next queued profile: {s}", .{next_profile.name}); @@ -256,7 +257,7 @@ pub const ProfileManager = struct { pub fn deinit(self: *ProfileManager) void { if (self.active_profile) |profile| { if (profile.performance_mode) { - self.power_profiles.disablePerformanceMode() catch {}; + self.power_profiles.disablePerformanceMode(); } } diff --git a/falcond/src/scx_scheds.zig b/falcond/src/scx_scheds.zig index 7bc5dce..76139f6 100644 --- a/falcond/src/scx_scheds.zig +++ b/falcond/src/scx_scheds.zig @@ -49,6 +49,7 @@ pub const ScxScheduler = enum { if (std.mem.eql(u8, str, "scx_simple")) return .simple; if (std.mem.eql(u8, str, "scx_userland")) return .userland; if (std.mem.eql(u8, str, "scx_vder")) return .vder; + return error.InvalidValue; } }; @@ -61,13 +62,13 @@ pub const ScxSchedModes = enum { server, }; -const PreviousState = struct { +const State = struct { scheduler: ?ScxScheduler = null, mode: ?ScxSchedModes = null, }; -var previous_state: PreviousState = .{}; -var supported_schedulers: []ScxScheduler = undefined; +var previous_state = State{}; +var supported_schedulers: []ScxScheduler = &[_]ScxScheduler{}; var allocator: std.mem.Allocator = undefined; pub fn init(alloc: std.mem.Allocator) !void { @@ -182,10 +183,19 @@ pub fn storePreviousState(alloc: std.mem.Allocator) !void { } } -pub fn activateScheduler(alloc: std.mem.Allocator, scheduler: ScxScheduler, mode: ScxSchedModes) ScxError!void { +fn isSchedulerSupported(scheduler: ScxScheduler) bool { + if (scheduler == .none) return true; + + for (supported_schedulers) |s| { + if (s == scheduler) return true; + } + return false; +} + +pub fn activateScheduler(alloc: std.mem.Allocator, scheduler: ScxScheduler, mode: ?ScxSchedModes) ScxError!void { var dbus_conn = dbus.DBus.init(alloc, SCX_NAME, SCX_PATH, SCX_IFACE); - const mode_str = try std.fmt.allocPrint(alloc, "{d}", .{modeToInt(mode)}); + const mode_str = try std.fmt.allocPrint(alloc, "{d}", .{modeToInt(mode orelse .default)}); defer alloc.free(mode_str); const args = [_][]const u8{ @@ -197,11 +207,33 @@ pub fn activateScheduler(alloc: std.mem.Allocator, scheduler: ScxScheduler, mode try dbus_conn.callMethod("SwitchScheduler", &args); } -pub fn applyScheduler(alloc: std.mem.Allocator, scheduler: ScxScheduler, mode: ScxSchedModes) ScxError!void { - std.log.info("Applying scheduler {s} with mode {s}", .{ scheduler.toScxName(), @tagName(mode) }); +pub fn applyScheduler(alloc: std.mem.Allocator, scheduler: ScxScheduler, mode: ?ScxSchedModes) void { + storePreviousState(alloc) catch |err| { + std.log.err("Failed to store previous state: {}", .{err}); + }; - try storePreviousState(alloc); - try activateScheduler(alloc, scheduler, mode); + if (scheduler == .none) { + std.log.info("No scheduler to apply for this profile", .{}); + deactivateScheduler(alloc) catch |err| { + std.log.err("Failed to deactivate scheduler: {}", .{err}); + }; + return; + } + + if (!isSchedulerSupported(scheduler)) { + std.log.info("Scheduler {s} not supported by system", .{scheduler.toScxName()}); + return; + } + + if (mode) |m| { + std.log.info("Applying scheduler {s} with mode {s}", .{ scheduler.toScxName(), @tagName(m) }); + } else { + std.log.info("Applying scheduler {s} with default mode", .{scheduler.toScxName()}); + } + + activateScheduler(alloc, scheduler, mode orelse .default) catch |err| { + std.log.err("Failed to activate scheduler {s}: {}", .{ scheduler.toScxName(), err }); + }; } pub fn deactivateScheduler(alloc: std.mem.Allocator) ScxError!void { @@ -209,16 +241,20 @@ pub fn deactivateScheduler(alloc: std.mem.Allocator) ScxError!void { try dbus_conn.callMethod("StopScheduler", &[_][]const u8{}); } -pub fn restorePreviousState(alloc: std.mem.Allocator) ScxError!void { +pub fn restorePreviousState(alloc: std.mem.Allocator) void { if (previous_state.scheduler) |scheduler| { - if (scheduler == .none) { - std.log.info("Previous state was none, stopping scheduler", .{}); - try deactivateScheduler(alloc); - } else { - std.log.info("Restoring previous scheduler: {s}", .{scheduler.toScxName()}); - try activateScheduler(alloc, scheduler, previous_state.mode orelse .default); + if (previous_state.mode) |mode| { + std.log.info("Restoring previous scheduler {s} with mode {s}", .{ scheduler.toScxName(), @tagName(mode) }); + activateScheduler(alloc, scheduler, mode) catch |err| { + std.log.err("Failed to restore previous scheduler: {}", .{err}); + }; } previous_state.scheduler = null; previous_state.mode = null; + } else { + std.log.info("Previous state was none, stopping scheduler", .{}); + deactivateScheduler(alloc) catch |err| { + std.log.err("Failed to stop scheduler: {}", .{err}); + }; } } diff --git a/falcond/src/vcache_setting.zig b/falcond/src/vcache_setting.zig index dc3917c..3698668 100644 --- a/falcond/src/vcache_setting.zig +++ b/falcond/src/vcache_setting.zig @@ -12,31 +12,45 @@ const vcache_path = "/sys/bus/platform/drivers/amd_x3d_vcache/AMDI0101:00/amd_x3 var previous_mode: ?[]const u8 = null; var previous_mode_buffer: [10]u8 = undefined; -pub fn applyVCacheMode(vcache_mode: VCacheMode) !void { +pub fn applyVCacheMode(vcache_mode: VCacheMode) void { const file = fs.openFileAbsolute(vcache_path, .{ .mode = .read_write }) catch |err| switch (err) { error.FileNotFound => return, - else => return err, + else => { + std.log.err("Failed to open vcache file: {}", .{err}); + return; + }, }; defer file.close(); if (vcache_mode == .none) { if (previous_mode) |mode| { - try file.writeAll(mode); + file.writeAll(mode) catch |err| { + std.log.err("Failed to restore previous vcache mode: {}", .{err}); + }; previous_mode = null; } return; } - const bytes_read = try file.readAll(previous_mode_buffer[0..]); + const bytes_read = file.readAll(previous_mode_buffer[0..]) catch |err| { + std.log.err("Failed to read current vcache mode: {}", .{err}); + return; + }; if (bytes_read > 0) { previous_mode = previous_mode_buffer[0..bytes_read]; } - try file.seekTo(0); + file.seekTo(0) catch |err| { + std.log.err("Failed to seek vcache file: {}", .{err}); + return; + }; - try file.writeAll(switch (vcache_mode) { + const mode_str = switch (vcache_mode) { .freq => "frequency", .cache => "cache", .none => unreachable, - }); + }; + file.writeAll(mode_str) catch |err| { + std.log.err("Failed to write vcache mode: {}", .{err}); + }; }