[newlib-cygwin/main] Cygwin: /proc/<PID>/stat: set field (18) according to scheduling policy

Corinna Vinschen corinna@sourceware.org
Tue Dec 17 16:45:24 GMT 2024


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=efa5401ea998ee01d79c63449f51cd36df938f42

commit efa5401ea998ee01d79c63449f51cd36df938f42
Author:     Christian Franke <christian.franke@t-online.de>
AuthorDate: Mon Dec 16 17:32:55 2024 +0100
Commit:     Corinna Vinschen <corinna@vinschen.de>
CommitDate: Tue Dec 17 17:39:00 2024 +0100

    Cygwin: /proc/<PID>/stat: set field (18) according to scheduling policy
    
    If a realtime policy is selected, set the '(18) priority' field to the
    negated sched_priority minus one.  If SCHED_IDLE is selected, set it to
    the lowest priority 39.  Also set '(19) nice' to the originally requested
    nice value.  Ensure consistence with the current Windows priority in all
    cases.  Move the sched_priority from/to Windows priority mapping from
    sched_get/setparam() to new functions in miscfuncs.cc.
    
    Signed-off-by: Christian Franke <christian.franke@t-online.de>

Diff:
---
 winsup/cygwin/fhandler/process.cc        | 26 +++++++++++++--
 winsup/cygwin/local_includes/miscfuncs.h |  2 ++
 winsup/cygwin/miscfuncs.cc               | 56 ++++++++++++++++++++++++++++++--
 winsup/cygwin/release/3.6.0              |  5 +++
 winsup/cygwin/sched.cc                   | 40 +++--------------------
 5 files changed, 88 insertions(+), 41 deletions(-)

diff --git a/winsup/cygwin/fhandler/process.cc b/winsup/cygwin/fhandler/process.cc
index 37bdff84e322..e0aebb64892a 100644
--- a/winsup/cygwin/fhandler/process.cc
+++ b/winsup/cygwin/fhandler/process.cc
@@ -1098,7 +1098,6 @@ format_process_stat (void *data, char *&destbuf)
   unsigned long fault_count = 0UL,
 		vmsize = 0UL, vmrss = 0UL, vmmaxrss = 0UL;
   uint64_t utime = 0ULL, stime = 0ULL, start_time = 0ULL;
-  int nice = 0;
 /* ctty maj is 31:16, min is 15:0; tty_nr s/b maj 15:8, min 31:20, 7:0;
    maj is 31:16 >> 16 & fff << 8; min is 15:0 >> 8 & ff << 20 | & ff */
   int tty_nr = 0;
@@ -1131,6 +1130,8 @@ format_process_stat (void *data, char *&destbuf)
   else
     state = get_process_state (p->dwProcessId);
 
+  int nice = 0, prio = 0;
+
   NTSTATUS status;
   HANDLE hProcess;
   VM_COUNTERS vmc = { 0 };
@@ -1168,7 +1169,26 @@ format_process_stat (void *data, char *&destbuf)
       if (!NT_SUCCESS (status))
 	debug_printf ("NtQueryInformationProcess(ProcessQuotaLimits): "
 		      "status %y", status);
-      nice = winprio_to_nice (GetPriorityClass (hProcess));
+
+      nice = p->nice;
+      DWORD winprio = GetPriorityClass (hProcess);
+      if (p->sched_policy == SCHED_FIFO || p->sched_policy == SCHED_RR)
+	/* Linux proc_pid_stat(5): (18) priority - For processes running a
+	   real-time scheduling policy ..., this is the negated scheduling
+	   priority, minus one. */
+	prio = - winprio_to_schedprio (winprio) - 1; /* -33(high)...-2(low) */
+      else if (p->sched_policy == SCHED_IDLE)
+	/* Return the lowest priority unless no longer consistent. */
+	prio = NZERO + (winprio == IDLE_PRIORITY_CLASS ? NZERO - 1 :
+			winprio_to_nice (winprio));
+      else
+	{
+	  /* Use originally requested nice value unless no longer consistent. */
+	  bool batch = (p->sched_policy == SCHED_BATCH);
+	  if (winprio != nice_to_winprio (nice, batch))
+	    nice = winprio_to_nice (winprio, batch);
+	  prio = NZERO + nice; /* 0(high)...39(low) */
+	}
       CloseHandle (hProcess);
     }
   status = NtQuerySystemInformation (SystemTimeOfDayInformation,
@@ -1201,7 +1221,7 @@ format_process_stat (void *data, char *&destbuf)
 			  p->ppid, p->pgid, p->sid, tty_nr,
 			  -1, 0, fault_count, fault_count, 0, 0,
 			  utime, stime, utime, stime,
-			  NZERO + nice, nice, 0, 0,
+			  prio, nice, 0, 0,
 			  start_time,
 			  vmsize, vmrss, vmmaxrss
 			  );
