mirror of
https://github.com/systemd/systemd.git
synced 2025-03-08 08:58:27 +03:00
Merge pull request #3753 from poettering/tasks-max-scale
Add support for relative TasksMax= specifications, and bump default for services
This commit is contained in:
commit
5052c4eadd
@ -315,12 +315,11 @@
|
||||
<varlistentry>
|
||||
<term><varname>UserTasksMax=</varname></term>
|
||||
|
||||
<listitem><para>Sets the maximum number of OS tasks each user
|
||||
may run concurrently. This controls the
|
||||
<varname>TasksMax=</varname> setting of the per-user slice
|
||||
unit, see
|
||||
<listitem><para>Sets the maximum number of OS tasks each user may run concurrently. This controls the
|
||||
<varname>TasksMax=</varname> setting of the per-user slice unit, see
|
||||
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details. Defaults to 12288 (12K).</para></listitem>
|
||||
for details. Defaults to 33%, which equals 10813 with the kernel's defaults on the host, but might be smaller
|
||||
in OS containers.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -325,12 +325,11 @@
|
||||
<varlistentry>
|
||||
<term><varname>DefaultTasksMax=</varname></term>
|
||||
|
||||
<listitem><para>Configure the default value for the per-unit
|
||||
<varname>TasksMax=</varname> setting. See
|
||||
<listitem><para>Configure the default value for the per-unit <varname>TasksMax=</varname> setting. See
|
||||
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details. This setting applies to all unit types that
|
||||
support resource control settings, with the exception of slice
|
||||
units. Defaults to 512.</para></listitem>
|
||||
for details. This setting applies to all unit types that support resource control settings, with the exception
|
||||
of slice units. Defaults to 15%, which equals 4915 with the kernel's defaults on the host, but might be smaller
|
||||
in OS containers.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -327,15 +327,12 @@
|
||||
<term><varname>TasksMax=<replaceable>N</replaceable></varname></term>
|
||||
|
||||
<listitem>
|
||||
<para>Specify the maximum number of tasks that may be
|
||||
created in the unit. This ensures that the number of tasks
|
||||
accounted for the unit (see above) stays below a specific
|
||||
limit. If assigned the special value
|
||||
<literal>infinity</literal>, no tasks limit is applied. This
|
||||
controls the <literal>pids.max</literal> control group
|
||||
attribute. For details about this control group attribute,
|
||||
see <ulink
|
||||
url="https://www.kernel.org/doc/Documentation/cgroup-v1/pids.txt">pids.txt</ulink>.</para>
|
||||
<para>Specify the maximum number of tasks that may be created in the unit. This ensures that the number of
|
||||
tasks accounted for the unit (see above) stays below a specific limit. This either takes an absolute number
|
||||
of tasks or a percentage value that is taken relative to the configured maximum number of tasks on the
|
||||
system. If assigned the special value <literal>infinity</literal>, no tasks limit is applied. This controls
|
||||
the <literal>pids.max</literal> control group attribute. For details about this control group attribute, see
|
||||
<ulink url="https://www.kernel.org/doc/Documentation/cgroup-v1/pids.txt">pids.txt</ulink>.</para>
|
||||
|
||||
<para>Implies <literal>TasksAccounting=true</literal>. The
|
||||
system default for this setting may be controlled with
|
||||
|
@ -832,6 +832,61 @@ uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t system_tasks_max(void) {
|
||||
|
||||
#if SIZEOF_PID_T == 4
|
||||
#define TASKS_MAX ((uint64_t) (INT32_MAX-1))
|
||||
#elif SIZEOF_PID_T == 2
|
||||
#define TASKS_MAX ((uint64_t) (INT16_MAX-1))
|
||||
#else
|
||||
#error "Unknown pid_t size"
|
||||
#endif
|
||||
|
||||
_cleanup_free_ char *value = NULL, *root = NULL;
|
||||
uint64_t a = TASKS_MAX, b = TASKS_MAX;
|
||||
|
||||
/* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
|
||||
* limit:
|
||||
*
|
||||
* a) the maximum value for the pid_t type
|
||||
* b) the cgroups pids_max attribute for the system
|
||||
* c) the kernel's configure maximum PID value
|
||||
*
|
||||
* And then pick the smallest of the three */
|
||||
|
||||
if (read_one_line_file("/proc/sys/kernel/pid_max", &value) >= 0)
|
||||
(void) safe_atou64(value, &a);
|
||||
|
||||
if (cg_get_root_path(&root) >= 0) {
|
||||
value = mfree(value);
|
||||
|
||||
if (cg_get_attribute("pids", root, "pids.max", &value) >= 0)
|
||||
(void) safe_atou64(value, &b);
|
||||
}
|
||||
|
||||
return MIN3(TASKS_MAX,
|
||||
a <= 0 ? TASKS_MAX : a,
|
||||
b <= 0 ? TASKS_MAX : b);
|
||||
}
|
||||
|
||||
uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
|
||||
uint64_t t, m;
|
||||
|
||||
assert(max > 0);
|
||||
|
||||
/* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
|
||||
* relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
|
||||
|
||||
t = system_tasks_max();
|
||||
assert(t > 0);
|
||||
|
||||
m = t * v;
|
||||
if (m / t != v) /* overflow? */
|
||||
return UINT64_MAX;
|
||||
|
||||
return m / max;
|
||||
}
|
||||
|
||||
int update_reboot_parameter_and_warn(const char *param) {
|
||||
int r;
|
||||
|
||||
|
@ -186,6 +186,9 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
|
||||
uint64_t physical_memory(void);
|
||||
uint64_t physical_memory_scale(uint64_t v, uint64_t max);
|
||||
|
||||
uint64_t system_tasks_max(void);
|
||||
uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
|
||||
|
||||
int update_reboot_parameter_and_warn(const char *param);
|
||||
|
||||
int version(void);
|
||||
|
@ -856,7 +856,7 @@ int bus_cgroup_set_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "MemoryLowByPhysicalMemory", "MemoryHighByPhysicalMemory", "MemoryMaxByPhysicalMemory")) {
|
||||
} else if (STR_IN_SET(name, "MemoryLowScale", "MemoryHighScale", "MemoryMaxScale")) {
|
||||
uint32_t raw;
|
||||
uint64_t v;
|
||||
|
||||
@ -872,7 +872,7 @@ int bus_cgroup_set_property(
|
||||
const char *e;
|
||||
|
||||
/* Chop off suffix */
|
||||
assert_se(e = endswith(name, "ByPhysicalMemory"));
|
||||
assert_se(e = endswith(name, "Scale"));
|
||||
name = strndupa(name, e - name);
|
||||
|
||||
if (streq(name, "MemoryLow"))
|
||||
@ -883,7 +883,8 @@ int bus_cgroup_set_property(
|
||||
c->memory_max = v;
|
||||
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
|
||||
unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu32 "%%", name, (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100, (uint64_t) UINT32_MAX)));
|
||||
unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu32 "%%", name,
|
||||
(uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -909,7 +910,7 @@ int bus_cgroup_set_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "MemoryLimitByPhysicalMemory")) {
|
||||
} else if (streq(name, "MemoryLimitScale")) {
|
||||
uint64_t limit;
|
||||
uint32_t raw;
|
||||
|
||||
@ -924,7 +925,8 @@ int bus_cgroup_set_property(
|
||||
if (mode != UNIT_CHECK) {
|
||||
c->memory_limit = limit;
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
|
||||
unit_write_drop_in_private_format(u, mode, "MemoryLimit", "MemoryLimit=%" PRIu32 "%%", (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100, (uint64_t) UINT32_MAX)));
|
||||
unit_write_drop_in_private_format(u, mode, "MemoryLimit", "MemoryLimit=%" PRIu32 "%%",
|
||||
(uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -1060,6 +1062,8 @@ int bus_cgroup_set_property(
|
||||
r = sd_bus_message_read(message, "t", &limit);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (limit <= 0)
|
||||
return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name);
|
||||
|
||||
if (mode != UNIT_CHECK) {
|
||||
c->tasks_max = limit;
|
||||
@ -1071,6 +1075,26 @@ int bus_cgroup_set_property(
|
||||
unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu64, limit);
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else if (streq(name, "TasksMaxScale")) {
|
||||
uint64_t limit;
|
||||
uint32_t raw;
|
||||
|
||||
r = sd_bus_message_read(message, "u", &raw);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
limit = system_tasks_max_scale(raw, UINT32_MAX);
|
||||
if (limit <= 0 || limit >= UINT64_MAX)
|
||||
return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name);
|
||||
|
||||
if (mode != UNIT_CHECK) {
|
||||
c->tasks_max = limit;
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
|
||||
unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu32 "%%",
|
||||
(uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -2823,8 +2823,8 @@ int config_parse_memory_limit(
|
||||
} else
|
||||
bytes = physical_memory_scale(r, 100U);
|
||||
|
||||
if (bytes < 1) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' too small. Ignoring.", rvalue);
|
||||
if (bytes <= 0 || bytes >= UINT64_MAX) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' out of range. Ignoring.", rvalue);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -2861,9 +2861,18 @@ int config_parse_tasks_max(
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = safe_atou64(rvalue, &u);
|
||||
if (r < 0 || u < 1) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Maximum tasks value '%s' invalid. Ignoring.", rvalue);
|
||||
r = parse_percent(rvalue);
|
||||
if (r < 0) {
|
||||
r = safe_atou64(rvalue, &u);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Maximum tasks value '%s' invalid. Ignoring.", rvalue);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
u = system_tasks_max_scale(r, 100U);
|
||||
|
||||
if (u <= 0 || u >= UINT64_MAX) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range. Ignoring.", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ static bool arg_default_io_accounting = false;
|
||||
static bool arg_default_blockio_accounting = false;
|
||||
static bool arg_default_memory_accounting = false;
|
||||
static bool arg_default_tasks_accounting = true;
|
||||
static uint64_t arg_default_tasks_max = UINT64_C(512);
|
||||
static uint64_t arg_default_tasks_max = UINT64_MAX;
|
||||
static sd_id128_t arg_machine_id = {};
|
||||
|
||||
noreturn static void freeze_or_reboot(void) {
|
||||
@ -1298,6 +1298,11 @@ static int fixup_environment(void) {
|
||||
_cleanup_free_ char *term = NULL;
|
||||
int r;
|
||||
|
||||
/* We expect the environment to be set correctly
|
||||
* if run inside a container. */
|
||||
if (detect_container() > 0)
|
||||
return 0;
|
||||
|
||||
/* When started as PID1, the kernel uses /dev/console
|
||||
* for our stdios and uses TERM=linux whatever the
|
||||
* backend device used by the console. We try to make
|
||||
@ -1314,7 +1319,7 @@ static int fixup_environment(void) {
|
||||
if (r == 0) {
|
||||
term = strdup(default_term_for_tty("/dev/console") + 5);
|
||||
if (!term)
|
||||
return -errno;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (setenv("TERM", term, 1) < 0)
|
||||
@ -1508,13 +1513,10 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (arg_system) {
|
||||
/* We expect the environment to be set correctly
|
||||
* if run inside a container. */
|
||||
if (detect_container() <= 0)
|
||||
if (fixup_environment() < 0) {
|
||||
error_message = "Failed to fix up PID1 environment";
|
||||
goto finish;
|
||||
}
|
||||
if (fixup_environment() < 0) {
|
||||
error_message = "Failed to fix up PID1 environment";
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* Try to figure out if we can use colors with the console. No
|
||||
* need to do that for user instances since they never log
|
||||
@ -1556,6 +1558,8 @@ int main(int argc, char *argv[]) {
|
||||
(void) reset_all_signal_handlers();
|
||||
(void) ignore_signals(SIGNALS_IGNORE, -1);
|
||||
|
||||
arg_default_tasks_max = system_tasks_max_scale(15U, 100U); /* 15% the system PIDs equals 4915 by default. */
|
||||
|
||||
if (parse_config_file() < 0) {
|
||||
error_message = "Failed to parse config file";
|
||||
goto finish;
|
||||
|
@ -569,7 +569,7 @@ int manager_new(UnitFileScope scope, bool test_run, Manager **_m) {
|
||||
m->exit_code = _MANAGER_EXIT_CODE_INVALID;
|
||||
m->default_timer_accuracy_usec = USEC_PER_MINUTE;
|
||||
m->default_tasks_accounting = true;
|
||||
m->default_tasks_max = UINT64_C(512);
|
||||
m->default_tasks_max = UINT64_MAX;
|
||||
|
||||
#ifdef ENABLE_EFI
|
||||
if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0)
|
||||
|
@ -42,7 +42,7 @@
|
||||
#DefaultBlockIOAccounting=no
|
||||
#DefaultMemoryAccounting=no
|
||||
#DefaultTasksAccounting=yes
|
||||
#DefaultTasksMax=512
|
||||
#DefaultTasksMax=15%
|
||||
#DefaultLimitCPU=
|
||||
#DefaultLimitFSIZE=
|
||||
#DefaultLimitDATA=
|
||||
|
@ -36,4 +36,4 @@ Login.RuntimeDirectorySize, config_parse_tmpfs_size, 0, offsetof(Manag
|
||||
Login.RemoveIPC, config_parse_bool, 0, offsetof(Manager, remove_ipc)
|
||||
Login.InhibitorsMax, config_parse_uint64, 0, offsetof(Manager, inhibitors_max)
|
||||
Login.SessionsMax, config_parse_uint64, 0, offsetof(Manager, sessions_max)
|
||||
Login.UserTasksMax, config_parse_uint64, 0, offsetof(Manager, user_tasks_max)
|
||||
Login.UserTasksMax, config_parse_user_tasks_max,0, offsetof(Manager, user_tasks_max)
|
||||
|
@ -870,3 +870,48 @@ int config_parse_tmpfs_size(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_user_tasks_max(
|
||||
const char* unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
uint64_t *m = data;
|
||||
uint64_t k;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
/* First, try to parse as percentage */
|
||||
r = parse_percent(rvalue);
|
||||
if (r > 0 && r < 100)
|
||||
k = system_tasks_max_scale(r, 100U);
|
||||
else {
|
||||
|
||||
/* If the passed argument was not a percentage, or out of range, parse as byte size */
|
||||
|
||||
r = safe_atou64(rvalue, &k);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse tasks maximum, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (k <= 0 || k >= UINT64_MAX) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Tasks maximum out of range, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*m = k;
|
||||
return 0;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ static void manager_reset_config(Manager *m) {
|
||||
m->idle_action = HANDLE_IGNORE;
|
||||
|
||||
m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
|
||||
m->user_tasks_max = 12288;
|
||||
m->user_tasks_max = system_tasks_max_scale(33U, 100U); /* 33% */
|
||||
m->sessions_max = 8192;
|
||||
m->inhibitors_max = 8192;
|
||||
|
||||
|
@ -34,4 +34,4 @@
|
||||
#RemoveIPC=yes
|
||||
#InhibitorsMax=8192
|
||||
#SessionsMax=8192
|
||||
#UserTasksMax=12288
|
||||
#UserTasksMax=33%
|
||||
|
@ -187,6 +187,7 @@ const struct ConfigPerfItem* logind_gperf_lookup(const char *key, unsigned lengt
|
||||
int manager_set_lid_switch_ignore(Manager *m, usec_t until);
|
||||
|
||||
int config_parse_tmpfs_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_user_tasks_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
||||
int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret);
|
||||
int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret);
|
||||
|
@ -132,10 +132,10 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
|
||||
char *n;
|
||||
|
||||
/* When this is a percentage we'll convert this into a relative value in the range
|
||||
* 0…UINT32_MAX and pass it in the MemoryLowByPhysicalMemory property (and related
|
||||
* 0…UINT32_MAX and pass it in the MemoryLowScale property (and related
|
||||
* ones). This way the physical memory size can be determined server-side */
|
||||
|
||||
n = strjoina(field, "ByPhysicalMemory");
|
||||
n = strjoina(field, "Scale");
|
||||
r = sd_bus_message_append(m, "sv", n, "u", (uint32_t) (((uint64_t) UINT32_MAX * r) / 100U));
|
||||
goto finish;
|
||||
|
||||
@ -148,6 +148,26 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
|
||||
|
||||
r = sd_bus_message_append(m, "sv", field, "t", bytes);
|
||||
goto finish;
|
||||
} else if (streq(field, "TasksMax")) {
|
||||
uint64_t t;
|
||||
|
||||
if (isempty(eq) || streq(eq, "infinity"))
|
||||
t = (uint64_t) -1;
|
||||
else {
|
||||
r = parse_percent(eq);
|
||||
if (r >= 0) {
|
||||
r = sd_bus_message_append(m, "sv", "TasksMaxScale", "u", (uint32_t) (((uint64_t) UINT32_MAX * r) / 100U));
|
||||
goto finish;
|
||||
} else {
|
||||
r = safe_atou64(eq, &t);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse maximum tasks specification %s", assignment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
r = sd_bus_message_append(m, "sv", "TasksMax", "t", t);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
|
||||
@ -191,21 +211,6 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
|
||||
|
||||
r = sd_bus_message_append(m, "v", "b", r);
|
||||
|
||||
} else if (streq(field, "TasksMax")) {
|
||||
uint64_t n;
|
||||
|
||||
if (isempty(eq) || streq(eq, "infinity"))
|
||||
n = (uint64_t) -1;
|
||||
else {
|
||||
r = safe_atou64(eq, &n);
|
||||
if (r < 0) {
|
||||
log_error("Failed to parse maximum tasks specification %s", assignment);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_bus_message_append(m, "v", "t", n);
|
||||
|
||||
} else if (STR_IN_SET(field, "CPUShares", "StartupCPUShares")) {
|
||||
uint64_t u;
|
||||
|
||||
|
@ -308,7 +308,43 @@ static void test_physical_memory_scale(void) {
|
||||
|
||||
/* overflow */
|
||||
assert_se(physical_memory_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX);
|
||||
}
|
||||
|
||||
static void test_system_tasks_max(void) {
|
||||
uint64_t t;
|
||||
|
||||
t = system_tasks_max();
|
||||
assert_se(t > 0);
|
||||
assert_se(t < UINT64_MAX);
|
||||
|
||||
log_info("Max tasks: %" PRIu64, t);
|
||||
}
|
||||
|
||||
static void test_system_tasks_max_scale(void) {
|
||||
uint64_t t;
|
||||
|
||||
t = system_tasks_max();
|
||||
|
||||
assert_se(system_tasks_max_scale(0, 100) == 0);
|
||||
assert_se(system_tasks_max_scale(100, 100) == t);
|
||||
|
||||
assert_se(system_tasks_max_scale(0, 1) == 0);
|
||||
assert_se(system_tasks_max_scale(1, 1) == t);
|
||||
assert_se(system_tasks_max_scale(2, 1) == 2*t);
|
||||
|
||||
assert_se(system_tasks_max_scale(0, 2) == 0);
|
||||
assert_se(system_tasks_max_scale(1, 2) == t/2);
|
||||
assert_se(system_tasks_max_scale(2, 2) == t);
|
||||
assert_se(system_tasks_max_scale(3, 2) == (3*t)/2);
|
||||
assert_se(system_tasks_max_scale(4, 2) == t*2);
|
||||
|
||||
assert_se(system_tasks_max_scale(0, UINT32_MAX) == 0);
|
||||
assert_se(system_tasks_max_scale((UINT32_MAX-1)/2, UINT32_MAX-1) == t/2);
|
||||
assert_se(system_tasks_max_scale(UINT32_MAX, UINT32_MAX) == t);
|
||||
|
||||
/* overflow */
|
||||
|
||||
assert_se(system_tasks_max_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
@ -327,6 +363,8 @@ int main(int argc, char *argv[]) {
|
||||
test_raw_clone();
|
||||
test_physical_memory();
|
||||
test_physical_memory_scale();
|
||||
test_system_tasks_max();
|
||||
test_system_tasks_max_scale();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user