Skip to content

Commit

Permalink
os: add os.{get,set}Priority()
Browse files Browse the repository at this point in the history
PR-URL: #22407
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
  • Loading branch information
cjihrig committed Aug 22, 2018
1 parent 91eec00 commit 92880f3
Show file tree
Hide file tree
Showing 7 changed files with 343 additions and 2 deletions.
87 changes: 87 additions & 0 deletions doc/api/os.md
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
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
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
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
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
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

0 comments on commit 92880f3

Please sign in to comment.