<varlistentry>
<term><varname>CPUAffinity=</varname></term>
- <listitem><para>Configures the CPU affinity for the service manager as well as the default CPU affinity for all
- forked off processes. Takes a list of CPU indices or ranges separated by either whitespace or commas. CPU
- ranges are specified by the lower and upper CPU indices separated by a dash. Individual services may override
- the CPU affinity for their processes with the <varname>CPUAffinity=</varname> setting in unit files, see
+ <listitem><para>Configures the CPU affinity for the service manager as well as the default CPU
+ affinity for all forked off processes. Takes a list of CPU indices or ranges separated by either
+ whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated by a
+ dash. This option may be specified more than once, in which case the specified CPU affinity masks are
+ merged. If the empty string is assigned, the mask is reset, all assignments prior to this will have
+ no effect. Individual services may override the CPU affinity for their processes with the
+ <varname>CPUAffinity=</varname> setting in unit files, see
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
static EmergencyAction arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE;
static OOMPolicy arg_default_oom_policy = OOM_STOP;
+static CPUSet arg_cpu_affinity = {};
+
_noreturn_ static void freeze_or_exit_or_reboot(void) {
/* If we are running in a container, let's prefer exiting, after all we can propagate an exit code to
void *data,
void *userdata) {
- _cleanup_(cpu_set_reset) CPUSet c = {};
- int r;
+ CPUSet *affinity = data;
- r = parse_cpu_set_full(rvalue, &c, true, unit, filename, line, lvalue);
- if (r < 0)
- return r;
+ assert(affinity);
- if (sched_setaffinity(0, c.allocated, c.set) < 0)
- log_warning_errno(errno, "Failed to set CPU affinity: %m");
-
- // FIXME: parsing and execution should be seperated.
+ (void) parse_cpu_set_extend(rvalue, affinity, true, unit, filename, line, lvalue);
return 0;
}
{ "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
{ "Manager", "CrashReboot", config_parse_bool, 0, &arg_crash_reboot },
{ "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status },
- { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL },
+ { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, &arg_cpu_affinity },
{ "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
{ "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog },
{ "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog },
log_warning_errno(r, "Failed to write '%s' to /proc/sys/kernel/core_pattern, ignoring: %m", arg_early_core_pattern);
}
+static void update_cpu_affinity(bool skip_setup) {
+ _cleanup_free_ char *mask = NULL;
+
+ if (skip_setup || !arg_cpu_affinity.set)
+ return;
+
+ assert(arg_cpu_affinity.allocated > 0);
+
+ mask = cpu_set_to_string(&arg_cpu_affinity);
+ log_debug("Setting CPU affinity to %s.", strnull(mask));
+
+ if (sched_setaffinity(0, arg_cpu_affinity.allocated, arg_cpu_affinity.set) < 0)
+ log_warning_errno(errno, "Failed to set CPU affinity: %m");
+}
+
static void do_reexecute(
int argc,
char *argv[],
set_manager_defaults(m);
+ update_cpu_affinity(false);
+
if (saved_log_level >= 0)
manager_override_log_level(m, saved_log_level);
if (saved_log_target >= 0)
if (arg_action != ACTION_RUN)
return 0;
+ update_cpu_affinity(skip_setup);
+
if (arg_system) {
/* Make sure we leave a core dump without panicking the kernel. */
install_crash_handler();
arg_confirm_spawn = mfree(arg_confirm_spawn);
arg_default_environment = strv_free(arg_default_environment);
arg_syscall_archs = set_free(arg_syscall_archs);
+
+ cpu_set_reset(&arg_cpu_affinity);
}
static int load_configuration(int argc, char **argv, const char **ret_error_message) {