Skip to content

Commit efa5401

Browse files
chrfrankegithub-cygwin
authored andcommitted
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 <[email protected]>
1 parent 14dda1f commit efa5401

File tree

5 files changed

+88
-41
lines changed

5 files changed

+88
-41
lines changed

winsup/cygwin/fhandler/process.cc

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,6 @@ format_process_stat (void *data, char *&destbuf)
10981098
unsigned long fault_count = 0UL,
10991099
vmsize = 0UL, vmrss = 0UL, vmmaxrss = 0UL;
11001100
uint64_t utime = 0ULL, stime = 0ULL, start_time = 0ULL;
1101-
int nice = 0;
11021101
/* ctty maj is 31:16, min is 15:0; tty_nr s/b maj 15:8, min 31:20, 7:0;
11031102
maj is 31:16 >> 16 & fff << 8; min is 15:0 >> 8 & ff << 20 | & ff */
11041103
int tty_nr = 0;
@@ -1131,6 +1130,8 @@ format_process_stat (void *data, char *&destbuf)
11311130
else
11321131
state = get_process_state (p->dwProcessId);
11331132

1133+
int nice = 0, prio = 0;
1134+
11341135
NTSTATUS status;
11351136
HANDLE hProcess;
11361137
VM_COUNTERS vmc = { 0 };
@@ -1168,7 +1169,26 @@ format_process_stat (void *data, char *&destbuf)
11681169
if (!NT_SUCCESS (status))
11691170
debug_printf ("NtQueryInformationProcess(ProcessQuotaLimits): "
11701171
"status %y", status);
1171-
nice = winprio_to_nice (GetPriorityClass (hProcess));
1172+
1173+
nice = p->nice;
1174+
DWORD winprio = GetPriorityClass (hProcess);
1175+
if (p->sched_policy == SCHED_FIFO || p->sched_policy == SCHED_RR)
1176+
/* Linux proc_pid_stat(5): (18) priority - For processes running a
1177+
real-time scheduling policy ..., this is the negated scheduling
1178+
priority, minus one. */
1179+
prio = - winprio_to_schedprio (winprio) - 1; /* -33(high)...-2(low) */
1180+
else if (p->sched_policy == SCHED_IDLE)
1181+
/* Return the lowest priority unless no longer consistent. */
1182+
prio = NZERO + (winprio == IDLE_PRIORITY_CLASS ? NZERO - 1 :
1183+
winprio_to_nice (winprio));
1184+
else
1185+
{
1186+
/* Use originally requested nice value unless no longer consistent. */
1187+
bool batch = (p->sched_policy == SCHED_BATCH);
1188+
if (winprio != nice_to_winprio (nice, batch))
1189+
nice = winprio_to_nice (winprio, batch);
1190+
prio = NZERO + nice; /* 0(high)...39(low) */
1191+
}
11721192
CloseHandle (hProcess);
11731193
}
11741194
status = NtQuerySystemInformation (SystemTimeOfDayInformation,
@@ -1201,7 +1221,7 @@ format_process_stat (void *data, char *&destbuf)
12011221
p->ppid, p->pgid, p->sid, tty_nr,
12021222
-1, 0, fault_count, fault_count, 0, 0,
12031223
utime, stime, utime, stime,
1204-
NZERO + nice, nice, 0, 0,
1224+
prio, nice, 0, 0,
12051225
start_time,
12061226
vmsize, vmrss, vmmaxrss
12071227
);

winsup/cygwin/local_includes/miscfuncs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ is_alt_numpad_event (PINPUT_RECORD pirec)
4646

4747
int winprio_to_nice (DWORD prio, bool batch = false);
4848
DWORD nice_to_winprio (int &nice, bool batch = false);
49+
int winprio_to_schedprio (DWORD prio);
50+
DWORD schedprio_to_winprio (int schedprio);
4951
bool set_and_check_winprio (HANDLE proc, DWORD prio, bool set = true);
5052

5153
bool create_pipe (PHANDLE, PHANDLE, LPSECURITY_ATTRIBUTES, DWORD);

