Skip to content

Commit 81c7742

Browse files
committed
unix,win: add uv_os_{get,set}priority()
Refs: nodejs/node#21675 PR-URL: libuv#1945 Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com> Reviewed-By: Richard Lau <riclau@uk.ibm.com>
1 parent 7284adf commit 81c7742

9 files changed

Lines changed: 246 additions & 0 deletions

File tree

‎CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ set(uv_test_sources
9898
test/test-poll-closesocket.c
9999
test/test-poll-oob.c
100100
test/test-poll.c
101+
test/test-process-priority.c
101102
test/test-process-title-threadsafe.c
102103
test/test-process-title.c
103104
test/test-queue-foreach-delete.c

‎Makefile.am‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
224224
test/test-poll-close-doesnt-corrupt-stack.c \
225225
test/test-poll-closesocket.c \
226226
test/test-poll-oob.c \
227+
test/test-process-priority.c \
227228
test/test-process-title.c \
228229
test/test-process-title-threadsafe.c \
229230
test/test-queue-foreach-delete.c \

‎docs/src/misc.rst‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,3 +517,31 @@ API
517517
storage required to hold the value.
518518
519519
.. versionadded:: 1.12.0
520+
521+
.. c:function:: int uv_os_getpriority(uv_pid_t pid, int* priority)
522+
523+
Retrieves the scheduling priority of the process specified by `pid`. The
524+
returned value of `priority` is between -20 (high priority) and 19 (low
525+
priority).
526+
527+
.. note::
528+
On Windows, the returned priority will equal one of the `UV_PRIORITY`
529+
constants.
530+
531+
.. versionadded:: REPLACEME
532+
533+
.. c:function:: int uv_os_setpriority(uv_pid_t pid, int priority)
534+
535+
Sets the scheduling priority of the process specified by `pid`. The
536+
`priority` value range is between -20 (high priority) and 19 (low priority).
537+
The constants `UV_PRIORITY_LOW`, `UV_PRIORITY_BELOW_NORMAL`,
538+
`UV_PRIORITY_NORMAL`, `UV_PRIORITY_ABOVE_NORMAL`, `UV_PRIORITY_HIGH`, and
539+
`UV_PRIORITY_HIGHEST` are also provided for convenience.
540+
541+
.. note::
542+
On Windows, this function utilizes `SetPriorityClass()`. The `priority`
543+
argument is mapped to a Windows priority class. When retrieving the
544+
process priority, the result will equal one of the `UV_PRIORITY`
545+
constants, and not necessarily the exact value of `priority`.
546+
547+
.. versionadded:: REPLACEME

‎include/uv.h‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,16 @@ UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd);
11001100
UV_EXTERN uv_pid_t uv_os_getpid(void);
11011101
UV_EXTERN uv_pid_t uv_os_getppid(void);
11021102

1103+
#define UV_PRIORITY_LOW 19
1104+
#define UV_PRIORITY_BELOW_NORMAL 10
1105+
#define UV_PRIORITY_NORMAL 0
1106+
#define UV_PRIORITY_ABOVE_NORMAL -7
1107+
#define UV_PRIORITY_HIGH -14
1108+
#define UV_PRIORITY_HIGHEST -20
1109+
1110+
UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority);
1111+
UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority);
1112+
11031113
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
11041114
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
11051115

