Fix issues with blank scheduler options
Some checks failed
PikaOS Package Build & Release (amd64-v3) / build (push) Failing after 24s

This commit is contained in:
ferreo 2025-01-12 23:12:39 +00:00
parent 5c5322a012
commit 5c33d2775e
9 changed files with 124 additions and 54 deletions

View File

@ -1 +1 @@
3 4

View File

@ -1,4 +1,4 @@
falcond (1.0.0-101pika2) pika; urgency=low falcond (1.0.0-101pika3) pika; urgency=low
* Initial release * Initial release

View File

@ -27,7 +27,7 @@ override_dh_install:
cp -r falcond-profiles/usr/share/falcond/profiles debian/falcond/usr/share/falcond/ cp -r falcond-profiles/usr/share/falcond/profiles debian/falcond/usr/share/falcond/
override_dh_installsystemd: override_dh_installsystemd:
dh_installsystemd --name=falcond --restart-after-upgrade dh_installsystemd --name=falcond --restart-after-upgrade --start
override_dh_clean: override_dh_clean:
dh_clean dh_clean

View File

@ -7,7 +7,7 @@ const scx_scheds = @import("scx_scheds.zig");
pub const Config = struct { pub const Config = struct {
enable_performance_mode: bool = true, enable_performance_mode: bool = true,
scx_sched: scx_scheds.ScxScheduler = .none, 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, vcache_mode: vcache_setting.VCacheMode = .none,
pub fn load(allocator: std.mem.Allocator) !Config { 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("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 = {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)}); try file.writer().print("vcache_mode = {s}\n", .{@tagName(self.vcache_mode)});
} }
}; };

View File

