1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <cerrno>
17 #include <cstring>
18 #include <fcntl.h>
19 #include <js_native_api.h>
20 #include <node_api.h>
21 #include <sched.h>
22 #include <unistd.h>
23 
24 #define NO_ERR 0
25 #define TWENTYTHREE 23
26 #define DEFAULTVALUE (-100)
27 #define SYS_pidfd_open 4
28 #define ONEVAL 1
29 #define MINUSONE (-1)
30 #define MINUSTEN (-10)
31 #define TWOTHREE 23
32 #define FAIL (-1)
33 #define NO_ERR 0
34 #define PARAM_0 0
35 #define PARAM_1 1
36 #define PARAM_2 2
37 #define PARAM_UNNORMAL (-1)
38 #define ERRON_0 0
39 #define TWENTYTHREE 23
40 #define DEFAULTVALUE (-100)
41 
SchedGetPriorityMax(napi_env env, napi_callback_info info)42 static napi_value SchedGetPriorityMax(napi_env env, napi_callback_info info)
43 {
44     size_t argc = PARAM_1;
45     napi_value args[1] = {nullptr};
46     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
47     int first = PARAM_0;
48     napi_get_value_int32(env, args[0], &first);
49     int maxvalue = sched_get_priority_max(first);
50     napi_value result = nullptr;
51     napi_create_int32(env, maxvalue, &result);
52     return result;
53 }
54 
SchedGetPriorityMin(napi_env env, napi_callback_info info)55 static napi_value SchedGetPriorityMin(napi_env env, napi_callback_info info)
56 {
57     size_t argc = PARAM_1;
58     napi_value args[1] = {nullptr};
59     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
60     int first = PARAM_0;
61     napi_get_value_int32(env, args[0], &first);
62     int minvalue = sched_get_priority_min(first);
63     napi_value result = nullptr;
64     napi_create_int32(env, minvalue, &result);
65     return result;
66 }
SchedCpualloc(napi_env env, napi_callback_info info)67 static napi_value SchedCpualloc(napi_env env, napi_callback_info info)
68 {
69     size_t count = PARAM_0;
70     cpu_set_t *ret = __sched_cpualloc(count);
71     napi_value result = nullptr;
72     if (ret == nullptr) {
73         napi_create_int32(env, PARAM_UNNORMAL, &result);
74     } else {
75         napi_create_int32(env, PARAM_0, &result);
76     }
77     return result;
78 }
SchedYield(napi_env env, napi_callback_info info)79 static napi_value SchedYield(napi_env env, napi_callback_info info)
80 {
81     int schValue = sched_yield();
82     napi_value result = nullptr;
83     napi_create_int32(env, schValue, &result);
84     return result;
85 }
86 
SchedGetscheduler(napi_env env, napi_callback_info info)87 static napi_value SchedGetscheduler(napi_env env, napi_callback_info info)
88 {
89     size_t argc = PARAM_1;
90     napi_value args[1] = {nullptr};
91     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
92     int first = PARAM_0;
93     napi_get_value_int32(env, args[0], &first);
94     napi_value result = nullptr;
95 
96     if (first == PARAM_0) {
97         int schval = sched_getscheduler(getpid());
98         napi_create_int32(env, schval, &result);
99     }
100     if (first == MINUSONE) {
101         int schval = sched_getscheduler(MINUSTEN);
102         napi_create_int32(env, schval, &result);
103     }
104     return result;
105 }
106 
SchedSetparam(napi_env env, napi_callback_info info)107 static napi_value SchedSetparam(napi_env env, napi_callback_info info)
108 {
109     napi_value result = nullptr;
110     size_t argc = PARAM_1;
111     napi_value args[1] = {nullptr};
112     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
113     struct sched_param param = {PARAM_0};
114     pid_t pid = getpid();
115     int first = PARAM_0;
116     napi_get_value_int32(env, args[0], &first);
117     int maxpri = sched_get_priority_max(SCHED_RR);
118     int minpri = sched_get_priority_min(SCHED_RR);
119     if (maxpri == FAIL || minpri == FAIL) {
120         napi_create_int32(env, FAIL, &result);
121     }
122     errno = 0;
123     if (first == PARAM_0) {
124         int ret = sched_getparam(pid, &param);
125         if (ret == NO_ERR) {
126             ret = sched_setparam(pid, &param);
127         }
128         napi_create_int32(env, ret, &result);
129     } else if (first == FAIL) {
130         int schval = sched_setparam(pid, nullptr);
131         napi_create_int32(env, schval, &result);
132     } else {
133         napi_create_int32(env, DEFAULTVALUE, &result);
134     }
135     return result;
136 }
137 
SchedSetscheduler(napi_env env, napi_callback_info info)138 static napi_value SchedSetscheduler(napi_env env, napi_callback_info info)
139 {
140     napi_value result = nullptr;
141     size_t argc = PARAM_1;
142     napi_value args[1] = {nullptr};
143     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
144     int first = PARAM_0;
145     napi_get_value_int32(env, args[0], &first);
146     int sched = PARAM_0;
147     pid_t pid = getpid();
148     sched = SCHED_FIFO;
149     struct sched_param param = {PARAM_0};
150     if (first == NO_ERR) {
151         param.sched_priority = TWENTYTHREE;
152         int schval = sched_setscheduler(pid, sched, &param);
153         napi_create_int32(env, schval, &result);
154     } else if (first == FAIL) {
155         int schval = sched_setscheduler(pid, sched, nullptr);
156         napi_create_int32(env, schval, &result);
157     } else {
158         napi_create_int32(env, DEFAULTVALUE, &result);
159     }
160     return result;
161 }
162 
SchedGetaffinity(napi_env env, napi_callback_info info)163 static napi_value SchedGetaffinity(napi_env env, napi_callback_info info)
164 {
165     cpu_set_t mask;
166     cpu_set_t get;
167     CPU_ZERO(&mask);
168     CPU_SET(PARAM_0, &mask);
169     int schval = sched_setaffinity(PARAM_0, sizeof(mask), &mask);
170     CPU_ZERO(&get);
171     schval = sched_getaffinity(PARAM_0, sizeof(get), &get);
172     napi_value result;
173     napi_create_int32(env, schval, &result);
174     return result;
175 }
176 
SchedGetcpu(napi_env env, napi_callback_info info)177 static napi_value SchedGetcpu(napi_env env, napi_callback_info info)
178 {
179     errno = ERRON_0;
180     int schval = sched_getcpu();
181     napi_value result = nullptr;
182     if (errno != PARAM_0) {
183         napi_create_int32(env, MINUSONE, &result);
184     } else if (schval >= PARAM_0) {
185         napi_create_int32(env, PARAM_0, &result);
186     }
187     return result;
188 }
189 
SchedSetaffinity(napi_env env, napi_callback_info info)190 static napi_value SchedSetaffinity(napi_env env, napi_callback_info info)
191 {
192     cpu_set_t mask;
193     CPU_ZERO(&mask);
194     CPU_SET(PARAM_0, &mask);
195     int schval = sched_setaffinity(PARAM_0, sizeof(mask), &mask);
196     napi_value result;
197     napi_create_int32(env, schval, &result);
198     return result;
199 }
200 
SchedRrGetInterval(napi_env env, napi_callback_info info)201 static napi_value SchedRrGetInterval(napi_env env, napi_callback_info info)
202 {
203     size_t argc = PARAM_1;
204     napi_value args[1] = {nullptr};
205     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
206     int first = PARAM_0;
207     napi_value result;
208     napi_get_value_int32(env, args[0], &first);
209     if (first == PARAM_0) {
210         pid_t pid = getpid();
211         struct timespec ts = {PARAM_0};
212         int schedvalue = sched_rr_get_interval(pid, &ts);
213         napi_create_int32(env, schedvalue, &result);
214     } else {
215         pid_t pid = MINUSONE;
216         struct timespec ts = {PARAM_0};
217         int schedvalue = sched_rr_get_interval(pid, &ts);
218         napi_create_int32(env, schedvalue, &result);
219     }
220     return result;
221 }
Setns(napi_env env, napi_callback_info info)222 static napi_value Setns(napi_env env, napi_callback_info info)
223 {
224     errno = ERRON_0;
225     pid_t pid = getpid();
226     int fd = syscall(SYS_pidfd_open, pid, PARAM_0);
227     int setval = PARAM_1;
228     if (fd >= PARAM_0) {
229         setval = setns(fd, PARAM_0);
230     }
231     napi_value result;
232     napi_create_int32(env, setval, &result);
233     return result;
234 }
Schedcpucount(napi_env env, napi_callback_info info)235 static napi_value Schedcpucount(napi_env env, napi_callback_info info)
236 {
237     napi_value result = nullptr;
238     int num_cpus = PARAM_0;
239     num_cpus = sysconf(_SC_NPROCESSORS_CONF);
240     size_t size;
241     size = CPU_ALLOC_SIZE(num_cpus);
242     cpu_set_t *cpu;
243     cpu = CPU_ALLOC(num_cpus);
244     int returnValue = __sched_cpucount(size, cpu);
245     napi_create_int32(env, returnValue, &result);
246     return result;
247 }
248 
Unshare(napi_env env, napi_callback_info info)249 static napi_value Unshare(napi_env env, napi_callback_info info)
250 {
251     size_t argc = PARAM_1;
252     napi_value args[1] = {nullptr};
253     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
254     int isOpenFile = PARAM_0, toJsResult = FAIL;
255     napi_get_value_int32(env, args[0], &isOpenFile);
256     if (isOpenFile == PARAM_1) {
257         int unshareResult = unshare(CLONE_FILES);
258         if (unshareResult == PARAM_0) {
259             toJsResult = PARAM_1;
260         }
261     }
262     napi_value result = nullptr;
263     napi_create_int32(env, toJsResult, &result);
264     return result;
265 }
266 
SchedGetparam(napi_env env, napi_callback_info info)267 static napi_value SchedGetparam(napi_env env, napi_callback_info info)
268 {
269     struct sched_param param1;
270     int ret = sched_getparam(PARAM_0, &param1);
271     napi_value result = nullptr;
272     napi_create_int32(env, ret, &result);
273     return result;
274 }
275 
276 EXTERN_C_START
Init(napi_env env, napi_value exports)277 static napi_value Init(napi_env env, napi_value exports)
278 {
279     napi_property_descriptor desc[] = {
280         {"schedGetPriorityMax", nullptr, SchedGetPriorityMax, nullptr, nullptr, nullptr, napi_default, nullptr},
281         {"schedGetPriorityMin", nullptr, SchedGetPriorityMin, nullptr, nullptr, nullptr, napi_default, nullptr},
282         {"sched_yield", nullptr, SchedYield, nullptr, nullptr, nullptr, napi_default, nullptr},
283         {"sched_getscheduler", nullptr, SchedGetscheduler, nullptr, nullptr, nullptr, napi_default, nullptr},
284         {"sched_setparam", nullptr, SchedSetparam, nullptr, nullptr, nullptr, napi_default, nullptr},
285         {"sched_setscheduler", nullptr, SchedSetscheduler, nullptr, nullptr, nullptr, napi_default, nullptr},
286         {"sched_getaffinity", nullptr, SchedGetaffinity, nullptr, nullptr, nullptr, napi_default, nullptr},
287         {"sched_getcpu", nullptr, SchedGetcpu, nullptr, nullptr, nullptr, napi_default, nullptr},
288         {"sched_setaffinity", nullptr, SchedSetaffinity, nullptr, nullptr, nullptr, napi_default, nullptr},
289         {"sched_rr_get_interval", nullptr, SchedRrGetInterval, nullptr, nullptr, nullptr, napi_default, nullptr},
290         {"setns", nullptr, Setns, nullptr, nullptr, nullptr, napi_default, nullptr},
291         {"schedCpuCount", nullptr, Schedcpucount, nullptr, nullptr, nullptr, napi_default, nullptr},
292         {"schedCpualloc", nullptr, SchedCpualloc, nullptr, nullptr, nullptr, napi_default, nullptr},
293         {"unshare", nullptr, Unshare, nullptr, nullptr, nullptr, napi_default, nullptr},
294         {"schedGetparam", nullptr, SchedGetparam, nullptr, nullptr, nullptr, napi_default, nullptr},
295     };
296     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
297     return exports;
298 }
299 EXTERN_C_END
300 
301 static napi_module demoModule = {
302     .nm_version = 1,
303     .nm_flags = 0,
304     .nm_filename = nullptr,
305     .nm_register_func = Init,
306     .nm_modname = "sched",
307     .nm_priv = ((void *)0),
308     .reserved = {0},
309 };
310 
RegisterModule(void)311 extern "C" __attribute__((constructor)) void RegisterModule(void) { napi_module_register(&demoModule); }