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 "napi/native_api.h"
17 #include <cstdlib>
18 #include <ctime>
19 #include <pthread.h>
20 #include <semaphore.h>
21 #include <sys/resource.h>
22 #include <threads.h>
23 #include <unistd.h>
24
25 #define TEST_RESULT_PASSED 0
26 #define TEST_RESULT_FAILED (-1)
27 #define PARAM_5 5
28 #define PARAM_0 0
29 #define PARAM_1 1
30 #define PARAM_2 2
31 #define PARAM_500 500
32 #define PARAM_1000 1000
33 #define PARAM_UNNORMAL (-1)
34 #define ETIMEDOUTS 110
35
36 struct cndTimedWaitTime64Param {
37 cnd_t cnd;
38 mtx_t mutex;
39 unsigned sleep;
40 };
41
CndTimedWaitTime64Thread(void * arg)42 static int CndTimedWaitTime64Thread(void *arg)
43 {
44 struct cndTimedWaitTime64Param *pparam = (cndTimedWaitTime64Param *)arg;
45
46 mtx_lock(&(pparam->mutex));
47 if (pparam->sleep > PARAM_0) {
48 sleep(pparam->sleep);
49 }
50 cnd_signal(&(pparam->cnd));
51 mtx_unlock(&(pparam->mutex));
52
53 thrd_exit(thrd_success);
54 }
55
56 extern "C" int __cnd_timedwait_time64(cnd_t *__restrict, mtx_t *__restrict, const struct timespec *__restrict);
Cnd_timedWait_time64_One(napi_env env,napi_callback_info info)57 static napi_value Cnd_timedWait_time64_One(napi_env env, napi_callback_info info)
58 {
59 int ret = TEST_RESULT_FAILED;
60 thrd_t id;
61 struct cndTimedWaitTime64Param param;
62 struct timespec ts {};
63
64 ret = cnd_init(&(param.cnd));
65 mtx_init(&(param.mutex), mtx_plain);
66 mtx_lock(&(param.mutex));
67 param.sleep = PARAM_0;
68 clock_gettime(CLOCK_REALTIME, &ts);
69 ts.tv_sec += PARAM_1;
70
71 thrd_create(&id, CndTimedWaitTime64Thread, ¶m);
72 ret = __cnd_timedwait_time64(&(param.cnd), &(param.mutex), &ts);
73 thrd_join(id, nullptr);
74
75 mtx_unlock(&(param.mutex));
76 mtx_destroy(&(param.mutex));
77 cnd_destroy(&(param.cnd));
78
79 napi_value result = nullptr;
80 napi_create_int32(env, ret, &result);
81 return result;
82 }
83
Cnd_timedWait_time64_Two(napi_env env,napi_callback_info info)84 static napi_value Cnd_timedWait_time64_Two(napi_env env, napi_callback_info info)
85 {
86 int ret = TEST_RESULT_FAILED;
87 thrd_t id;
88 struct cndTimedWaitTime64Param param;
89 struct timespec ts {};
90
91 ret = cnd_init(&(param.cnd));
92 mtx_init(&(param.mutex), mtx_plain);
93 mtx_lock(&(param.mutex));
94 param.sleep = PARAM_2;
95 clock_gettime(CLOCK_REALTIME, &ts);
96 ts.tv_sec += PARAM_1;
97
98 thrd_create(&id, CndTimedWaitTime64Thread, ¶m);
99 ret = __cnd_timedwait_time64(&(param.cnd), &(param.mutex), &ts);
100 thrd_join(id, nullptr);
101
102 mtx_unlock(&(param.mutex));
103 mtx_destroy(&(param.mutex));
104 cnd_destroy(&(param.cnd));
105
106 napi_value result = nullptr;
107 napi_create_int32(env, ret, &result);
108 return result;
109 }
110
111 extern "C" pid_t __wait4_time64(pid_t, int *, int, struct rusage *);
Wait4_time64_One(napi_env env,napi_callback_info info)112 static napi_value Wait4_time64_One(napi_env env, napi_callback_info info)
113 {
114 int ret = TEST_RESULT_FAILED;
115 pid_t pid = fork();
116 if (pid > PARAM_0) {
117 int status = PARAM_0;
118 int options = PARAM_0;
119 struct rusage ru;
120 pid_t wait4ForPid = __wait4_time64(pid, &status, options, &ru);
121 if (wait4ForPid == pid && status == PARAM_0) {
122 ret = TEST_RESULT_PASSED;
123 }
124 } else {
125 sleep(PARAM_1);
126 exit(PARAM_0);
127 }
128
129 napi_value result = nullptr;
130 napi_create_int32(env, ret, &result);
131 return result;
132 }
133
Wait4_time64_Two(napi_env env,napi_callback_info info)134 static napi_value Wait4_time64_Two(napi_env env, napi_callback_info info)
135 {
136 int ret = TEST_RESULT_FAILED;
137 pid_t pid = fork();
138 if (pid > PARAM_0) {
139 int status = PARAM_0;
140 int options = PARAM_0;
141 struct rusage ru;
142 sleep(PARAM_1);
143 pid_t wait4ForPid = __wait4_time64(pid, &status, options, &ru);
144 if (wait4ForPid == pid && status == PARAM_0) {
145 ret = TEST_RESULT_PASSED;
146 }
147 } else {
148 sleep(PARAM_0);
149 exit(PARAM_0);
150 }
151
152 napi_value result = nullptr;
153 napi_create_int32(env, ret, &result);
154 return result;
155 }
156
157 #define NSEC_PER_SEC 1000000000
158 #define NSEC_PER_MSEC 1000000
159 #define MS_PER_S 1000
160 #define SLEEP_10_MS 10
161 #define SLEEP_100_MS 100
162 struct pthreadCondTimedwaitTime64Param {
163 pthread_cond_t cond;
164 pthread_mutex_t mutex;
165 };
166 extern "C" int __pthread_cond_timedwait_time64(pthread_cond_t *__restrict, pthread_mutex_t *__restrict,
167 const struct timespec *__restrict);
PThreadCondTimedWaitTime64Thread(void * arg)168 static void *PThreadCondTimedWaitTime64Thread(void *arg)
169 {
170 struct pthreadCondTimedwaitTime64Param *pparam = (pthreadCondTimedwaitTime64Param *)arg;
171 struct timespec ts {};
172 pthread_mutex_lock(&(pparam->mutex));
173 clock_gettime(CLOCK_REALTIME, &ts);
174 ts.tv_nsec += SLEEP_100_MS * NSEC_PER_MSEC;
175 if (ts.tv_nsec >= NSEC_PER_SEC) {
176 ts.tv_nsec -= NSEC_PER_SEC;
177 ts.tv_sec += PARAM_1;
178 }
179 int ret = __pthread_cond_timedwait_time64(&(pparam->cond), &(pparam->mutex), &ts);
180 pthread_mutex_unlock(&(pparam->mutex));
181 return (void *)ret;
182 }
183
PThread_cond_timedWait_time64_One(napi_env env,napi_callback_info info)184 static napi_value PThread_cond_timedWait_time64_One(napi_env env, napi_callback_info info)
185 {
186 struct pthreadCondTimedwaitTime64Param param;
187 pthread_t threadId;
188 struct timespec ts {
189 PARAM_0, SLEEP_10_MS *NSEC_PER_MSEC
190 };
191 int ret = TEST_RESULT_FAILED;
192 param.cond = PTHREAD_COND_INITIALIZER;
193 param.mutex = PTHREAD_MUTEX_INITIALIZER;
194 pthread_create(&threadId, nullptr, PThreadCondTimedWaitTime64Thread, ¶m);
195 nanosleep(&ts, nullptr);
196 pthread_mutex_lock(¶m.mutex);
197 pthread_cond_signal(¶m.cond);
198 pthread_mutex_unlock(¶m.mutex);
199 pthread_join(threadId, (void **)&ret);
200 pthread_cond_destroy(¶m.cond);
201 pthread_mutex_destroy(¶m.mutex);
202 napi_value result = nullptr;
203 napi_create_int32(env, ret, &result);
204 return result;
205 }
206
PThread_cond_timedWait_time64_Two(napi_env env,napi_callback_info info)207 static napi_value PThread_cond_timedWait_time64_Two(napi_env env, napi_callback_info info)
208 {
209 struct pthreadCondTimedwaitTime64Param param;
210 pthread_t threadId;
211 int ret = TEST_RESULT_FAILED;
212 param.cond = PTHREAD_COND_INITIALIZER;
213 param.mutex = PTHREAD_MUTEX_INITIALIZER;
214 pthread_create(&threadId, nullptr, PThreadCondTimedWaitTime64Thread, ¶m);
215 pthread_join(threadId, (void **)&ret);
216 pthread_cond_destroy(¶m.cond);
217 pthread_mutex_destroy(¶m.mutex);
218 napi_value result = nullptr;
219 napi_create_int32(env, ret != ETIMEDOUTS, &result);
220 return result;
221 }
222
223 extern "C" int __sem_timedwait_time64(sem_t *__restrict, const struct timespec *__restrict);
SemTimedWaitTime64Thread(void * arg)224 static void *SemTimedWaitTime64Thread(void *arg)
225 {
226 sem_t *psem = (sem_t *)arg;
227 struct timespec ts;
228 clock_gettime(CLOCK_REALTIME, &ts);
229 ts.tv_sec += PARAM_1;
230 int ret = __sem_timedwait_time64(psem, &ts);
231 return (void *)ret;
232 }
233
Sem_timedWait_time64(napi_env env,napi_callback_info info)234 static napi_value Sem_timedWait_time64(napi_env env, napi_callback_info info)
235 {
236 int ret = PARAM_UNNORMAL;
237 pthread_t threadId;
238 sem_t sem;
239 sem_init(&sem, PARAM_0, PARAM_0);
240 pthread_create(&threadId, nullptr, SemTimedWaitTime64Thread, &sem);
241 usleep(PARAM_500 * PARAM_1000);
242 sem_post(&sem);
243 pthread_join(threadId, (void **)&ret);
244 sem_destroy(&sem);
245 napi_value result = nullptr;
246 napi_create_int32(env, ret, &result);
247 return result;
248 }
249
250 EXTERN_C_START
Init(napi_env env,napi_value exports)251 static napi_value Init(napi_env env, napi_value exports)
252 {
253 napi_property_descriptor desc[] = {
254 {"__cnd_timedwait_time64_One", nullptr, Cnd_timedWait_time64_One, nullptr, nullptr, nullptr, napi_default,
255 nullptr},
256 {"__cnd_timedwait_time64_Two", nullptr, Cnd_timedWait_time64_Two, nullptr, nullptr, nullptr, napi_default,
257 nullptr},
258 {"__wait4_time64_One", nullptr, Wait4_time64_One, nullptr, nullptr, nullptr, napi_default, nullptr},
259 {"__wait4_time64_Two", nullptr, Wait4_time64_Two, nullptr, nullptr, nullptr, napi_default, nullptr},
260 {"__pthread_cond_timedwait_time64_One", nullptr, PThread_cond_timedWait_time64_One, nullptr, nullptr, nullptr,
261 napi_default, nullptr},
262 {"__pthread_cond_timedwait_time64_Two", nullptr, PThread_cond_timedWait_time64_Two, nullptr, nullptr, nullptr,
263 napi_default, nullptr},
264 {"__sem_timedwait_time64", nullptr, Sem_timedWait_time64, nullptr, nullptr, nullptr, napi_default, nullptr},
265 };
266 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
267 return exports;
268 }
269 EXTERN_C_END
270
271 static napi_module demoModule = {
272 .nm_version = 1,
273 .nm_flags = 0,
274 .nm_filename = nullptr,
275 .nm_register_func = Init,
276 .nm_modname = "libfnmatchndk1",
277 .nm_priv = ((void *)0),
278 .reserved = {0},
279 };
280
RegisterModule(void)281 extern "C" __attribute__((constructor)) void RegisterModule(void) { napi_module_register(&demoModule); }
282