Corinna Vinschen wrote:
On Dec 16 08:48, Christian Franke wrote:
Christian Franke wrote:

A slighty changed version is attached. SCHED_IDLE now sets the lowest
prioritity.


Linux also provides (40) rt_priority and (41) policy. Adding these would
require to determine (or fake) fields (26) to (39) first :-)

This would also require to decide whether the values of (41) policy should
be Cygwin (SCHED_OTHER=3) or Linux (...=0) compatible...
Cygwin-compatible.  A tool actually using this feature should check
against SCHED_OTHER of the target system, not the value of a foreign
system or, worse, the constant 0.

--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -1348,8 +1348,8 @@ wait_sig (VOID *)
    /* GetTickCount() here is enough because GetTickCount() - t0 does
       not overflow until 49 days psss. Even if GetTickCount() overflows,
       GetTickCount() - t0 returns correct value, since underflow in
-     unsigned wraps correctly. Pending a signal for more than 49
-     days makes no sense. */
+     unsigned wraps correctly. Pending a signal for more thtn 49
+     days would be noncense. */
    DWORD t0 = GetTickCount ();
    for (;;)
      {
This hunk isn't supposed to be part of the patch, I guess...

Sorry!

From 46fa0f243d24c6df682ea6722509e890be6adf59 Mon Sep 17 00:00:00 2001
From: Christian Franke <christian.fra...@t-online.de>
Date: Mon, 16 Dec 2024 17:32:55 +0100
Subject: [PATCH] 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.fra...@t-online.de>
---
 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 37bdff84e..e0aebb648 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 6001a1636..fd10e40f1 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 6faf04937..31080d043 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 4e0726e8f..47c19a86b 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 d75a3404f..43b17357b 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);
-- 
2.45.1

Reply via email to