diff --git a/winsup/cygwin/local_includes/miscfuncs.h b/winsup/cygwin/local_includes/miscfuncs.h
index 6001a1636119..fd10e40f133a 100644
--- a/winsup/cygwin/local_includes/miscfuncs.h
+++ b/winsup/cygwin/local_includes/miscfuncs.h
@@ -46,6 +46,8 @@ is_alt_numpad_event (PINPUT_RECORD pirec)
 
 int winprio_to_nice (DWORD prio, bool batch = false);
 DWORD nice_to_winprio (int &nice, bool batch = false);
+int winprio_to_schedprio (DWORD prio);
+DWORD schedprio_to_winprio (int schedprio);
 bool set_and_check_winprio (HANDLE proc, DWORD prio, bool set = true);
 
 bool create_pipe (PHANDLE, PHANDLE, LPSECURITY_ATTRIBUTES, DWORD);
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index 6faf04937afb..31080d043ab1 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -104,7 +104,7 @@ yield ()
 }
 
 /*
-   Mapping of nice value from/to Windows priority
+   Mapping of nice value or sched_priority from/to Windows priority
    ('batch' is used for SCHED_BATCH policy).
 
     nice_to_winprio()                                       winprio_to_nice()
@@ -115,6 +115,14 @@ yield ()
   -12...-5    -13..-19    3    ABOVE_NORMAL_PRIORITY_CLASS    -8      -16
   -13..-19         -20    4    HIGH_PRIORITY_CLASS           -16      -20
        -20           -    5    REALTIME_PRIORITY_CLASS       -20      -20
+
+   schedprio_to_winprio()                               winprio_to_schedprio()
+    1....6                0    IDLE_PRIORITY_CLASS             3
+    7...12                1    BELOW_NORMAL_PRIORITY_CLASS     9
+   13...18                2    NORMAL_PRIORITY_CLASS          15
+   19...24                3    ABOVE_NORMAL_PRIORITY_CLASS    21
+   25...30                4    HIGH_PRIORITY_CLASS            27
+   31...32                5    REALTIME_PRIORITY_CLASS        32
 */
 
 /* *_PRIORITY_CLASS -> 0...5 */
@@ -167,9 +175,25 @@ nice_to_winprio_impl (int nice, bool batch = false)
   return level_to_winprio (level);
 }
 
+/* *_PRIORITY_CLASS -> sched_priority */
+constexpr int
+winprio_to_schedprio_impl (DWORD prio)
+{
+  int level = winprio_to_level (prio);
+  return (level < 5 ? 3 + level * 6 : 32);
+}
+
+/* sched_priority -> *_PRIORITY_CLASS */
+constexpr DWORD
+schedprio_to_winprio_impl (int schedprio)
+{
+  int level = (schedprio <= 1 ? 0 : (schedprio < 32 ? (schedprio - 1) / 6 : 5));
+  return level_to_winprio (level);
+}
+
 /* Check consistency at compile time. */
 constexpr bool
-check_nice_winprio_mapping ()
+check_nice_schedprio_winprio_mapping ()
 {
   for (int nice = -NZERO; nice < NZERO; nice++)
     for (int batch = 0; batch <= 1; batch++) {
@@ -179,16 +203,28 @@ check_nice_winprio_mapping ()
       if (prio != prio2)
 	return false;
     }
+  for (int schedprio = 1; schedprio <= 32; schedprio++)
+    {
+      DWORD prio = schedprio_to_winprio_impl (schedprio);
+      int schedprio2 = winprio_to_schedprio_impl (prio);
+      DWORD prio2 = schedprio_to_winprio_impl (schedprio2);
+      if (prio != prio2)
+	return false;
+    }
   return true;
 }
 
-static_assert (check_nice_winprio_mapping());
+static_assert (check_nice_schedprio_winprio_mapping());
 static_assert (nice_to_winprio_impl(NZERO-1, false) == IDLE_PRIORITY_CLASS);
 static_assert (nice_to_winprio_impl(0, true) == BELOW_NORMAL_PRIORITY_CLASS);
 static_assert (winprio_to_nice_impl(BELOW_NORMAL_PRIORITY_CLASS, true) == 0);
 static_assert (nice_to_winprio_impl(0, false) == NORMAL_PRIORITY_CLASS);
 static_assert (winprio_to_nice_impl(NORMAL_PRIORITY_CLASS, false) == 0);
 static_assert (nice_to_winprio_impl(-NZERO, false) == REALTIME_PRIORITY_CLASS);
