diff options
-rw-r--r-- | newlib/libc/include/sys/sched.h | 3 | ||||
-rw-r--r-- | winsup/cygwin/fork.cc | 37 | ||||
-rw-r--r-- | winsup/cygwin/local_includes/pinfo.h | 5 | ||||
-rw-r--r-- | winsup/cygwin/pinfo.cc | 1 | ||||
-rw-r--r-- | winsup/cygwin/release/3.6.0 | 3 | ||||
-rw-r--r-- | winsup/cygwin/sched.cc | 11 | ||||
-rw-r--r-- | winsup/cygwin/spawn.cc | 1 |
7 files changed, 52 insertions, 9 deletions
diff --git a/newlib/libc/include/sys/sched.h b/newlib/libc/include/sys/sched.h index 6977d3d..95509db 100644 --- a/newlib/libc/include/sys/sched.h +++ b/newlib/libc/include/sys/sched.h @@ -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 */ diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index 7d976e8..41a5337 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -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. */ diff --git a/winsup/cygwin/local_includes/pinfo.h b/winsup/cygwin/local_includes/pinfo.h index 03e0c4d..be5d530 100644 --- a/winsup/cygwin/local_includes/pinfo.h +++ b/winsup/cygwin/local_includes/pinfo.h @@ -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; diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 06c966f..fecf76e 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -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); } diff --git a/winsup/cygwin/release/3.6.0 b/winsup/cygwin/release/3.6.0 index 0795742..4e0726e 100644 --- a/winsup/cygwin/release/3.6.0 +++ b/winsup/cygwin/release/3.6.0 @@ -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. diff --git a/winsup/cygwin/sched.cc b/winsup/cygwin/sched.cc index ec62ea8..d75a340 100644 --- a/winsup/cygwin/sched.cc +++ b/winsup/cygwin/sched.cc @@ -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; } diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 7f9f2df..8016f08 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -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 ())) |