mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-22 00:38:06 +08:00
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.franke@t-online.de>
This commit is contained in:
parent
a0527e3786
commit
a31a6fe5dd
@ -44,6 +44,7 @@ extern "C" {
|
||||
|
||||
#if __GNU_VISIBLE
|
||||
#define SCHED_IDLE 5
|
||||
#define SCHED_BATCH 6
|
||||
#endif
|
||||
|
||||
/* Scheduling Parameters */
|
||||
|
@ -44,8 +44,8 @@ is_alt_numpad_event (PINPUT_RECORD pirec)
|
||||
&& pirec->Event.KeyEvent.wVirtualScanCode == 0x38;
|
||||
}
|
||||
|
||||
int winprio_to_nice (DWORD);
|
||||
DWORD nice_to_winprio (int &);
|
||||
int winprio_to_nice (DWORD prio, bool batch = false);
|
||||
DWORD nice_to_winprio (int &nice, bool batch = false);
|
||||
bool set_and_check_winprio (HANDLE proc, DWORD prio, bool set = true);
|
||||
|
||||
bool create_pipe (PHANDLE, PHANDLE, LPSECURITY_ATTRIBUTES, DWORD);
|
||||
|
@ -103,84 +103,111 @@ yield ()
|
||||
Sleep (0L);
|
||||
}
|
||||
|
||||
/* Get a default value for the nice factor. When changing these values,
|
||||
have a look into the below function nice_to_winprio. The values must
|
||||
match the layout of the static "priority" array. */
|
||||
int
|
||||
winprio_to_nice (DWORD prio)
|
||||
/*
|
||||
Mapping of nice value from/to Windows priority
|
||||
('batch' is used for SCHED_BATCH policy).
|
||||
|
||||
nice_to_winprio() winprio_to_nice()
|
||||
!batch batch Level Windows priority class !batch batch
|
||||
12...19 4...19 0 IDLE_PRIORITY_CLASS 16 8
|
||||
4...11 -4....3 1 BELOW_NORMAL_PRIORITY_CLASS 8 0
|
||||
-4....3 -12...-5 2 NORMAL_PRIORITY_CLASS 0 -8
|
||||
-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
|
||||
*/
|
||||
|
||||
/* *_PRIORITY_CLASS -> 0...5 */
|
||||
constexpr int
|
||||
winprio_to_level (DWORD prio)
|
||||
{
|
||||
switch (prio)
|
||||
{
|
||||
case REALTIME_PRIORITY_CLASS:
|
||||
return -20;
|
||||
case HIGH_PRIORITY_CLASS:
|
||||
return -16;
|
||||
case ABOVE_NORMAL_PRIORITY_CLASS:
|
||||
return -8;
|
||||
case NORMAL_PRIORITY_CLASS:
|
||||
return 0;
|
||||
case BELOW_NORMAL_PRIORITY_CLASS:
|
||||
return 8;
|
||||
case IDLE_PRIORITY_CLASS:
|
||||
return 16;
|
||||
case IDLE_PRIORITY_CLASS: return 0;
|
||||
case BELOW_NORMAL_PRIORITY_CLASS: return 1;
|
||||
default: return 2;
|
||||
case ABOVE_NORMAL_PRIORITY_CLASS: return 3;
|
||||
case HIGH_PRIORITY_CLASS: return 4;
|
||||
case REALTIME_PRIORITY_CLASS: return 5;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 0...5 -> *_PRIORITY_CLASS */
|
||||
constexpr DWORD
|
||||
level_to_winprio (int level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case 0: return IDLE_PRIORITY_CLASS;
|
||||
case 1: return BELOW_NORMAL_PRIORITY_CLASS;
|
||||
default: return NORMAL_PRIORITY_CLASS;
|
||||
case 3: return ABOVE_NORMAL_PRIORITY_CLASS;
|
||||
case 4: return HIGH_PRIORITY_CLASS;
|
||||
case 5: return REALTIME_PRIORITY_CLASS;
|
||||
}
|
||||
}
|
||||
|
||||
/* *_PRIORITY_CLASS -> nice value */
|
||||
constexpr int
|
||||
winprio_to_nice_impl (DWORD prio, bool batch = false)
|
||||
{
|
||||
int level = winprio_to_level (prio);
|
||||
if (batch && level < 5)
|
||||
level++;
|
||||
return (level < 5 ? NZERO - 1 - 3 - level * 8 : -NZERO);
|
||||
}
|
||||
|
||||
/* nice value -> *_PRIORITY_CLASS */
|
||||
constexpr DWORD
|
||||
nice_to_winprio_impl (int nice, bool batch = false)
|
||||
{
|
||||
int level = (nice > -NZERO ? (NZERO - 1 - nice) / 8 : 5);
|
||||
if (batch && level > 0)
|
||||
level--;
|
||||
return level_to_winprio (level);
|
||||
}
|
||||
|
||||
/* Check consistency at compile time. */
|
||||
constexpr bool
|
||||
check_nice_winprio_mapping ()
|
||||
{
|
||||
for (int nice = -NZERO; nice < NZERO; nice++)
|
||||
for (int batch = 0; batch <= 1; batch++) {
|
||||
DWORD prio = nice_to_winprio_impl (nice, !!batch);
|
||||
int nice2 = winprio_to_nice_impl (prio, !!batch);
|
||||
DWORD prio2 = nice_to_winprio_impl (nice2, !!batch);
|
||||
if (prio != prio2)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert (check_nice_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);
|
||||
|
||||
/* Get a default value for the nice factor. */
|
||||
int
|
||||
winprio_to_nice (DWORD prio, bool batch /* = false */)
|
||||
{
|
||||
return winprio_to_nice_impl (prio, batch);
|
||||
}
|
||||
|
||||
/* Get a Win32 priority matching the incoming nice factor. The incoming
|
||||
nice is limited to the interval [-NZERO,NZERO-1]. */
|
||||
DWORD
|
||||
nice_to_winprio (int &nice)
|
||||
nice_to_winprio (int &nice, bool batch /* = false */)
|
||||
{
|
||||
static const DWORD priority[] =
|
||||
{
|
||||
REALTIME_PRIORITY_CLASS, /* 0 */
|
||||
HIGH_PRIORITY_CLASS, /* 1 */
|
||||
HIGH_PRIORITY_CLASS,
|
||||
HIGH_PRIORITY_CLASS,
|
||||
HIGH_PRIORITY_CLASS,
|
||||
HIGH_PRIORITY_CLASS,
|
||||
HIGH_PRIORITY_CLASS,
|
||||
HIGH_PRIORITY_CLASS, /* 7 */
|
||||
ABOVE_NORMAL_PRIORITY_CLASS, /* 8 */
|
||||
ABOVE_NORMAL_PRIORITY_CLASS,
|
||||
ABOVE_NORMAL_PRIORITY_CLASS,
|
||||
ABOVE_NORMAL_PRIORITY_CLASS,
|
||||
ABOVE_NORMAL_PRIORITY_CLASS,
|
||||
ABOVE_NORMAL_PRIORITY_CLASS,
|
||||
ABOVE_NORMAL_PRIORITY_CLASS,
|
||||
ABOVE_NORMAL_PRIORITY_CLASS, /* 15 */
|
||||
NORMAL_PRIORITY_CLASS, /* 16 */
|
||||
NORMAL_PRIORITY_CLASS,
|
||||
NORMAL_PRIORITY_CLASS,
|
||||
NORMAL_PRIORITY_CLASS,
|
||||
NORMAL_PRIORITY_CLASS,
|
||||
NORMAL_PRIORITY_CLASS,
|
||||
NORMAL_PRIORITY_CLASS,
|
||||
NORMAL_PRIORITY_CLASS, /* 23 */
|
||||
BELOW_NORMAL_PRIORITY_CLASS, /* 24 */
|
||||
BELOW_NORMAL_PRIORITY_CLASS,
|
||||
BELOW_NORMAL_PRIORITY_CLASS,
|
||||
BELOW_NORMAL_PRIORITY_CLASS,
|
||||
BELOW_NORMAL_PRIORITY_CLASS,
|
||||
BELOW_NORMAL_PRIORITY_CLASS,
|
||||
BELOW_NORMAL_PRIORITY_CLASS,
|
||||
BELOW_NORMAL_PRIORITY_CLASS, /* 31 */
|
||||
IDLE_PRIORITY_CLASS, /* 32 */
|
||||
IDLE_PRIORITY_CLASS,
|
||||
IDLE_PRIORITY_CLASS,
|
||||
IDLE_PRIORITY_CLASS,
|
||||
IDLE_PRIORITY_CLASS,
|
||||
IDLE_PRIORITY_CLASS,
|
||||
IDLE_PRIORITY_CLASS,
|
||||
IDLE_PRIORITY_CLASS /* 39 */
|
||||
};
|
||||
if (nice < -NZERO)
|
||||
nice = -NZERO;
|
||||
else if (nice > NZERO - 1)
|
||||
nice = NZERO - 1;
|
||||
DWORD prio = priority[nice + NZERO];
|
||||
return prio;
|
||||
|
||||
return nice_to_winprio_impl (nice, batch);
|
||||
}
|
||||
|
||||
/* Set Win32 priority or return false on failure. Also return
|
||||
|
@ -57,11 +57,12 @@ What changed:
|
||||
to POSIX and Linux (glibc >= 2.2.4) behavior.
|
||||
|
||||
- sched_setscheduler(2) now emulates changes between SCHED_OTHER,
|
||||
SCHED_IDLE, SCHED_FIFO and SCHED_RR. If SCHED_OTHER is selected, the
|
||||
Windows priority is set according to the nice value. If SCHED_IDLE is
|
||||
SCHED_BATCH, SCHED_IDLE, SCHED_FIFO and SCHED_RR. If SCHED_OTHER or
|
||||
SCHED_BATCH is selected, the Windows priority is set according to the
|
||||
nice value where SCHED_BATCH sets a one step lower priority. If
|
||||
SCHED_IDLE is selected, the nice value is preserved and the Windows
|
||||
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
|
||||
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.
|
||||
according to the realtime priority.
|
||||
Note: Windows does not offer alternative scheduling policies so
|
||||
this could only emulate API behavior.
|
||||
|
@ -34,6 +34,7 @@ sched_get_priority_max (int policy)
|
||||
switch (policy)
|
||||
{
|
||||
case SCHED_OTHER:
|
||||
case SCHED_BATCH:
|
||||
case SCHED_IDLE:
|
||||
return 0;
|
||||
case SCHED_FIFO:
|
||||
@ -51,6 +52,7 @@ sched_get_priority_min (int policy)
|
||||
switch (policy)
|
||||
{
|
||||
case SCHED_OTHER:
|
||||
case SCHED_BATCH:
|
||||
case SCHED_IDLE:
|
||||
return 0;
|
||||
case SCHED_FIFO:
|
||||
@ -95,7 +97,8 @@ sched_getparam (pid_t pid, struct sched_param *param)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (p->sched_policy == SCHED_OTHER || p->sched_policy == SCHED_IDLE)
|
||||
if (p->sched_policy == SCHED_OTHER || p->sched_policy == SCHED_BATCH
|
||||
|| p->sched_policy == SCHED_IDLE)
|
||||
{
|
||||
/* No realtime policy. */
|
||||
param->sched_priority = 0;
|
||||
@ -234,9 +237,10 @@ sched_setparam_pinfo (pinfo & p, const struct sched_param *param)
|
||||
/* calculate our desired priority class. We only reserve a small area
|
||||
(31/32) for realtime priority. */
|
||||
DWORD pclass;
|
||||
if (p->sched_policy == SCHED_OTHER && pri == 0)
|
||||
bool batch = (p->sched_policy == SCHED_BATCH);
|
||||
if ((p->sched_policy == SCHED_OTHER || batch) && pri == 0)
|
||||
/* No realtime policy, reapply the nice value. */
|
||||
pclass = nice_to_winprio (p->nice);
|
||||
pclass = nice_to_winprio (p->nice, batch);
|
||||
else if (p->sched_policy == SCHED_IDLE && pri == 0)
|
||||
/* Idle policy, ignore the nice value. */
|
||||
pclass = IDLE_PRIORITY_CLASS;
|
||||
@ -422,8 +426,9 @@ sched_setscheduler (pid_t pid, int policy,
|
||||
const struct sched_param *param)
|
||||
{
|
||||
if (!(pid >= 0 && param &&
|
||||
(((policy == SCHED_OTHER || policy == SCHED_IDLE) && param->sched_priority == 0) ||
|
||||
((policy == SCHED_FIFO || policy == SCHED_RR) && valid_sched_parameters(param)))))
|
||||
(((policy == SCHED_OTHER || policy == SCHED_BATCH || policy == SCHED_IDLE)
|
||||
&& param->sched_priority == 0) || ((policy == SCHED_FIFO || policy == SCHED_RR)
|
||||
&& valid_sched_parameters(param)))))
|
||||
{
|
||||
set_errno (EINVAL);
|
||||
return -1;
|
||||
|
@ -3816,9 +3816,6 @@ vhangup ()
|
||||
extern "C" int
|
||||
setpriority (int which, id_t who, int value)
|
||||
{
|
||||
DWORD prio = nice_to_winprio (value);
|
||||
int error = 0;
|
||||
|
||||
switch (which)
|
||||
{
|
||||
case PRIO_PROCESS:
|
||||
@ -3827,8 +3824,10 @@ setpriority (int which, id_t who, int value)
|
||||
if ((pid_t) who == myself->pid)
|
||||
{
|
||||
/* If realtime policy is set, keep prio but check its validity. */
|
||||
bool batch = (myself->sched_policy == SCHED_BATCH);
|
||||
DWORD prio = nice_to_winprio (value, batch);
|
||||
if (!set_and_check_winprio (GetCurrentProcess (), prio,
|
||||
(myself->sched_policy == SCHED_OTHER)))
|
||||
(myself->sched_policy == SCHED_OTHER || batch)))
|
||||
{
|
||||
set_errno (EACCES);
|
||||
return -1;
|
||||
@ -3850,6 +3849,8 @@ setpriority (int which, id_t who, int value)
|
||||
set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int error = 0;
|
||||
winpids pids ((DWORD) PID_MAP_RW);
|
||||
for (DWORD i = 0; i < pids.npids; ++i)
|
||||
{
|
||||
@ -3878,9 +3879,11 @@ setpriority (int which, id_t who, int value)
|
||||
error = EPERM;
|
||||
else
|
||||
{
|
||||
bool batch = (p->sched_policy == SCHED_BATCH);
|
||||
DWORD prio = nice_to_winprio (value, batch);
|
||||
/* If realtime policy is set, keep prio but check its validity. */
|
||||
if (!set_and_check_winprio (proc_h, prio,
|
||||
(p->sched_policy == SCHED_OTHER)))
|
||||
(p->sched_policy == SCHED_OTHER || batch)))
|
||||
error = EACCES;
|
||||
else
|
||||
p->nice = value;
|
||||
@ -3909,11 +3912,12 @@ getpriority (int which, id_t who)
|
||||
who = myself->pid;
|
||||
if ((pid_t) who == myself->pid)
|
||||
{
|
||||
if (myself->sched_policy == SCHED_OTHER)
|
||||
bool batch = (myself->sched_policy == SCHED_BATCH);
|
||||
if (myself->sched_policy == SCHED_OTHER || batch)
|
||||
{
|
||||
DWORD winprio = GetPriorityClass (GetCurrentProcess());
|
||||
if (winprio != nice_to_winprio (myself->nice))
|
||||
myself->nice = winprio_to_nice (winprio);
|
||||
if (winprio != nice_to_winprio (myself->nice, batch))
|
||||
myself->nice = winprio_to_nice (winprio, batch);
|
||||
}
|
||||
return myself->nice;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user