unix,win: add uv_os_{get,set}priority()

Refs: https://github.com/nodejs/node/pull/21675
PR-URL: https://github.com/libuv/libuv/pull/1945
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
This commit is contained in:
cjihrig 2018-08-12 21:59:22 -04:00
parent 7284adfa7a
commit e57e07172e
No known key found for this signature in database
GPG Key ID: 7434390BDBE9B9C5
9 changed files with 246 additions and 0 deletions

View File

@ -98,6 +98,7 @@ set(uv_test_sources
test/test-poll-closesocket.c
test/test-poll-oob.c
test/test-poll.c
test/test-process-priority.c
test/test-process-title-threadsafe.c
test/test-process-title.c
test/test-queue-foreach-delete.c

View File

@ -224,6 +224,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-poll-close-doesnt-corrupt-stack.c \
test/test-poll-closesocket.c \
test/test-poll-oob.c \
test/test-process-priority.c \
test/test-process-title.c \
test/test-process-title-threadsafe.c \
test/test-queue-foreach-delete.c \

View File

@ -517,3 +517,31 @@ API
storage required to hold the value.
.. versionadded:: 1.12.0
.. c:function:: int uv_os_getpriority(uv_pid_t pid, int* priority)
Retrieves the scheduling priority of the process specified by `pid`. The
returned value of `priority` is between -20 (high priority) and 19 (low
priority).
.. note::
On Windows, the returned priority will equal one of the `UV_PRIORITY`
constants.
.. versionadded:: 1.23.0
.. c:function:: int uv_os_setpriority(uv_pid_t pid, int priority)
Sets the scheduling priority of the process specified by `pid`. The
`priority` value range is between -20 (high priority) and 19 (low priority).
The constants `UV_PRIORITY_LOW`, `UV_PRIORITY_BELOW_NORMAL`,
`UV_PRIORITY_NORMAL`, `UV_PRIORITY_ABOVE_NORMAL`, `UV_PRIORITY_HIGH`, and
`UV_PRIORITY_HIGHEST` are also provided for convenience.
.. note::
On Windows, this function utilizes `SetPriorityClass()`. The `priority`
argument is mapped to a Windows priority class. When retrieving the
process priority, the result will equal one of the `UV_PRIORITY`
constants, and not necessarily the exact value of `priority`.
.. versionadded:: 1.23.0

View File

@ -1100,6 +1100,16 @@ UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd);
UV_EXTERN uv_pid_t uv_os_getpid(void);
UV_EXTERN uv_pid_t uv_os_getppid(void);
#define UV_PRIORITY_LOW 19
#define UV_PRIORITY_BELOW_NORMAL 10
#define UV_PRIORITY_NORMAL 0
#define UV_PRIORITY_ABOVE_NORMAL -7
#define UV_PRIORITY_HIGH -14
#define UV_PRIORITY_HIGHEST -20
UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority);
UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority);
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);

View File