winsup/cygwin/miscfuncs.cc

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ yield ()
104104
}
105105

106106
/*
107-
Mapping of nice value from/to Windows priority
107+
Mapping of nice value or sched_priority from/to Windows priority
108108
('batch' is used for SCHED_BATCH policy).
109109
110110
nice_to_winprio() winprio_to_nice()
@@ -115,6 +115,14 @@ yield ()
115115
-12...-5 -13..-19 3 ABOVE_NORMAL_PRIORITY_CLASS -8 -16
116116
-13..-19 -20 4 HIGH_PRIORITY_CLASS -16 -20
117117
-20 - 5 REALTIME_PRIORITY_CLASS -20 -20
118+
119+
schedprio_to_winprio() winprio_to_schedprio()
120+
1....6 0 IDLE_PRIORITY_CLASS 3
121+
7...12 1 BELOW_NORMAL_PRIORITY_CLASS 9
122+
13...18 2 NORMAL_PRIORITY_CLASS 15
123+
19...24 3 ABOVE_NORMAL_PRIORITY_CLASS 21
124+
25...30 4 HIGH_PRIORITY_CLASS 27
125+
31...32 5 REALTIME_PRIORITY_CLASS 32
118126
*/
119127

120128
/* *_PRIORITY_CLASS -> 0...5 */
@@ -167,9 +175,25 @@ nice_to_winprio_impl (int nice, bool batch = false)
167175
return level_to_winprio (level);
168176
}
169177

178+
/* *_PRIORITY_CLASS -> sched_priority */
179+
constexpr int
180+
winprio_to_schedprio_impl (DWORD prio)
181+
{
182+
int level = winprio_to_level (prio);
183+
return (level < 5 ? 3 + level * 6 : 32);
184+
}
185+
186+
/* sched_priority -> *_PRIORITY_CLASS */
187+
constexpr DWORD
188+
schedprio_to_winprio_impl (int schedprio)
189+
{
190+
int level = (schedprio <= 1 ? 0 : (schedprio < 32 ? (schedprio - 1) / 6 : 5));
191+
return level_to_winprio (level);
192+
}
193+
170194
/* Check consistency at compile time. */
171195
constexpr bool
172-
check_nice_winprio_mapping ()
196+
check_nice_schedprio_winprio_mapping ()
173197
{
174198
for (int nice = -NZERO; nice < NZERO; nice++)
175199
for (int batch = 0; batch <= 1; batch++) {
@@ -179,16 +203,28 @@ check_nice_winprio_mapping ()
179203
if (prio != prio2)
180204
return false;
181205
}
206+
for (int schedprio = 1; schedprio <= 32; schedprio++)
207+
{
208+
DWORD prio = schedprio_to_winprio_impl (schedprio);
209+
int schedprio2 = winprio_to_schedprio_impl (prio);
210+
DWORD prio2 = schedprio_to_winprio_impl (schedprio2);
211+
if (prio != prio2)
212+
return false;
213+
}
182214
return true;
183215
}
184216

185-
static_assert (check_nice_winprio_mapping());
217+
static_assert (check_nice_schedprio_winprio_mapping());
186218
static_assert (nice_to_winprio_impl(NZERO-1, false) == IDLE_PRIORITY_CLASS);
187219
static_assert (nice_to_winprio_impl(0, true) == BELOW_NORMAL_PRIORITY_CLASS);
188220
static_assert (winprio_to_nice_impl(BELOW_NORMAL_PRIORITY_CLASS, true) == 0);
189221
static_assert (nice_to_winprio_impl(0, false) == NORMAL_PRIORITY_CLASS);
190222
static_assert (winprio_to_nice_impl(NORMAL_PRIORITY_CLASS, false) == 0);
191223
static_assert (nice_to_winprio_impl(-NZERO, false) == REALTIME_PRIORITY_CLASS);
224+
static_assert (schedprio_to_winprio_impl(1) == IDLE_PRIORITY_CLASS);
225+
static_assert (schedprio_to_winprio_impl(15) == NORMAL_PRIORITY_CLASS);
226+
static_assert (winprio_to_schedprio_impl(NORMAL_PRIORITY_CLASS) == 15);
227+
static_assert (schedprio_to_winprio_impl(32) == REALTIME_PRIORITY_CLASS);
192228