@ -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| { .pointer => |ptr_info| {
if (ptr_info.size != .Slice) return error.InvalidSyntax; if (ptr_info.size != .Slice) return error.InvalidSyntax;
switch (ptr_info.child) { switch (ptr_info.child) {

View File

@ -101,24 +101,30 @@ pub const PowerProfiles = struct {
return result.toOwnedSlice(); return result.toOwnedSlice();
} }
pub fn enablePerformanceMode(self: *PowerProfiles) !void { 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 {
if (!self.has_performance) return; 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| { 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.allocator.free(profile);
self.original_profile = null; self.original_profile = null;
} }

View File

@ -18,7 +18,7 @@ pub const Profile = struct {
name: []const u8, name: []const u8,
performance_mode: bool = false, performance_mode: bool = false,
scx_sched: scx_scheds.ScxScheduler = .none, 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, vcache_mode: vcache_setting.VCacheMode = .cache,
pub fn matches(self: *const Profile, process_name: []const u8) bool { pub fn matches(self: *const Profile, process_name: []const u8) bool {
@ -67,6 +67,7 @@ pub const ProfileManager = struct {
"REDEngineErrorReporter.exe", "REDEngineErrorReporter.exe",
"REDprelauncher.exe", "REDprelauncher.exe",
"SteamService.exe", "SteamService.exe",
"UnityCrashHandler64.exe",
"start.exe", "start.exe",
}; };
@ -88,25 +89,26 @@ pub const ProfileManager = struct {
if (profile.performance_mode and self.power_profiles.isPerformanceAvailable()) { if (profile.performance_mode and self.power_profiles.isPerformanceAvailable()) {
std.log.info("Enabling performance mode for profile: {s}", .{profile.name}); 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) const effective_mode = if (self.config.vcache_mode != .none)
self.config.vcache_mode self.config.vcache_mode
else else
profile.vcache_mode; 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) const effective_sched = if (self.config.scx_sched != .none)
self.config.scx_sched self.config.scx_sched
else else
profile.scx_sched; 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 self.config.scx_sched_props
else else
profile.scx_sched_props; 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 { } else {
std.log.info("Queueing profile: {s} (active: {s})", .{ profile.name, self.active_profile.?.name }); std.log.info("Queueing profile: {s} (active: {s})", .{ profile.name, self.active_profile.?.name });
try self.queued_profiles.append(profile); try self.queued_profiles.append(profile);
@ -120,12 +122,11 @@ pub const ProfileManager = struct {
if (profile.performance_mode) { if (profile.performance_mode) {
std.log.info("Disabling performance mode for profile: {s}", .{profile.name}); 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); vcache_setting.applyVCacheMode(.none);
try scx_scheds.restorePreviousState(self.allocator); scx_scheds.restorePreviousState(self.allocator);
if (self.queued_profiles.items.len > 0) { if (self.queued_profiles.items.len > 0) {
const next_profile = self.queued_profiles.orderedRemove(0); const next_profile = self.queued_profiles.orderedRemove(0);
std.log.info("Activating next queued profile: {s}", .{next_profile.name}); 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 { pub fn deinit(self: *ProfileManager) void {
if (self.active_profile) |profile| { if (self.active_profile) |profile| {
if (profile.performance_mode) { if (profile.performance_mode) {
self.power_profiles.disablePerformanceMode() catch {}; self.power_profiles.disablePerformanceMode();
} }
} }

View File

@ -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_simple")) return .simple;
if (std.mem.eql(u8, str, "scx_userland")) return .userland; if (std.mem.eql(u8, str, "scx_userland")) return .userland;
if (std.mem.eql(u8, str, "scx_vder")) return .vder; if (std.mem.eql(u8, str, "scx_vder")) return .vder;
return error.InvalidValue; return error.InvalidValue;
} }
}; };
@ -61,13 +62,13 @@ pub const ScxSchedModes = enum {
server, server,
}; };
const PreviousState = struct { const State = struct {
scheduler: ?ScxScheduler = null, scheduler: ?ScxScheduler = null,
mode: ?ScxSchedModes = null, mode: ?ScxSchedModes = null,
}; };
var previous_state: PreviousState = .{}; var previous_state = State{};
var supported_schedulers: []ScxScheduler = undefined; var supported_schedulers: []ScxScheduler = &[_]ScxScheduler{};
var allocator: std.mem.Allocator = undefined; var allocator: std.mem.Allocator = undefined;
pub fn init(alloc: std.mem.Allocator) !void { 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); 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); defer alloc.free(mode_str);
const args = [_][]const u8{ const args = [_][]const u8{
@ -197,11 +207,33 @@ pub fn activateScheduler(alloc: std.mem.Allocator, scheduler: ScxScheduler, mode
try dbus_conn.callMethod("SwitchScheduler", &args); try dbus_conn.callMethod("SwitchScheduler", &args);
} }
pub fn applyScheduler(alloc: std.mem.Allocator, scheduler: ScxScheduler, mode: ScxSchedModes) ScxError!void { pub fn applyScheduler(alloc: std.mem.Allocator, scheduler: ScxScheduler, mode: ?ScxSchedModes) void {
std.log.info("Applying scheduler {s} with mode {s}", .{ scheduler.toScxName(), @tagName(mode) }); storePreviousState(alloc) catch |err| {
std.log.err("Failed to store previous state: {}", .{err});
};
try storePreviousState(alloc); if (scheduler == .none) {
try activateScheduler(alloc, scheduler, mode); 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 { 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{}); 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 (previous_state.scheduler) |scheduler| {
if (scheduler == .none) { if (previous_state.mode) |mode| {
std.log.info("Previous state was none, stopping scheduler", .{}); std.log.info("Restoring previous scheduler {s} with mode {s}", .{ scheduler.toScxName(), @tagName(mode) });
try deactivateScheduler(alloc); activateScheduler(alloc, scheduler, mode) catch |err| {
} else { std.log.err("Failed to restore previous scheduler: {}", .{err});
std.log.info("Restoring previous scheduler: {s}", .{scheduler.toScxName()}); };
try activateScheduler(alloc, scheduler, previous_state.mode orelse .default);
} }
previous_state.scheduler = null; previous_state.scheduler = null;
previous_state.mode = 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});
};
} }
} }

View File

@ -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: ?[]const u8 = null;
var previous_mode_buffer: [10]u8 = undefined; 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) { const file = fs.openFileAbsolute(vcache_path, .{ .mode = .read_write }) catch |err| switch (err) {
error.FileNotFound => return, error.FileNotFound => return,
else => return err, else => {
std.log.err("Failed to open vcache file: {}", .{err});
return;
},
}; };
defer file.close(); defer file.close();
if (vcache_mode == .none) { if (vcache_mode == .none) {
if (previous_mode) |mode| { 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; previous_mode = null;
} }
return; 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) { if (bytes_read > 0) {
previous_mode = previous_mode_buffer[0..bytes_read]; 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", .freq => "frequency",
.cache => "cache", .cache => "cache",
.none => unreachable, .none => unreachable,
}); };
file.writeAll(mode_str) catch |err| {
std.log.err("Failed to write vcache mode: {}", .{err});
};
} }