os: add os.{get,set}Priority()

PR-URL: https://github.com/nodejs/node/pull/22407
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
This commit is contained in:
cjihrig committed 2018-08-22 17:27:16 -04:00
1 parent 91eec00ca2
commit 92880f31da
7 files changed
+343 -2

No files matched your search

+87
View File
@@ -192,6 +192,19 @@ added: v0.3.3
The `os.freemem()` method returns the amount of free system memory in bytes as
an integer.
## os.getPriority([pid])
<!-- YAML
added: REPLACEME
-->
* `pid` {integer} The process ID to retrieve scheduling priority for.
**Default** `0`.
* Returns: {integer}
The `os.getPriority()` method returns the scheduling priority for the process
specified by `pid`. If `pid` is not provided, or is `0`, the priority of the
current process is returned.
## os.homedir()
<!-- YAML
added: v2.3.0
@@ -338,6 +351,26 @@ On POSIX systems, the operating system release is determined by calling
[uname(3)][]. On Windows, `GetVersionExW()` is used. Please see
https://en.wikipedia.org/wiki/Uname#Examples for more information.
## os.setPriority([pid, ]priority)
<!-- YAML
added: REPLACEME
-->
* `pid` {integer} The process ID to set scheduling priority for.
**Default** `0`.
* `priority` {integer} The scheduling priority to assign to the process.
The `os.setPriority()` method attempts to set the scheduling priority for the
process specified by `pid`. If `pid` is not provided, or is `0`, the priority
of the current process is used.
The `priority` input must be an integer between `-20` (high priority) and `19`
(low priority). Due to differences between Unix priority levels and Windows
priority classes, `priority` is mapped to one of six priority constants in
`os.constants.priority`. When retrieving a process priority level, this range
mapping may cause the return value to be slightly different on Windows. To avoid
confusion, it is recommended to set `priority` to one of the priority constants.
## os.tmpdir()
<!-- YAML
added: v0.9.9
@@ -1208,6 +1241,60 @@ information.
</tr>
</table>
### Priority Constants
<!-- YAML
added: REPLACEME
-->
The following process scheduling constants are exported by
`os.constants.priority`:
<table>
<tr>
<th>Constant</th>
<th>Description</th>
</tr>
<tr>
<td><code>PRIORITY_LOW</code></td>
<td>The lowest process scheduling priority. This corresponds to
<code>IDLE_PRIORITY_CLASS</code> on Windows, and a nice value of
<code>19</code> on all other platforms.</td>
</tr>
<tr>
<td><code>PRIORITY_BELOW_NORMAL</code></td>
<td>The process scheduling priority above <code>PRIORITY_LOW</code> and
below <code>PRIORITY_NORMAL</code>. This corresponds to
<code>BELOW_NORMAL_PRIORITY_CLASS</code> on Windows, and a nice value of
<code>10</code> on all other platforms.</td>
</tr>
<tr>
<td><code>PRIORITY_NORMAL</code></td>
<td>The default process scheduling priority. This corresponds to
<code>NORMAL_PRIORITY_CLASS</code> on Windows, and a nice value of
<code>0</code> on all other platforms.</td>
</tr>
<tr>
<td><code>PRIORITY_ABOVE_NORMAL</code></td>
<td>The process scheduling priority above <code>PRIORITY_NORMAL</code> and
below <code>PRIORITY_HIGH</code>. This corresponds to
<code>ABOVE_NORMAL_PRIORITY_CLASS</code> on Windows, and a nice value of
<code>-7</code> on all other platforms.</td>
</tr>
<tr>
<td><code>PRIORITY_HIGH</code></td>
<td>The process scheduling priority above <code>PRIORITY_ABOVE_NORMAL</code>
and below <code>PRIORITY_HIGHEST</code>. This corresponds to
<code>HIGH_PRIORITY_CLASS</code> on Windows, and a nice value of
<code>-14</code> on all other platforms.</td>
</tr>
<tr>
<td><code>PRIORITY_HIGHEST</code></td>
<td>The highest process scheduling priority. This corresponds to
<code>REALTIME_PRIORITY_CLASS</code> on Windows, and a nice value of
<code>-20</code> on all other platforms.</td>
</tr>
</table>
### libuv Constants
<table>
+1
View File
@@ -29,6 +29,7 @@ const constants = process.binding('constants');
Object.assign(exports,
constants.os.dlopen,
constants.os.errno,
constants.os.priority,
constants.os.signals,
constants.fs,
constants.crypto);
+36 -1
View File
@@ -27,6 +27,7 @@ const { deprecate } = require('internal/util');
const isWindows = process.platform === 'win32';
const { codes: { ERR_SYSTEM_ERROR } } = require('internal/errors');
const { validateInt32 } = require('internal/validators');
const {
getCPUs,
@@ -37,10 +38,12 @@ const {
getLoadAvg,
getOSRelease: _getOSRelease,
getOSType: _getOSType,
getPriority: _getPriority,
getTotalMem,
getUserInfo: _getUserInfo,
getUptime,
isBigEndian
isBigEndian,
setPriority: _setPriority
} = process.binding('os');
function getCheckedFunction(fn) {
@@ -206,17 +209,49 @@ function networkInterfaces() {
return interfaceAddresses;
}
function setPriority(pid, priority) {
if (priority === undefined) {
priority = pid;
pid = 0;
}
validateInt32(pid, 'pid');
validateInt32(priority, 'priority', -20, 19);
const ctx = {};
if (_setPriority(pid, priority, ctx) !== 0)
throw new ERR_SYSTEM_ERROR(ctx);
}
function getPriority(pid) {
if (pid === undefined)
pid = 0;
else
validateInt32(pid, 'pid');
const ctx = {};
const priority = _getPriority(pid, ctx);
if (priority === undefined)
throw new ERR_SYSTEM_ERROR(ctx);
return priority;
}
module.exports = {
arch,
cpus,
endianness,
freemem: getFreeMem,
getPriority,
homedir: getHomeDirectory,
hostname: getHostname,
loadavg,
networkInterfaces,
platform,
release: getOSRelease,
setPriority,
tmpdir,
totalmem: getTotalMem,
type: getOSType,
+44
View File
@@ -758,6 +758,44 @@ void DefineSignalConstants(Local<Object> target) {
#endif
}
void DefinePriorityConstants(Local<Object> target) {
#ifdef UV_PRIORITY_LOW
# define PRIORITY_LOW UV_PRIORITY_LOW
NODE_DEFINE_CONSTANT(target, PRIORITY_LOW);
# undef PRIORITY_LOW
#endif
#ifdef UV_PRIORITY_BELOW_NORMAL
# define PRIORITY_BELOW_NORMAL UV_PRIORITY_BELOW_NORMAL
NODE_DEFINE_CONSTANT(target, PRIORITY_BELOW_NORMAL);
# undef PRIORITY_BELOW_NORMAL
#endif
#ifdef UV_PRIORITY_NORMAL
# define PRIORITY_NORMAL UV_PRIORITY_NORMAL
NODE_DEFINE_CONSTANT(target, PRIORITY_NORMAL);
# undef PRIORITY_NORMAL
#endif
#ifdef UV_PRIORITY_ABOVE_NORMAL
# define PRIORITY_ABOVE_NORMAL UV_PRIORITY_ABOVE_NORMAL
NODE_DEFINE_CONSTANT(target, PRIORITY_ABOVE_NORMAL);
# undef PRIORITY_ABOVE_NORMAL
#endif
#ifdef UV_PRIORITY_HIGH
# define PRIORITY_HIGH UV_PRIORITY_HIGH
NODE_DEFINE_CONSTANT(target, PRIORITY_HIGH);
# undef PRIORITY_HIGH
#endif
#ifdef UV_PRIORITY_HIGHEST
# define PRIORITY_HIGHEST UV_PRIORITY_HIGHEST
NODE_DEFINE_CONSTANT(target, PRIORITY_HIGHEST);
# undef PRIORITY_HIGHEST
#endif
}
void DefineOpenSSLConstants(Local<Object> target) {
#ifdef OPENSSL_VERSION_NUMBER
NODE_DEFINE_CONSTANT(target, OPENSSL_VERSION_NUMBER);
@@ -1338,6 +1376,10 @@ void DefineConstants(v8::Isolate* isolate, Local<Object> target) {
CHECK(sig_constants->SetPrototype(env->context(),
Null(env->isolate())).FromJust());
Local<Object> priority_constants = Object::New(isolate);
CHECK(priority_constants->SetPrototype(env->context(),
Null(env->isolate())).FromJust());
Local<Object> fs_constants = Object::New(isolate);
CHECK(fs_constants->SetPrototype(env->context(),
Null(env->isolate())).FromJust());
@@ -1361,6 +1403,7 @@ void DefineConstants(v8::Isolate* isolate, Local<Object> target) {
DefineErrnoConstants(err_constants);
DefineWindowsErrorConstants(err_constants);
DefineSignalConstants(sig_constants);
DefinePriorityConstants(priority_constants);
DefineSystemConstants(fs_constants);
DefineOpenSSLConstants(crypto_constants);
DefineCryptoConstants(crypto_constants);
@@ -1374,6 +1417,7 @@ void DefineConstants(v8::Isolate* isolate, Local<Object> target) {
os_constants->Set(OneByteString(isolate, "dlopen"), dlopen_constants);
os_constants->Set(OneByteString(isolate, "errno"), err_constants);
os_constants->Set(OneByteString(isolate, "signals"), sig_constants);
os_constants->Set(OneByteString(isolate, "priority"), priority_constants);
target->Set(OneByteString(isolate, "os"), os_constants);
target->Set(OneByteString(isolate, "fs"), fs_constants);
target->Set(OneByteString(isolate, "crypto"), crypto_constants);
+43
View File
@@ -52,6 +52,7 @@ using v8::Context;
using v8::Float64Array;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Int32;
using v8::Integer;
using v8::Local;
using v8::MaybeLocal;
@@ -405,6 +406,46 @@ static void GetUserInfo(const FunctionCallbackInfo<Value>& args) {
}
static void SetPriority(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK_EQ(args.Length(), 3);
CHECK(args[0]->IsInt32());
CHECK(args[1]->IsInt32());
const int pid = args[0].As<Int32>()->Value();
const int priority = args[1].As<Int32>()->Value();
const int err = uv_os_setpriority(pid, priority);
if (err) {
CHECK(args[2]->IsObject());
env->CollectUVExceptionInfo(args[2], err, "uv_os_setpriority");
}
args.GetReturnValue().Set(err);
}
static void GetPriority(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK_EQ(args.Length(), 2);
CHECK(args[0]->IsInt32());
const int pid = args[0].As<Int32>()->Value();
int priority;
const int err = uv_os_getpriority(pid, &priority);
if (err) {
CHECK(args[1]->IsObject());
env->CollectUVExceptionInfo(args[1], err, "uv_os_getpriority");
return;
}
args.GetReturnValue().Set(priority);
}
void Initialize(Local<Object> target,
Local<Value> unused,
Local<Context> context) {
@@ -420,6 +461,8 @@ void Initialize(Local<Object> target,
env->SetMethod(target, "getInterfaceAddresses", GetInterfaceAddresses);
env->SetMethod(target, "getHomeDirectory", GetHomeDirectory);
env->SetMethod(target, "getUserInfo", GetUserInfo);
env->SetMethod(target, "setPriority", SetPriority);
env->SetMethod(target, "getPriority", GetPriority);
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "isBigEndian"),
Boolean::New(env->isolate(), IsBigEndian()));
}
+1 -1
View File
@@ -10,7 +10,7 @@ assert.deepStrictEqual(
assert.deepStrictEqual(
Object.keys(constants.os).sort(), ['UV_UDP_REUSEADDR', 'dlopen', 'errno',
'signals']
'priority', 'signals']
);
// Make sure all the constants objects don't inherit from Object.prototype
+131
View File
@@ -0,0 +1,131 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const os = require('os');
const {
PRIORITY_LOW,
PRIORITY_BELOW_NORMAL,
PRIORITY_NORMAL,
PRIORITY_ABOVE_NORMAL,
PRIORITY_HIGH,
PRIORITY_HIGHEST
} = os.constants.priority;
// Validate priority constants.
assert.strictEqual(typeof PRIORITY_LOW, 'number');
assert.strictEqual(typeof PRIORITY_BELOW_NORMAL, 'number');
assert.strictEqual(typeof PRIORITY_NORMAL, 'number');
assert.strictEqual(typeof PRIORITY_ABOVE_NORMAL, 'number');
assert.strictEqual(typeof PRIORITY_HIGH, 'number');
assert.strictEqual(typeof PRIORITY_HIGHEST, 'number');
// Test pid type validation.
[null, true, false, 'foo', {}, [], /x/].forEach((pid) => {
const errObj = {
code: 'ERR_INVALID_ARG_TYPE',
message: /The "pid" argument must be of type number\./
};
common.expectsError(() => {
os.setPriority(pid, PRIORITY_NORMAL);
}, errObj);
common.expectsError(() => {
os.getPriority(pid);
}, errObj);
});
// Test pid range validation.
[NaN, Infinity, -Infinity, 3.14, 2 ** 32].forEach((pid) => {
const errObj = {
code: 'ERR_OUT_OF_RANGE',
message: /The value of "pid" is out of range\./
};
common.expectsError(() => {
os.setPriority(pid, PRIORITY_NORMAL);
}, errObj);
common.expectsError(() => {
os.getPriority(pid);
}, errObj);
});
// Test priority type validation.
[null, true, false, 'foo', {}, [], /x/].forEach((priority) => {
common.expectsError(() => {
os.setPriority(0, priority);
}, {
code: 'ERR_INVALID_ARG_TYPE',
message: /The "priority" argument must be of type number\./
});
});
// Test priority range validation.
[
NaN,
Infinity,
-Infinity,
3.14,
2 ** 32,
PRIORITY_HIGHEST - 1,
PRIORITY_LOW + 1
].forEach((priority) => {
common.expectsError(() => {
os.setPriority(0, priority);
}, {
code: 'ERR_OUT_OF_RANGE',
message: /The value of "priority" is out of range\./
});
});
// Verify that valid values work.
for (let i = PRIORITY_HIGHEST; i <= PRIORITY_LOW; i++) {
// A pid of 0 corresponds to the current process.
try {
os.setPriority(0, i);
} catch (err) {
// The current user might not have sufficient permissions to set this
// specific priority level. Skip this priority, but keep trying lower
// priorities.
if (err.info.code === 'EACCES')
continue;
assert(err);
}
checkPriority(0, i);
// An undefined pid corresponds to the current process.
os.setPriority(i);
checkPriority(undefined, i);
// Specifying the actual pid works.
os.setPriority(process.pid, i);
checkPriority(process.pid, i);
}
function checkPriority(pid, expected) {
const priority = os.getPriority(pid);
// Verify that the priority values match on Unix, and are range mapped on
// Windows.
if (!common.isWindows) {
assert.strictEqual(priority, expected);
return;
}
if (expected < PRIORITY_HIGH)
assert.strictEqual(priority, PRIORITY_HIGHEST);
else if (expected < PRIORITY_ABOVE_NORMAL)
assert.strictEqual(priority, PRIORITY_HIGH);
else if (expected < PRIORITY_NORMAL)
assert.strictEqual(priority, PRIORITY_ABOVE_NORMAL);
else if (expected < PRIORITY_BELOW_NORMAL)
assert.strictEqual(priority, PRIORITY_NORMAL);
else if (expected < PRIORITY_LOW)
assert.strictEqual(priority, PRIORITY_BELOW_NORMAL);
else
assert.strictEqual(priority, PRIORITY_LOW);
}