Cygwin: sched_setscheduler: accept SCHED_RESET_ON_FORK flag

Add SCHED_RESET_ON_FORK to <sys/sched.h>.  If this flag is set, SCHED_FIFO
and SCHED_RR are reset to SCHED_OTHER and negative nice values are reset to
zero in each child process created with fork(2).

Signed-off-by: Christian Franke <christian.franke@t-online.de>
This commit is contained in:
Christian Franke 2024-12-11 12:48:58 +01:00 committed by Corinna Vinschen
parent a31a6fe5dd
commit 06952f41ff
7 changed files with 52 additions and 9 deletions

View file

@ -45,6 +45,9 @@ extern "C" {
#if __GNU_VISIBLE
#define SCHED_IDLE 5
#define SCHED_BATCH 6
/* Flag to drop realtime policies and negative nice values on fork(). */
#define SCHED_RESET_ON_FORK 0x40000000
#endif
/* Scheduling Parameters */

View file

@ -212,7 +212,37 @@ frok::parent (volatile char * volatile stack_here)
bool fix_impersonation = false;
pinfo child;
int c_flags = GetPriorityClass (GetCurrentProcess ());
/* Inherit scheduling parameters by default. */
int child_nice = myself->nice;
int child_sched_policy = myself->sched_policy;
int c_flags = 0;
/* Handle SCHED_RESET_ON_FORK flag. */
if (myself->sched_reset_on_fork)
{
bool batch = (myself->sched_policy == SCHED_BATCH);
bool idle = (myself->sched_policy == SCHED_IDLE);
bool set_prio = false;
/* Reset negative nice values to zero. */
if (myself->nice < 0)
{
child_nice = 0;
set_prio = !idle;
}
/* Reset realtime policies to SCHED_OTHER. */
if (!(myself->sched_policy == SCHED_OTHER || batch || idle))
{
child_sched_policy = SCHED_OTHER;
set_prio = true;
}
if (set_prio)
c_flags = nice_to_winprio (child_nice, batch);
}
/* Always request a priority because otherwise anything above
NORMAL_PRIORITY_CLASS would not be inherited. */
if (!c_flags)
c_flags = GetPriorityClass (GetCurrentProcess ());
debug_printf ("priority class %d", c_flags);
/* Per MSDN, this must be specified even if lpEnvironment is set to NULL,
otherwise UNICODE characters in the parent environment are not copied
@ -401,8 +431,9 @@ frok::parent (volatile char * volatile stack_here)
goto cleanup;
}
child->nice = myself->nice;
child->sched_policy = myself->sched_policy;
child->nice = child_nice;
child->sched_policy = child_sched_policy;
child->sched_reset_on_fork = false;
/* Initialize things that are done later in dll_crt0_1 that aren't done
for the forkee. */

View file

@ -93,8 +93,9 @@ public:
struct rusage rusage_self;
struct rusage rusage_children;
int nice; /* nice value for SCHED_OTHER. */
int sched_policy; /* SCHED_OTHER, SCHED_FIFO or SCHED_RR. */
int nice; /* nice value for SCHED_OTHER and SCHED_BATCH. */
int sched_policy; /* SCHED_OTHER/BATCH/IDLE/FIFO/RR */
bool sched_reset_on_fork; /* true if SCHED_RESET_ON_FORK flag was set. */
/* Non-zero if process was stopped by a signal. */
char stopsig;

View file

@ -103,6 +103,7 @@ pinfo_init (char **envp, int envc)
environ_init (NULL, 0); /* call after myself has been set up */
myself->nice = winprio_to_nice (GetPriorityClass (GetCurrentProcess ()));
myself->sched_policy = SCHED_OTHER;
myself->sched_reset_on_fork = false;
myself->ppid = 1; /* always set last */
debug_printf ("Set nice to %d", myself->nice);
}

View file

@ -64,5 +64,8 @@ What changed:
priority is set to IDLE_PRIORITY_CLASS. If SCHED_FIFO or SCHED_RR is
selected, the nice value is preserved and the Windows priority is set
according to the realtime priority.
If the SCHED_RESET_ON_FORK flag is set, SCHED_FIFO and SCHED_RR are
reset to SCHED_OTHER and negative nice values are reset to zero in
each child process created with fork(2).
Note: Windows does not offer alternative scheduling policies so
this could only emulate API behavior.

View file

@ -162,7 +162,7 @@ sched_getscheduler (pid_t pid)
set_errno (ESRCH);
return -1;
}
return p->sched_policy;
return p->sched_policy | (p->sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0);
}
/* get the time quantum for pid */
@ -425,9 +425,11 @@ int
sched_setscheduler (pid_t pid, int policy,
const struct sched_param *param)
{
int new_policy = policy & ~SCHED_RESET_ON_FORK;
if (!(pid >= 0 && param &&
(((policy == SCHED_OTHER || policy == SCHED_BATCH || policy == SCHED_IDLE)
&& param->sched_priority == 0) || ((policy == SCHED_FIFO || policy == SCHED_RR)
(((new_policy == SCHED_OTHER || new_policy == SCHED_BATCH
|| new_policy == SCHED_IDLE) && param->sched_priority == 0)
|| ((new_policy == SCHED_FIFO || new_policy == SCHED_RR)
&& valid_sched_parameters(param)))))
{
set_errno (EINVAL);
@ -442,13 +444,14 @@ sched_setscheduler (pid_t pid, int policy,
}
int prev_policy = p->sched_policy;
p->sched_policy = policy;
p->sched_policy = new_policy;
if (sched_setparam_pinfo (p, param))
{
p->sched_policy = prev_policy;
return -1;
}
p->sched_reset_on_fork = !!(policy & SCHED_RESET_ON_FORK);
return 0;
}

View file

@ -800,6 +800,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
child->start_time = time (NULL); /* Register child's starting time. */
child->nice = myself->nice;
child->sched_policy = myself->sched_policy;
child->sched_reset_on_fork = false;
postfork (child);
if (mode != _P_DETACH
&& (!child.remember () || !child.attach ()))