Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Aug 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions doc/api/os.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
37 changes: 36 additions & 1 deletion lib/os.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down
44 changes: 44 additions & 0 deletions src/node_constants.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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());
Expand All @@ -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);
Expand All @@ -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);
Expand Down
43 changes: 43 additions & 0 deletions src/node_os.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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()));
}
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-binding-constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading