Christian Franke wrote:
Christian Franke wrote:
Corinna Vinschen wrote:
Hi Christian,

On Dec  6 17:52, Christian Franke wrote:
A first attempt to add SCHED_BATCH.

Still TODO:
- Add SCHED_IDLE/BATCH to winsup/doc/posix.xml
- Provide correct values in (18) and (19) of /proc/PID/stat for SCHED_BATCH.
- Provide correct value in (18) of /proc/PID/stat for SCHED_FIFO/RR.

--
Regards,
Christian

 From 0822917252fdade3edc240b4fbfd3c0f47ef1deb Mon Sep 17 00:00:00 2001
From: Christian Franke <christian.fra...@t-online.de>
Date: Fri, 6 Dec 2024 17:32:29 +0100
Subject: [PATCH] Cygwin: sched_setscheduler: accept SCHED_BATCH

Add SCHED_BATCH to <sys/sched.h>.  SCHED_BATCH is similar to SCHED_OTHER, except that the nice value is mapped to a one step lower Windows priority. Rework the mapping functions to ease the addition of this functionality.

Signed-off-by: Christian Franke <christian.fra...@t-online.de>
---
  newlib/libc/include/sys/sched.h          |   8 ++
  winsup/cygwin/local_includes/miscfuncs.h |   4 +-
  winsup/cygwin/miscfuncs.cc               | 155 +++++++++++++----------
  winsup/cygwin/release/3.6.0              |  11 +-
  winsup/cygwin/sched.cc                   |  15 ++-
  winsup/cygwin/syscalls.cc                |  20 +--
  6 files changed, 129 insertions(+), 84 deletions(-)

diff --git a/newlib/libc/include/sys/sched.h b/newlib/libc/include/sys/sched.h
index c96355c24..265215211 100644
--- a/newlib/libc/include/sys/sched.h
+++ b/newlib/libc/include/sys/sched.h
@@ -38,6 +38,14 @@ extern "C" {
  #define SCHED_FIFO     1
  #define SCHED_RR       2
  +#if __GNU_VISIBLE
+#if defined(__CYGWIN__)
+#define SCHED_BATCH    0
+#else
+#define SCHED_BATCH    3
+#endif
+#endif
I would prefer that SCHED_BATCH gets its own, single value.
There's no good reason to add another ifdef for that.  Why
not just #define SCHED_BATCH 6?

The idea was to keep the non-Cygwin value in sync with Linux.
https://github.com/torvalds/linux/blob/fac04ef/include/uapi/linux/sched.h#L111
Of course we could drop this idea and use 6.


Attached, no other changes.



The next (and possibly last) SCHED_* feature addition on top of the SCHED_BATCH (6) patch.

From 56e406c5ab270b2ef3ca31cb8fabfaca927f4d29 Mon Sep 17 00:00:00 2001
From: Christian Franke <christian.fra...@t-online.de>
Date: Tue, 10 Dec 2024 15:09:42 +0100
Subject: [PATCH] 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.fra...@t-online.de>
---
 newlib/libc/include/sys/sched.h      |  3 +++
 winsup/cygwin/fork.cc                | 33 ++++++++++++++++++++++++++++
 winsup/cygwin/local_includes/pinfo.h |  5 +++--
 winsup/cygwin/pinfo.cc               |  1 +
 winsup/cygwin/release/3.6.0          |  3 +++
 winsup/cygwin/sched.cc               | 11 ++++++----
 winsup/cygwin/spawn.cc               |  1 +
 7 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/newlib/libc/include/sys/sched.h b/newlib/libc/include/sys/sched.h
index 6977d3d4a..95509dbf0 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 7d976e882..925f988bf 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -404,6 +404,39 @@ frok::parent (volatile char * volatile stack_here)
   child->nice = myself->nice;
   child->sched_policy = myself->sched_policy;
 
+  /* 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;
+       }
+      /* Adjust Windows priority if required. */
+      if (set_prio)
+       {
+         HANDLE proc = OpenProcess(PROCESS_SET_INFORMATION |
+                                   PROCESS_QUERY_LIMITED_INFORMATION,
+                                   FALSE, child->dwProcessId);
+         if (proc)
+           {
+             set_and_check_winprio(proc, nice_to_winprio(child->nice, batch));
+             CloseHandle(proc);
+           }
+       }
+    }
+  child->sched_reset_on_fork = false;
+
   /* Initialize things that are done later in dll_crt0_1 that aren't done
      for the forkee.  */
   wcscpy (child->progname, myself->progname);
diff --git a/winsup/cygwin/local_includes/pinfo.h 
b/winsup/cygwin/local_includes/pinfo.h
index 03e0c4d60..be5d53021 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 06c966f1e..fecf76eb6 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 11f745b23..d35aa3036 100644
--- a/winsup/cygwin/release/3.6.0
+++ b/winsup/cygwin/release/3.6.0
@@ -61,5 +61,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 ec62ea83c..d75a3404f 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 7f9f2df64..8016f0864 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 ()))
-- 
2.45.1

Reply via email to