‎src/unix/core.c‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,3 +1350,31 @@ uv_pid_t uv_os_getpid(void) {
13501350
uv_pid_t uv_os_getppid(void) {
13511351
return getppid();
13521352
}
1353+
1354+
1355+
int uv_os_getpriority(uv_pid_t pid, int* priority) {
1356+
int r;
1357+
1358+
if (priority == NULL)
1359+
return UV_EINVAL;
1360+
1361+
errno = 0;
1362+
r = getpriority(PRIO_PROCESS, (int) pid);
1363+
1364+
if (r == -1 && errno != 0)
1365+
return UV__ERR(errno);
1366+
1367+
*priority = r;
1368+
return 0;
1369+
}
1370+
1371+
1372+
int uv_os_setpriority(uv_pid_t pid, int priority) {
1373+
if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
1374+
return UV_EINVAL;
1375+
1376+
if (setpriority(PRIO_PROCESS, (int) pid, priority) != 0)
1377+
return UV__ERR(errno);
1378+
1379+
return 0;
1380+
}

‎src/win/util.c‎

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,3 +1530,97 @@ int uv_os_gethostname(char* buffer, size_t* size) {
15301530
*size = len;
15311531
return 0;
15321532
}
1533+
1534+
1535+
static int uv__get_handle(uv_pid_t pid, int access, HANDLE* handle) {
1536+
int r;
1537+
1538+
if (pid == 0)
1539+
*handle = GetCurrentProcess();
1540+
else
1541+
*handle = OpenProcess(access, FALSE, pid);
1542+
1543+
if (*handle == NULL) {
1544+
r = GetLastError();
1545+
1546+
if (r == ERROR_INVALID_PARAMETER)
1547+
return UV_ESRCH;
1548+
else
1549+
return uv_translate_sys_error(r);
1550+
}
1551+
1552+
return 0;
1553+
}
1554+
1555+
1556+
int uv_os_getpriority(uv_pid_t pid, int* priority) {
1557+
HANDLE handle;
1558+
int r;
1559+
1560+
if (priority == NULL)
1561+
return UV_EINVAL;
1562+
1563+
r = uv__get_handle(pid, PROCESS_QUERY_LIMITED_INFORMATION, &handle);
1564+
1565+
if (r != 0)
1566+
return r;
1567+
1568+
r = GetPriorityClass(handle);
1569+
1570+
if (r == 0) {
1571+
r = uv_translate_sys_error(GetLastError());
1572+
} else {
1573+
/* Map Windows priority classes to Unix nice values. */
1574+
if (r == REALTIME_PRIORITY_CLASS)
1575+
*priority = UV_PRIORITY_HIGHEST;
1576+
else if (r == HIGH_PRIORITY_CLASS)
1577+
*priority = UV_PRIORITY_HIGH;
1578+
else if (r == ABOVE_NORMAL_PRIORITY_CLASS)
1579+
*priority = UV_PRIORITY_ABOVE_NORMAL;
1580+
else if (r == NORMAL_PRIORITY_CLASS)
1581+
*priority = UV_PRIORITY_NORMAL;
1582+
else if (r == BELOW_NORMAL_PRIORITY_CLASS)
1583+
*priority = UV_PRIORITY_BELOW_NORMAL;
1584+
else /* IDLE_PRIORITY_CLASS */
1585+
*priority = UV_PRIORITY_LOW;
1586+
1587+
r = 0;
1588+
}
1589+
1590+
CloseHandle(handle);
1591+
return r;
1592+
}
1593+
1594+
1595+
int uv_os_setpriority(uv_pid_t pid, int priority) {
1596+
HANDLE handle;
1597+
int priority_class;
1598+
int r;
1599+
1600+
/* Map Unix nice values to Windows priority classes. */
1601+
if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
1602+
return UV_EINVAL;
1603+
else if (priority < UV_PRIORITY_HIGH)
1604+
priority_class = REALTIME_PRIORITY_CLASS;
1605+
else if (priority < UV_PRIORITY_ABOVE_NORMAL)
1606+
priority_class = HIGH_PRIORITY_CLASS;
1607+
else if (priority < UV_PRIORITY_NORMAL)
1608+
priority_class = ABOVE_NORMAL_PRIORITY_CLASS;
1609+
else if (priority < UV_PRIORITY_BELOW_NORMAL)
1610+
priority_class = NORMAL_PRIORITY_CLASS;
1611+
else if (priority < UV_PRIORITY_LOW)
1612+
priority_class = BELOW_NORMAL_PRIORITY_CLASS;
1613+
else
1614+
priority_class = IDLE_PRIORITY_CLASS;
1615+
1616+
r = uv__get_handle(pid, PROCESS_SET_INFORMATION, &handle);
1617+
1618+
if (r != 0)
1619+
return r;
1620+
1621+
if (SetPriorityClass(handle, priority_class) == 0)
1622+
r = uv_translate_sys_error(GetLastError());
1623+
1624+
CloseHandle(handle);
1625+
return r;
1626+
}

‎test/test-list.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ TEST_DECLARE (pipe_close_stdout_read_stdin)
214214
TEST_DECLARE (pipe_set_non_blocking)
215215
TEST_DECLARE (pipe_set_chmod)
216216
TEST_DECLARE (process_ref)
217+
TEST_DECLARE (process_priority)
217218
TEST_DECLARE (has_ref)
218219
TEST_DECLARE (active)
219220
TEST_DECLARE (embed)
@@ -689,6 +690,7 @@ TASK_LIST_START
689690
TEST_ENTRY (pipe_ref4)
690691
TEST_HELPER (pipe_ref4, pipe_echo_server)
691692
TEST_ENTRY (process_ref)
693+
TEST_ENTRY (process_priority)
692694
TEST_ENTRY (has_ref)
693695

694696
TEST_ENTRY (loop_handles)

‎test/test-process-priority.c‎

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/* Copyright libuv contributors. All rights reserved.
2+
*
3+
* Permission is hereby granted, free of charge, to any person obtaining a copy
4+
* of this software and associated documentation files (the "Software"), to
5+
* deal in the Software without restriction, including without limitation the
6+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7+
* sell copies of the Software, and to permit persons to whom the Software is
8+
* furnished to do so, subject to the following conditions:
9+
*
10+
* The above copyright notice and this permission notice shall be included in
11+
* all copies or substantial portions of the Software.
12+
*
13+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19+
* IN THE SOFTWARE.
20+
*/
21+
22+
#include "uv.h"
23+
#include "task.h"
24+
25+
26+
TEST_IMPL(process_priority) {
27+
int priority;
28+
int r;
29+
int i;
30+
31+
#if defined(__MVS__)
32+
if (uv_os_setpriority(0, 0) == UV_ENOSYS)
33+
RETURN_SKIP("functionality not supported on zOS");
34+
#endif
35+
36+
/* Verify that passing a NULL pointer returns UV_EINVAL. */
37+
r = uv_os_getpriority(0, NULL);
38+
ASSERT(r == UV_EINVAL);
39+
40+
/* Verify that all valid values work. */
41+
for (i = UV_PRIORITY_HIGHEST; i <= UV_PRIORITY_LOW; i++) {
42+
r = uv_os_setpriority(0, i);
43+
44+
/* If UV_EACCES is returned, the current user doesn't have permission to
45+
set this specific priority. */
46+
if (r == UV_EACCES)
47+
continue;
48+
49+
ASSERT(r == 0);
50+
ASSERT(uv_os_getpriority(0, &priority) == 0);
51+
52+
/* Verify that the priority values match on Unix, and are range mapped
53+
on Windows. */
54+
#ifndef _WIN32
55+
ASSERT(priority == i);
56+
#else
57+
if (i < UV_PRIORITY_HIGH)
58+
ASSERT(priority == UV_PRIORITY_HIGHEST);
59+
else if (i < UV_PRIORITY_ABOVE_NORMAL)
60+
ASSERT(priority == UV_PRIORITY_HIGH);
61+
else if (i < UV_PRIORITY_NORMAL)
62+
ASSERT(priority == UV_PRIORITY_ABOVE_NORMAL);
63+
else if (i < UV_PRIORITY_BELOW_NORMAL)
64+
ASSERT(priority == UV_PRIORITY_NORMAL);
65+
else if (i < UV_PRIORITY_LOW)
66+
ASSERT(priority == UV_PRIORITY_BELOW_NORMAL);
67+
else
68+
ASSERT(priority == UV_PRIORITY_LOW);
69+
#endif
70+
71+
/* Verify that the current PID and 0 are equivalent. */
72+
ASSERT(uv_os_getpriority(uv_os_getpid(), &r) == 0);
73+
ASSERT(priority == r);
74+
}
75+
76+
/* Verify that invalid priorities return UV_EINVAL. */
77+
ASSERT(uv_os_setpriority(0, UV_PRIORITY_HIGHEST - 1) == UV_EINVAL);
78+
ASSERT(uv_os_setpriority(0, UV_PRIORITY_LOW + 1) == UV_EINVAL);
79+
80+
return 0;
81+
}

‎test/test.gyp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
'test-poll-close-doesnt-corrupt-stack.c',
8181
'test-poll-closesocket.c',
8282
'test-poll-oob.c',
83+
'test-process-priority.c',
8384
'test-process-title.c',
8485
'test-process-title-threadsafe.c',
8586
'test-queue-foreach-delete.c',

0 commit comments

Comments
 (0)