@ -1350,3 +1350,31 @@ uv_pid_t uv_os_getpid(void) {
uv_pid_t uv_os_getppid(void) {
return getppid();
}
int uv_os_getpriority(uv_pid_t pid, int* priority) {
int r;
if (priority == NULL)
return UV_EINVAL;
errno = 0;
r = getpriority(PRIO_PROCESS, (int) pid);
if (r == -1 && errno != 0)
return UV__ERR(errno);
*priority = r;
return 0;
}
int uv_os_setpriority(uv_pid_t pid, int priority) {
if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
return UV_EINVAL;
if (setpriority(PRIO_PROCESS, (int) pid, priority) != 0)
return UV__ERR(errno);
return 0;
}

View File

@ -1530,3 +1530,97 @@ int uv_os_gethostname(char* buffer, size_t* size) {
*size = len;
return 0;
}
static int uv__get_handle(uv_pid_t pid, int access, HANDLE* handle) {
int r;
if (pid == 0)
*handle = GetCurrentProcess();
else
*handle = OpenProcess(access, FALSE, pid);
if (*handle == NULL) {
r = GetLastError();
if (r == ERROR_INVALID_PARAMETER)
return UV_ESRCH;
else
return uv_translate_sys_error(r);
}
return 0;
}
int uv_os_getpriority(uv_pid_t pid, int* priority) {
HANDLE handle;
int r;
if (priority == NULL)
return UV_EINVAL;
r = uv__get_handle(pid, PROCESS_QUERY_LIMITED_INFORMATION, &handle);
if (r != 0)
return r;
r = GetPriorityClass(handle);
if (r == 0) {
r = uv_translate_sys_error(GetLastError());
} else {
/* Map Windows priority classes to Unix nice values. */
if (r == REALTIME_PRIORITY_CLASS)
*priority = UV_PRIORITY_HIGHEST;
else if (r == HIGH_PRIORITY_CLASS)
*priority = UV_PRIORITY_HIGH;
else if (r == ABOVE_NORMAL_PRIORITY_CLASS)
*priority = UV_PRIORITY_ABOVE_NORMAL;
else if (r == NORMAL_PRIORITY_CLASS)
*priority = UV_PRIORITY_NORMAL;
else if (r == BELOW_NORMAL_PRIORITY_CLASS)
*priority = UV_PRIORITY_BELOW_NORMAL;
else /* IDLE_PRIORITY_CLASS */
*priority = UV_PRIORITY_LOW;
r = 0;
}
CloseHandle(handle);
return r;
}
int uv_os_setpriority(uv_pid_t pid, int priority) {
HANDLE handle;
int priority_class;
int r;
/* Map Unix nice values to Windows priority classes. */
if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
return UV_EINVAL;
else if (priority < UV_PRIORITY_HIGH)
priority_class = REALTIME_PRIORITY_CLASS;
else if (priority < UV_PRIORITY_ABOVE_NORMAL)
priority_class = HIGH_PRIORITY_CLASS;
else if (priority < UV_PRIORITY_NORMAL)
priority_class = ABOVE_NORMAL_PRIORITY_CLASS;
else if (priority < UV_PRIORITY_BELOW_NORMAL)
priority_class = NORMAL_PRIORITY_CLASS;
else if (priority < UV_PRIORITY_LOW)
priority_class = BELOW_NORMAL_PRIORITY_CLASS;
else
priority_class = IDLE_PRIORITY_CLASS;
r = uv__get_handle(pid, PROCESS_SET_INFORMATION, &handle);
if (r != 0)
return r;
if (SetPriorityClass(handle, priority_class) == 0)
r = uv_translate_sys_error(GetLastError());
CloseHandle(handle);
return r;
}

View File

@ -214,6 +214,7 @@ TEST_DECLARE (pipe_close_stdout_read_stdin)
TEST_DECLARE (pipe_set_non_blocking)
TEST_DECLARE (pipe_set_chmod)
TEST_DECLARE (process_ref)
TEST_DECLARE (process_priority)
TEST_DECLARE (has_ref)
TEST_DECLARE (active)
TEST_DECLARE (embed)
@ -689,6 +690,7 @@ TASK_LIST_START
TEST_ENTRY (pipe_ref4)
TEST_HELPER (pipe_ref4, pipe_echo_server)
TEST_ENTRY (process_ref)
TEST_ENTRY (process_priority)
TEST_ENTRY (has_ref)
TEST_ENTRY (loop_handles)

View File

@ -0,0 +1,81 @@
/* Copyright libuv contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "task.h"
TEST_IMPL(process_priority) {
int priority;
int r;
int i;
#if defined(__MVS__)
if (uv_os_setpriority(0, 0) == UV_ENOSYS)
RETURN_SKIP("functionality not supported on zOS");
#endif
/* Verify that passing a NULL pointer returns UV_EINVAL. */
r = uv_os_getpriority(0, NULL);
ASSERT(r == UV_EINVAL);
/* Verify that all valid values work. */
for (i = UV_PRIORITY_HIGHEST; i <= UV_PRIORITY_LOW; i++) {
r = uv_os_setpriority(0, i);
/* If UV_EACCES is returned, the current user doesn't have permission to
set this specific priority. */
if (r == UV_EACCES)
continue;
ASSERT(r == 0);
ASSERT(uv_os_getpriority(0, &priority) == 0);
/* Verify that the priority values match on Unix, and are range mapped
on Windows. */
#ifndef _WIN32
ASSERT(priority == i);
#else
if (i < UV_PRIORITY_HIGH)
ASSERT(priority == UV_PRIORITY_HIGHEST);
else if (i < UV_PRIORITY_ABOVE_NORMAL)
ASSERT(priority == UV_PRIORITY_HIGH);
else if (i < UV_PRIORITY_NORMAL)
ASSERT(priority == UV_PRIORITY_ABOVE_NORMAL);
else if (i < UV_PRIORITY_BELOW_NORMAL)
ASSERT(priority == UV_PRIORITY_NORMAL);
else if (i < UV_PRIORITY_LOW)
ASSERT(priority == UV_PRIORITY_BELOW_NORMAL);
else
ASSERT(priority == UV_PRIORITY_LOW);
#endif
/* Verify that the current PID and 0 are equivalent. */
ASSERT(uv_os_getpriority(uv_os_getpid(), &r) == 0);
ASSERT(priority == r);
}
/* Verify that invalid priorities return UV_EINVAL. */
ASSERT(uv_os_setpriority(0, UV_PRIORITY_HIGHEST - 1) == UV_EINVAL);
ASSERT(uv_os_setpriority(0, UV_PRIORITY_LOW + 1) == UV_EINVAL);
return 0;
}

View File

@ -80,6 +80,7 @@
'test-poll-close-doesnt-corrupt-stack.c',
'test-poll-closesocket.c',
'test-poll-oob.c',
'test-process-priority.c',
'test-process-title.c',
'test-process-title-threadsafe.c',
'test-queue-foreach-delete.c',