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 <cstring>
17 #include <fcntl.h>
18 #include <js_native_api.h>
19 #include <js_native_api_types.h>
20 #include <node_api.h>
21 #include <pthread.h>
22 #include <sched.h>
23 #include <semaphore.h>
24 #include <sys/stat.h>
25 
26 #define ONEHUNDRED 100
27 #define TWOHUNDRED 200
28 #define THOUSAND 1000
29 #define ONE 1
30 #define FLAG (0644)
31 #define PARAM_0 0
32 #define PARAM_1 1
33 #define ONEVAL 1
34 #define MINUSONE (-1)
35 #define VALUE100 100
36 #define VALUE200 200
37 #define MINUSVALUE1000 (-1000)
38 #define TEST_MODE 0777
39 #define FLAGS (0600)
40 
SemGetvalue(napi_env env, napi_callback_info info)41 static napi_value SemGetvalue(napi_env env, napi_callback_info info)
42 {
43     size_t argc = PARAM_1;
44     napi_value args[1] = {nullptr};
45     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
46     int first = PARAM_0;
47     napi_get_value_int32(env, args[0], &first);
48     sem_t semp = {PARAM_0};
49     int ret = sem_getvalue(&semp, &first);
50     sem_destroy(&semp);
51     napi_value result = nullptr;
52     napi_create_int32(env, ret, &result);
53     return result;
54 }
55 
SemOpen(napi_env env, napi_callback_info info)56 static napi_value SemOpen(napi_env env, napi_callback_info info)
57 {
58     char name[] = "/testsemopen";
59     size_t argc = PARAM_1;
60     napi_value args[1] = {nullptr};
61     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
62     int param;
63     napi_get_value_int32(env, args[0], &param);
64 
65     int ret;
66     sem_t *semFirst = sem_open(name, O_CREAT, TEST_MODE, ONE);
67     if (semFirst == nullptr || semFirst == SEM_FAILED) {
68         ret = -THOUSAND;
69     } else {
70         ret = TWOHUNDRED;
71     }
72     if (param == PARAM_0) {
73         sem_t *semSecond = sem_open(name, O_CREAT | O_EXCL, TEST_MODE, ONE);
74         if (semSecond == nullptr || semSecond == SEM_FAILED) {
75             ret = -THOUSAND;
76         } else {
77             ret = TWOHUNDRED;
78         }
79         sem_close(semSecond);
80         sem_destroy(semSecond);
81     }
82     sem_close(semFirst);
83     sem_unlink(name);
84     sem_destroy(semFirst);
85     napi_value result = nullptr;
86     napi_create_int32(env, ret, &result);
87     return result;
88 }
SemUnlink(napi_env env, napi_callback_info info)89 static napi_value SemUnlink(napi_env env, napi_callback_info info)
90 {
91     char buf[] = "mysemXXXXXX";
92     sem_open(buf, O_CREAT | O_EXCL, FLAGS, PARAM_0);
93     sem_open(buf, PARAM_0);
94     int semval = sem_unlink(buf);
95     napi_value result = nullptr;
96     napi_create_int32(env, semval, &result);
97     return result;
98 }
SemInit(napi_env env, napi_callback_info info)99 static napi_value SemInit(napi_env env, napi_callback_info info)
100 {
101     size_t argc = PARAM_1;
102     napi_value args[1] = {nullptr};
103     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
104     int first = PARAM_0;
105     napi_get_value_int32(env, args[0], &first);
106     sem_t bin_sem;
107     int ret = sem_init(&bin_sem, PARAM_0, first);
108     sem_destroy(&bin_sem);
109     napi_value result = nullptr;
110     napi_create_int32(env, ret, &result);
111     return result;
112 }
113 
114 static sem_t g_sem;
threadfuncA(void *arg)115 void *threadfuncA(void *arg)
116 {
117     sem_wait(&g_sem);
118     return arg;
119 }
120 
SemDestroy(napi_env env, napi_callback_info info)121 static napi_value SemDestroy(napi_env env, napi_callback_info info)
122 {
123     sem_t semp = {PARAM_0};
124     sem_init(&semp, PARAM_0, ONEVAL);
125     int sem = sem_destroy(&semp);
126     napi_value result = nullptr;
127     napi_create_int32(env, sem, &result);
128     return result;
129 }
130 
SemPost(napi_env env, napi_callback_info info)131 static napi_value SemPost(napi_env env, napi_callback_info info)
132 {
133     size_t argc = PARAM_1;
134     napi_value args[1] = {nullptr};
135     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
136     int first = PARAM_0;
137     napi_get_value_int32(env, args[0], &first);
138     pthread_t tid = PARAM_0;
139     sem_init(&g_sem, PARAM_0, PARAM_0);
140     pthread_create(&tid, nullptr, threadfuncA, nullptr);
141     struct sched_param sched = {PARAM_0};
142     sched.sched_priority = PARAM_0;
143     pthread_setschedparam(tid, SCHED_OTHER, &sched);
144     int semRet = sem_post(&g_sem);
145     napi_value result = nullptr;
146     napi_create_int32(env, semRet, &result);
147     return result;
148 }
149 
SemWait(napi_env env, napi_callback_info info)150 static napi_value SemWait(napi_env env, napi_callback_info info)
151 {
152     size_t argc = PARAM_1;
153     napi_value args[1] = {nullptr};
154     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
155     int first = PARAM_0;
156     napi_get_value_int32(env, args[0], &first);
157     sem_t semp = {PARAM_0};
158     sem_init(&semp, PARAM_0, first);
159     int sem = sem_wait(&semp);
160     sem_destroy(&semp);
161     napi_value result = nullptr;
162     napi_create_double(env, sem, &result);
163     return result;
164 }
165 
SemTrywait(napi_env env, napi_callback_info info)166 static napi_value SemTrywait(napi_env env, napi_callback_info info)
167 {
168     size_t argc = PARAM_1;
169     napi_value args[1] = {nullptr};
170     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
171     int first = PARAM_0;
172     napi_get_value_int32(env, args[0], &first);
173     sem_t semp = {PARAM_0};
174     sem_init(&semp, PARAM_0, first);
175     int sem = sem_trywait(&semp);
176     sem_destroy(&semp);
177     napi_value result = nullptr;
178     napi_create_double(env, sem, &result);
179     return result;
180 }
181 
SemTimedwait(napi_env env, napi_callback_info info)182 static napi_value SemTimedwait(napi_env env, napi_callback_info info)
183 {
184     size_t argc = PARAM_1;
185     napi_value args[1] = {nullptr};
186     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
187     int first = PARAM_0;
188     napi_get_value_int32(env, args[0], &first);
189     sem_t semp = {PARAM_0};
190     sem_init(&semp, PARAM_0, first);
191     struct timespec spec = {PARAM_0};
192     int sem = sem_timedwait(&semp, &spec);
193     sem_destroy(&semp);
194     napi_value result = nullptr;
195     napi_create_double(env, sem, &result);
196     return result;
197 }
SemClose(napi_env env, napi_callback_info info)198 static napi_value SemClose(napi_env env, napi_callback_info info)
199 {
200     char buf[] = "mysemXXXXXX";
201     sem_t *sem = sem_open(buf, O_CREAT | O_EXCL, FLAGS, PARAM_0);
202     sem_open(buf, PARAM_0);
203     sem_unlink(buf);
204     int semval = sem_close(sem);
205     sem_destroy(sem);
206     napi_value result = nullptr;
207     napi_create_int32(env, semval, &result);
208     return result;
209 }
210 EXTERN_C_START
Init(napi_env env, napi_value exports)211 static napi_value Init(napi_env env, napi_value exports)
212 {
213     napi_property_descriptor desc[] = {
214         {"sem_init", nullptr, SemInit, nullptr, nullptr, nullptr, napi_default, nullptr},
215         {"sem_destroy", nullptr, SemDestroy, nullptr, nullptr, nullptr, napi_default, nullptr},
216         {"sem_open", nullptr, SemOpen, nullptr, nullptr, nullptr, napi_default, nullptr},
217         {"sem_post", nullptr, SemPost, nullptr, nullptr, nullptr, napi_default, nullptr},
218         {"sem_wait", nullptr, SemWait, nullptr, nullptr, nullptr, napi_default, nullptr},
219         {"sem_timedwait", nullptr, SemTimedwait, nullptr, nullptr, nullptr, napi_default, nullptr},
220         {"sem_trywait", nullptr, SemTrywait, nullptr, nullptr, nullptr, napi_default, nullptr},
221         {"sem_getvalue", nullptr, SemGetvalue, nullptr, nullptr, nullptr, napi_default, nullptr},
222         {"sem_close", nullptr, SemClose, nullptr, nullptr, nullptr, napi_default, nullptr},
223         {"sem_unlink", nullptr, SemUnlink, nullptr, nullptr, nullptr, napi_default, nullptr},
224     };
225     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
226     return exports;
227 }
228 
229 EXTERN_C_END
230 
231 static napi_module demoModule = {
232     .nm_version = 1,
233     .nm_flags = 0,
234     .nm_filename = nullptr,
235     .nm_register_func = Init,
236     .nm_modname = "semaphore",
237     .nm_priv = ((void *)0),
238     .reserved = {0},
239 };
240 
RegisterEntryModule(void)241 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
242