193229
/* Get a default value for the nice factor. */
194230
int
@@ -210,6 +246,20 @@ nice_to_winprio (int &nice, bool batch /* = false */)
210246
return nice_to_winprio_impl (nice, batch);
211247
}
212248

249+
/* Get a default sched_priority from a Win32 priority. */
250+
int
251+
winprio_to_schedprio (DWORD prio)
252+
{
253+
return winprio_to_schedprio_impl (prio);
254+
}
255+
256+
/* Get a Win32 priority matching the sched_priority. */
257+
DWORD
258+
schedprio_to_winprio (int schedprio)
259+
{
260+
return schedprio_to_winprio_impl (schedprio);
261+
}
262+
213263
/* Set Win32 priority or return false on failure. Also return
214264
false and revert to the original priority if a different (lower)
215265
priority is set instead. Always revert to original priority if

winsup/cygwin/release/3.6.0

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,8 @@ What changed:
6969
each child process created with fork(2).
7070
Note: Windows does not offer alternative scheduling policies so
7171
this could only emulate API behavior.
72+
73+
- If SCHED_FIFO or SCHED_RR is selected, the /proc/<PID>/stat field
74+
'(18) priority' is now set to the negated sched_policy minus one.
75+
If SCHED_IDLE is selected, this field is set to 39. The '(19) nice'
76+
field is now set to the originally requested nice value.

winsup/cygwin/sched.cc

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -120,29 +120,7 @@ sched_getparam (pid_t pid, struct sched_param *param)
120120
return -1;
121121
}
122122
/* calculate the unix priority. */
123-
switch (pclass)
124-
{
125-
case IDLE_PRIORITY_CLASS:
126-
param->sched_priority = 3;
127-
break;
128-
case BELOW_NORMAL_PRIORITY_CLASS:
129-
param->sched_priority = 9;
130-
break;
131-
case NORMAL_PRIORITY_CLASS:
132-
default:
133-
param->sched_priority = 15;
134-
break;
135-
case ABOVE_NORMAL_PRIORITY_CLASS:
136-
param->sched_priority = 21;
137-
break;
138-
case HIGH_PRIORITY_CLASS:
139-
param->sched_priority = 27;
140-
break;
141-
case REALTIME_PRIORITY_CLASS:
142-
param->sched_priority = 32;
143-
break;
144-
}
145-
123+
param->sched_priority = winprio_to_schedprio (pclass);
146124
return 0;
147125
}
148126

@@ -244,18 +222,10 @@ sched_setparam_pinfo (pinfo & p, const struct sched_param *param)
244222
else if (p->sched_policy == SCHED_IDLE && pri == 0)
245223
/* Idle policy, ignore the nice value. */
246224
pclass = IDLE_PRIORITY_CLASS;
247-
else if (1 <= pri && pri <= 6)
248-
pclass = IDLE_PRIORITY_CLASS;
249-
else if (pri <= 12)
250-
pclass = BELOW_NORMAL_PRIORITY_CLASS;
251-
else if (pri <= 18)
252-
pclass = NORMAL_PRIORITY_CLASS;
253-
else if (pri <= 24)
254-
pclass = ABOVE_NORMAL_PRIORITY_CLASS;
255-
else if (pri <= 30)
256-
pclass = HIGH_PRIORITY_CLASS;
257-
else if (pri <= 32)
258-
pclass = REALTIME_PRIORITY_CLASS;
225+
else if ((p->sched_policy == SCHED_FIFO || p->sched_policy == SCHED_RR)
226+
&& valid_sched_parameters (param))
227+
/* Realtime policy, apply requested priority. */
228+
pclass = schedprio_to_winprio (param->sched_priority);
259229
else
260230
{
261231
set_errno (EINVAL);

0 commit comments

Comments
 (0)