1 /* sched.cc: scheduler interface for Cygwin
3 Copyright 2001 Red Hat, Inc.
5 Written by Robert Collins <rbtcollins@hotmail.com>
7 This file is part of Cygwin.
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
30 /* Win32 priority to UNIX priority Mapping.
31 For now, I'm just following the spec: any range of priorities is ok.
32 There are probably many many issues with this...
34 We don't want process's going realtime. Well, they probably could, but the issues
35 with avoiding the priority values 17-22 and 27-30 (not supported before win2k)
36 make that inefficient.
37 However to complicate things most unixes use lower is better priorities.
39 So we map -14 to 15, and 15 to 1 via (16- ((n+16) >> 1))
40 we then map 1 to 15 to various process class and thread priority combinations
42 Then we need to look at the threads vi process priority. As win95 98 and NT 4
43 Don't support opening threads cross-process (unless a thread HANDLE is passed around)
44 for now, we'll just use the priority class.
46 The code and logic are present to calculate the priority for thread
47 , if a thread handle can be obtained. Alternatively, if the symbols wouldn't be
48 resolved until they are used
49 we could support this on windows 2000 and ME now, and just fall back to the
50 class only on pre win2000 machines.
52 Lastly, because we can't assume that the pid we're given are Windows pids, we can't
53 alter non-cygwin started programs.
59 /* max priority for policy */
61 sched_get_priority_max (int policy)
63 if (policy < 1 || policy > 3)
71 /* min priority for policy */
73 sched_get_priority_min (int policy)
75 if (policy < 1 || policy > 3)
83 /* Check a scheduler parameter struct for valid settings */
85 valid_sched_parameters(const struct sched_param *param)
87 if (param->sched_priority < -14 || param->sched_priority > 15)
95 /* get sched params for process
97 Note, I'm never returning EPERM,
98 Always ESRCH. This is by design (If cygwin ever looks at paranoid security
99 Walking the pid values is a known hole in some os's)
102 sched_getparam (pid_t pid, struct sched_param *param)
106 if (!param || pid < 0)
112 localpid = pid ? pid : getpid ();
126 process = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, p->dwProcessId);
132 Class = GetPriorityClass (process);
133 CloseHandle (process);
139 ThreadPriority = THREAD_PRIORITY_NORMAL;
141 /* calculate the unix priority.
143 FIXME: windows 2000 supports ABOVE_NORMAL and BELOW_NORMAL class's
144 So this logic just defaults those class factors to NORMAL in the calculations */
148 case IDLE_PRIORITY_CLASS:
149 switch (ThreadPriority)
151 case THREAD_PRIORITY_IDLE:
154 case THREAD_PRIORITY_LOWEST:
157 case THREAD_PRIORITY_BELOW_NORMAL:
160 case THREAD_PRIORITY_NORMAL:
163 case THREAD_PRIORITY_ABOVE_NORMAL:
166 case THREAD_PRIORITY_HIGHEST:
172 case HIGH_PRIORITY_CLASS:
173 switch (ThreadPriority)
175 case THREAD_PRIORITY_IDLE:
178 case THREAD_PRIORITY_LOWEST:
181 case THREAD_PRIORITY_BELOW_NORMAL:
184 case THREAD_PRIORITY_NORMAL:
187 case THREAD_PRIORITY_ABOVE_NORMAL:
190 case THREAD_PRIORITY_HIGHEST:
196 case NORMAL_PRIORITY_CLASS:
198 switch (ThreadPriority)
200 case THREAD_PRIORITY_IDLE:
203 case THREAD_PRIORITY_LOWEST:
206 case THREAD_PRIORITY_BELOW_NORMAL:
209 case THREAD_PRIORITY_NORMAL:
212 case THREAD_PRIORITY_ABOVE_NORMAL:
215 case THREAD_PRIORITY_HIGHEST:
223 /* reverse out winpri = (16- ((unixpri+16) >> 1)) */
225 winpri-16 = - (unixpri +16 ) >> 1
227 -(winpri-16) = unixpri +16 >> 1
228 (-(winpri-16)) << 1 = unixpri+16
229 ((-(winpri - 16)) << 1) - 16 = unixpri
232 param->sched_priority = ((-(winpri - 16)) << 1) - 16;
237 /* get the scheduler for pid
239 All process's on WIN32 run with SCHED_FIFO.
240 So we just give an answer.
241 (WIN32 uses a multi queue FIFO).
244 sched_getscheduler (pid_t pid)
252 /* get the time quantum for pid
254 We can't return -11, errno ENOSYS, because that implies that
255 sched_get_priority_max & min are also not supported (according to the spec)
256 so some spec-driven autoconf tests will likely assume they aren't present either
258 returning ESRCH might confuse some applications (if they assumed that when
259 rr_get_interval is called on pid 0 it always works).
261 If someone knows the time quanta for the various win32 platforms, then a
262 simple check for the os we're running on will finish this function
265 sched_rr_get_interval (pid_t pid, struct timespec *interval)
271 /* set the scheduling parameters */
273 sched_setparam (pid_t pid, const struct sched_param *param)
281 if (!param || pid < 0)
287 if (!valid_sched_parameters(param))
293 /* winpri = (16- ((unixpri+16) >> 1)) */
294 winpri = 16 - ((param->sched_priority + 16) >> 1);
296 /* calculate our desired priority class and thread priority */
299 Class = IDLE_PRIORITY_CLASS;
300 else if (winpri > 10)
301 Class = HIGH_PRIORITY_CLASS;
303 Class = NORMAL_PRIORITY_CLASS;
307 case IDLE_PRIORITY_CLASS:
311 ThreadPriority = THREAD_PRIORITY_IDLE;
314 ThreadPriority = THREAD_PRIORITY_LOWEST;
317 ThreadPriority = THREAD_PRIORITY_BELOW_NORMAL;
320 ThreadPriority = THREAD_PRIORITY_NORMAL;
323 ThreadPriority = THREAD_PRIORITY_ABOVE_NORMAL;
326 ThreadPriority = THREAD_PRIORITY_HIGHEST;
330 case NORMAL_PRIORITY_CLASS:
334 ThreadPriority = THREAD_PRIORITY_LOWEST;
337 ThreadPriority = THREAD_PRIORITY_BELOW_NORMAL;
340 ThreadPriority = THREAD_PRIORITY_NORMAL;
343 ThreadPriority = THREAD_PRIORITY_ABOVE_NORMAL;
346 ThreadPriority = THREAD_PRIORITY_HIGHEST;
350 case HIGH_PRIORITY_CLASS:
354 ThreadPriority = THREAD_PRIORITY_BELOW_NORMAL;
357 ThreadPriority = THREAD_PRIORITY_NORMAL;
360 ThreadPriority = THREAD_PRIORITY_ABOVE_NORMAL;
363 ThreadPriority = THREAD_PRIORITY_HIGHEST;
369 localpid = pid ? pid : getpid ();
377 set_errno (1); //ESRCH);
381 OpenProcess (PROCESS_SET_INFORMATION, FALSE, (DWORD) p->dwProcessId);
384 set_errno (2); //ESRCH);
387 if (!SetPriorityClass (process, Class))
389 CloseHandle (process);
393 CloseHandle (process);
398 /* we map -14 to 15, and 15 to 1 via (16- ((n+16) >> 1)). This lines up with the allowed
399 * valueswe return elsewhere in the sched* functions. We then map in groups of three to
400 * allowed thread priority's. The reason for dropping accuracy while still returning
401 * a wide range of values is to allow more flexible code in the future.
404 sched_set_thread_priority(HANDLE thread, int priority)
407 real_pri = 16 - ((priority + 16) >> 1);
408 if (real_pri <1 || real_pri > 15)
412 real_pri = THREAD_PRIORITY_LOWEST;
413 else if (real_pri < 7)
414 real_pri = THREAD_PRIORITY_BELOW_NORMAL;
415 else if (real_pri < 10)
416 real_pri = THREAD_PRIORITY_NORMAL;
417 else if (real_pri < 13)
418 real_pri = THREAD_PRIORITY_ABOVE_NORMAL;
420 real_pri = THREAD_PRIORITY_HIGHEST;
422 if (!SetThreadPriority(thread, real_pri))
423 /* invalid handle, no access are the only expected errors. */
428 /* set the scheduler */
430 sched_setscheduler (pid_t pid, int policy,
431 const struct sched_param *param)
433 /* on win32, you can't change the scheduler. Doh! */