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:
parent
7284adfa7a
commit
e57e07172e
@ -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
|
||||
|
||||
@ -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 \
|
||||
|
||||
@ -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
|
||||
|
||||
10
include/uv.h
10
include/uv.h
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
81
test/test-process-priority.c
Normal file
81
test/test-process-priority.c
Normal 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;
|
||||
}
|
||||
@ -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',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user