1 /*
2 * Copyright (c) 2025 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 <native_fence/native_fence.h>
18
19 #include <chrono>
20 #include <cstring>
21 #include <cerrno>
22 #include <fcntl.h>
23 #include <iostream>
24 #include <csignal>
25 #include <sys/ioctl.h>
26 #include <sys/signalfd.h>
27 #include <thread>
28 #include <unistd.h>
29 #include "common/log_common.h"
30
31 #define SUCCESS 0
32 #define FAIL (-1)
33
34 constexpr int INVALID_FD = -1;
35 constexpr uint32_t TIMEOUT_ZE = 0;
36 constexpr uint32_t TIMEOUT_FH = 500;
37 constexpr uint32_t TIMEOUT_FT = 5000;
38
NativeFenceWaitIs0(napi_env env,napi_callback_info info)39 static napi_value NativeFenceWaitIs0(napi_env env, napi_callback_info info)
40 {
41 napi_value res = nullptr;
42 bool result = OH_NativeFence_Wait(INVALID_FD, TIMEOUT_FT);
43 if (result) {
44 napi_create_int32(env, 1, &res); // 1 Mark the incorrect location
45 return res;
46 }
47 bool isValid = OH_NativeFence_IsValid(INVALID_FD);
48 if (isValid) {
49 napi_create_int32(env, 2, &res); // 2 Mark the incorrect location
50 return res;
51 }
52 sigset_t mask;
53 sigemptyset(&mask);
54 sigaddset(&mask, SIGINT); // Monitor SIGINT signal (Ctrl C)
55 sigaddset(&mask, SIGURG); // Monitor SIGURG signal (Emergency event)
56 sigprocmask(SIG_BLOCK, &mask, nullptr);
57 int sfd = signalfd(-1, &mask, 0);
58 if (sfd == -1) {
59 perror("signalfd failed");
60 exit(1);
61 }
62 isValid = OH_NativeFence_IsValid(sfd);
63 if (!isValid) {
64 napi_create_int32(env, 3, &res); // 3 Mark the incorrect location
65 return res;
66 }
67 bool result2 = false;
68 result2 = OH_NativeFence_Wait(sfd, TIMEOUT_ZE);
69 if (result2) {
70 napi_create_int32(env, 4, &res); // 4 Mark the incorrect location
71 return res;
72 }
73 OH_NativeFence_Close(sfd);
74 napi_create_int32(env, SUCCESS, &res);
75 return res;
76 }
77
NativeFenceWaitIs500(napi_env env,napi_callback_info info)78 static napi_value NativeFenceWaitIs500(napi_env env, napi_callback_info info)
79 {
80 napi_value res = nullptr;
81 sigset_t mask;
82 sigemptyset(&mask);
83 sigaddset(&mask, SIGINT); // Monitor SIGINT signal (Ctrl C)
84 sigaddset(&mask, SIGURG); // Monitor SIGURG signal (Emergency event)
85 sigprocmask(SIG_BLOCK, &mask, nullptr);
86 int sfd = signalfd(-1, &mask, 0);
87 if (sfd == -1) {
88 perror("signalfd failed");
89 exit(1);
90 }
91 bool isValid = OH_NativeFence_IsValid(sfd);
92 if (!isValid) {
93 napi_create_int32(env, 1, &res); // 1 Mark the incorrect location
94 return res;
95 }
96 bool result2 = false;
97 result2 = OH_NativeFence_Wait(sfd, TIMEOUT_FH);
98 if (result2) {
99 napi_create_int32(env, 2, &res); // 2 Mark the incorrect location
100 return res;
101 }
102 OH_NativeFence_Close(sfd);
103 napi_create_int32(env, SUCCESS, &res);
104 return res;
105 }
106
NativeFenceWaitIs5000(napi_env env,napi_callback_info info)107 static napi_value NativeFenceWaitIs5000(napi_env env, napi_callback_info info)
108 {
109 napi_value res = nullptr;
110 sigset_t mask;
111 sigemptyset(&mask);
112 sigaddset(&mask, SIGINT); // Monitor SIGINT signal (Ctrl C)
113 sigaddset(&mask, SIGURG); // Monitor SIGURG signal (Emergency event)
114 sigprocmask(SIG_BLOCK, &mask, nullptr);
115 int sfd = signalfd(-1, &mask, 0);
116 if (sfd == -1) {
117 perror("signalfd failed");
118 exit(1);
119 }
120 bool isValid = OH_NativeFence_IsValid(sfd);
121 if (!isValid) {
122 napi_create_int32(env, 1, &res); // 1 Mark the incorrect location
123 return res;
124 }
125 bool result2 = false;
126 result2 = OH_NativeFence_Wait(sfd, TIMEOUT_FT);
127 if (result2) {
128 napi_create_int32(env, 2, &res); // 2 Mark the incorrect location
129 return res;
130 }
131 OH_NativeFence_Close(sfd);
132 napi_create_int32(env, SUCCESS, &res);
133 return res;
134 }
135
NativeFenceWaitKill(napi_env env,napi_callback_info info)136 static napi_value NativeFenceWaitKill(napi_env env, napi_callback_info info)
137 {
138 napi_value res = nullptr;
139 std::atomic<bool> signaled(false);
140 sigset_t mask;
141 sigemptyset(&mask);
142 sigaddset(&mask, SIGINT); // Monitor SIGINT signal (Ctrl C)
143 sigaddset(&mask, SIGURG); // Monitor SIGURG signal (Emergency event)
144 sigprocmask(SIG_BLOCK, &mask, nullptr);
145 int sfd = signalfd(-1, &mask, 0);
146 if (sfd == -1) {
147 perror("signalfd failed");
148 exit(1);
149 }
150 bool result = false;
151 std::thread waitThread([&result, sfd, &signaled]() {
152 result = OH_NativeFence_Wait(sfd, TIMEOUT_FT);
153 signaled.store(true);
154 });
155 std::this_thread::sleep_for(std::chrono::seconds(3)); // 3 means main thread sleep 3 seconds.
156 pthread_kill(waitThread.native_handle(), SIGURG);
157 // Waiting for waitThread to complete
158 waitThread.join();
159 bool isValid = OH_NativeFence_IsValid(sfd);
160 if (!isValid) {
161 napi_create_int32(env, 1, &res); // 1 Mark the incorrect location
162 return res;
163 }
164 if (!result) {
165 napi_create_int32(env, 2, &res); // 2 Mark the incorrect location
166 return res;
167 }
168 // checks the signaled variable to ensure that OH_NativeFence_Wait has returned
169 if (!signaled.load()) {
170 napi_create_int32(env, FAIL, &res);
171 return res;
172 }
173 OH_NativeFence_Close(sfd);
174 napi_create_int32(env, SUCCESS, &res);
175 return res;
176 }
177
NativeFenceWaitForeverKill(napi_env env,napi_callback_info info)178 static napi_value NativeFenceWaitForeverKill(napi_env env, napi_callback_info info)
179 {
180 napi_value res = nullptr;
181 bool result = OH_NativeFence_WaitForever(INVALID_FD);
182 if (result) {
183 napi_create_int32(env, 1, &res); // 1 Mark the incorrect location
184 return res;
185 }
186 std::atomic<bool> signaled(false);
187 sigset_t mask;
188 sigemptyset(&mask);
189 sigaddset(&mask, SIGINT); // Monitor SIGINT signal (Ctrl C)
190 sigaddset(&mask, SIGTTIN); // Monitor SIGURG signal (The background job reads data from the user terminal)
191 sigprocmask(SIG_BLOCK, &mask, nullptr);
192 int sfd = signalfd(-1, &mask, 0);
193 if (sfd == -1) {
194 perror("signalfd failed");
195 exit(1);
196 }
197 bool result2 = false;
198 std::thread waitThread([&result2, sfd, &signaled]() {
199 result2 = OH_NativeFence_WaitForever(sfd);
200 signaled.store(true);
201 });
202 std::this_thread::sleep_for(std::chrono::seconds(3)); // 3 means main thread sleep 3 seconds.
203 pthread_kill(waitThread.native_handle(), SIGTTIN);
204 // Waiting for waitThread to complete
205 waitThread.join();
206 if (!result2) {
207 napi_create_int32(env, 1, &res); // 1 Mark the incorrect location
208 return res;
209 }
210 bool isValid = OH_NativeFence_IsValid(sfd);
211 if (!isValid) {
212 napi_create_int32(env, 2, &res); // 2 Mark the incorrect location
213 return res;
214 }
215 // checks the signaled variable to ensure that OH_NativeFence_Wait has returned
216 if (!signaled.load()) {
217 napi_create_int32(env, FAIL, &res);
218 return res;
219 }
220 OH_NativeFence_Close(sfd);
221 napi_create_int32(env, SUCCESS, &res);
222 return res;
223 }
224
225 // EXTERN_C_START
Init(napi_env env,napi_value exports)226 static napi_value Init(napi_env env, napi_value exports)
227 {
228 napi_property_descriptor desc[] = {
229 { "nativeFenceWaitIs0", nullptr, NativeFenceWaitIs0, nullptr, nullptr, nullptr, napi_default, nullptr },
230 { "nativeFenceWaitIs500", nullptr, NativeFenceWaitIs500, nullptr, nullptr, nullptr, napi_default, nullptr },
231 { "nativeFenceWaitIs5000", nullptr, NativeFenceWaitIs5000, nullptr, nullptr, nullptr, napi_default, nullptr },
232 { "nativeFenceWaitKill", nullptr, NativeFenceWaitKill, nullptr, nullptr, nullptr, napi_default, nullptr },
233 { "nativeFenceWaitForeverKill", nullptr,
234 NativeFenceWaitForeverKill, nullptr, nullptr, nullptr, napi_default, nullptr },
235 };
236 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
237 return exports;
238 }
239 // EXTERN_C_END
240
241 static napi_module demoModule = {
242 .nm_version = 1,
243 .nm_flags = 0,
244 .nm_filename = nullptr,
245 .nm_register_func = Init,
246 .nm_modname = "nativefence",
247 .nm_priv = ((void*)0),
248 .reserved = { 0 },
249 };
250
RegisterEntryModule(void)251 extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
252 {
253 napi_module_register(&demoModule);
254 }