+static_assert (schedprio_to_winprio_impl(1) == IDLE_PRIORITY_CLASS);
+static_assert (schedprio_to_winprio_impl(15) == NORMAL_PRIORITY_CLASS);
+static_assert (winprio_to_schedprio_impl(NORMAL_PRIORITY_CLASS) == 15);
+static_assert (schedprio_to_winprio_impl(32) == REALTIME_PRIORITY_CLASS);
 
 /* Get a default value for the nice factor. */
 int
@@ -210,6 +246,20 @@ nice_to_winprio (int &nice, bool batch /* = false */)
   return nice_to_winprio_impl (nice, batch);
 }
 
+/* Get a default sched_priority from a Win32 priority. */
+int
+winprio_to_schedprio (DWORD prio)
+{
+  return winprio_to_schedprio_impl (prio);
+}
+
+/* Get a Win32 priority matching the sched_priority. */
+DWORD
+schedprio_to_winprio (int schedprio)
+{
+  return schedprio_to_winprio_impl (schedprio);
+}
+
 /* Set Win32 priority or return false on failure.  Also return
    false and revert to the original priority if a different (lower)
    priority is set instead.  Always revert to original priority if
diff --git a/winsup/cygwin/release/3.6.0 b/winsup/cygwin/release/3.6.0
index 4e0726e8f204..47c19a86bac3 100644
--- a/winsup/cygwin/release/3.6.0
+++ b/winsup/cygwin/release/3.6.0
@@ -69,3 +69,8 @@ What changed:
   each child process created with fork(2).
   Note: Windows does not offer alternative scheduling policies so
   this could only emulate API behavior.
+
+- If SCHED_FIFO or SCHED_RR is selected, the /proc/<PID>/stat field
+  '(18) priority' is now set to the negated sched_policy minus one.
+  If SCHED_IDLE is selected, this field is set to 39.  The '(19) nice'
+  field is now set to the originally requested nice value.
diff --git a/winsup/cygwin/sched.cc b/winsup/cygwin/sched.cc
index d75a3404f5d9..43b17357baa2 100644
--- a/winsup/cygwin/sched.cc
+++ b/winsup/cygwin/sched.cc
@@ -120,29 +120,7 @@ sched_getparam (pid_t pid, struct sched_param *param)
       return -1;
     }
   /* calculate the unix priority. */
-  switch (pclass)
-    {
-    case IDLE_PRIORITY_CLASS:
-      param->sched_priority = 3;
-      break;
-    case BELOW_NORMAL_PRIORITY_CLASS:
-      param->sched_priority = 9;
-      break;
-    case NORMAL_PRIORITY_CLASS:
-    default:
-      param->sched_priority = 15;
-      break;
-    case ABOVE_NORMAL_PRIORITY_CLASS:
-      param->sched_priority = 21;
-      break;
-    case HIGH_PRIORITY_CLASS:
-      param->sched_priority = 27;
-      break;
-    case REALTIME_PRIORITY_CLASS:
-      param->sched_priority = 32;
-      break;
-    }
-
+  param->sched_priority = winprio_to_schedprio (pclass);
   return 0;
 }
 
@@ -244,18 +222,10 @@ sched_setparam_pinfo (pinfo & p, const struct sched_param *param)
   else if (p->sched_policy == SCHED_IDLE && pri == 0)
     /* Idle policy, ignore the nice value. */
     pclass = IDLE_PRIORITY_CLASS;
-  else if (1 <= pri && pri <= 6)
-    pclass = IDLE_PRIORITY_CLASS;
-  else if (pri <= 12)
-    pclass = BELOW_NORMAL_PRIORITY_CLASS;
-  else if (pri <= 18)
-    pclass = NORMAL_PRIORITY_CLASS;
-  else if (pri <= 24)
-    pclass = ABOVE_NORMAL_PRIORITY_CLASS;
-  else if (pri <= 30)
-    pclass = HIGH_PRIORITY_CLASS;
-  else if (pri <= 32)
-    pclass = REALTIME_PRIORITY_CLASS;
+  else if ((p->sched_policy == SCHED_FIFO || p->sched_policy == SCHED_RR)
+           && valid_sched_parameters (param))
+    /* Realtime policy, apply requested priority. */
+    pclass = schedprio_to_winprio (param->sched_priority);
   else
     {
       set_errno (EINVAL);


More information about the Cygwin-cvs mailing list