aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Franke <christian.franke@t-online.de>2024-12-11 12:48:58 +0100
committerCorinna Vinschen <corinna@vinschen.de>2024-12-12 10:32:00 +0100
commit06952f41ff4897c615fa838c5daf571aacb55d0f (patch)
tree572a5dbe1ae3e194b34b6c44406abde0634a8e77
parenta31a6fe5dd36616ac4ccbb62958072413265e563 (diff)
downloadnewlib-06952f41ff4897c615fa838c5daf571aacb55d0f.zip
newlib-06952f41ff4897c615fa838c5daf571aacb55d0f.tar.gz
newlib-06952f41ff4897c615fa838c5daf571aacb55d0f.tar.bz2
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>
-rw-r--r--newlib/libc/include/sys/sched.h3
-rw-r--r--winsup/cygwin/fork.cc37
-rw-r--r--winsup/cygwin/local_includes/pinfo.h5
-rw-r--r--winsup/cygwin/pinfo.cc1
-rw-r--r--winsup/cygwin/release/3.6.03
-rw-r--r--winsup/cygwin/sched.cc11
-rw-r--r--winsup/cygwin/spawn.cc1
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 ()))