1 /*
2 * Copyright (c) 2021-2024 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 #ifndef _GNU_SOURCE
16 #define _GNU_SOURCE
17 #endif
18
19 #include "softbus_adapter_thread.h"
20
21 #include <pthread.h>
22 #include <sched.h>
23 #include <securec.h>
24 #include <string.h>
25
26 #include "softbus_adapter_mem.h"
27 #include "softbus_errcode.h"
28
29 static pthread_mutex_t g_adapterStaticLock = PTHREAD_MUTEX_INITIALIZER;
30 /* mutex */
SoftBusMutexAttrInit(SoftBusMutexAttr * mutexAttr)31 int32_t SoftBusMutexAttrInit(SoftBusMutexAttr *mutexAttr)
32 {
33 if (mutexAttr == NULL) {
34 COMM_LOGE(COMM_ADAPTER, "mutexAttr is null");
35 return SOFTBUS_INVALID_PARAM;
36 }
37
38 mutexAttr->type = SOFTBUS_MUTEX_NORMAL;
39 return SOFTBUS_OK;
40 }
41
SoftBusMutexInit(SoftBusMutex * mutex,SoftBusMutexAttr * mutexAttr)42 int32_t SoftBusMutexInit(SoftBusMutex *mutex, SoftBusMutexAttr *mutexAttr)
43 {
44 if (mutex == NULL) {
45 COMM_LOGE(COMM_ADAPTER, "mutex is null");
46 return SOFTBUS_INVALID_PARAM;
47 }
48 if (pthread_mutex_lock(&g_adapterStaticLock) != 0) {
49 COMM_LOGE(COMM_ADAPTER, "mutex init : g_adapterStaticLock lock failed");
50 return SOFTBUS_ERR;
51 }
52 if ((void *)*mutex != NULL) {
53 (void)pthread_mutex_unlock(&g_adapterStaticLock);
54 return SOFTBUS_OK;
55 }
56 pthread_mutex_t *tempMutex;
57 tempMutex = (pthread_mutex_t *)SoftBusCalloc(sizeof(pthread_mutex_t));
58 if (tempMutex == NULL) {
59 COMM_LOGE(COMM_ADAPTER, "tempMutex is null");
60 (void)pthread_mutex_unlock(&g_adapterStaticLock);
61 return SOFTBUS_INVALID_PARAM;
62 }
63
64 pthread_mutexattr_t attr;
65 pthread_mutexattr_init(&attr);
66 if (mutexAttr == NULL) {
67 #ifndef __LITEOS_M__
68 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
69 #else
70 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
71 #endif
72 } else if (mutexAttr->type == SOFTBUS_MUTEX_NORMAL) {
73 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
74 } else if (mutexAttr->type == SOFTBUS_MUTEX_RECURSIVE) {
75 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
76 }
77
78 int32_t ret = pthread_mutex_init(tempMutex, &attr);
79 if (ret != 0) {
80 COMM_LOGE(COMM_ADAPTER, "SoftBusMutexInit failed, ret=%{public}d", ret);
81 SoftBusFree(tempMutex);
82 tempMutex = NULL;
83 (void)pthread_mutex_unlock(&g_adapterStaticLock);
84 return SOFTBUS_ERR;
85 }
86
87 *mutex = (SoftBusMutex)tempMutex;
88 (void)pthread_mutex_unlock(&g_adapterStaticLock);
89 return SOFTBUS_OK;
90 }
91
SoftBusMutexLockInner(SoftBusMutex * mutex)92 int32_t SoftBusMutexLockInner(SoftBusMutex *mutex)
93 {
94 return pthread_mutex_lock((pthread_mutex_t *)*mutex);
95 }
96
SoftBusMutexUnlockInner(SoftBusMutex * mutex)97 int32_t SoftBusMutexUnlockInner(SoftBusMutex *mutex)
98 {
99 return pthread_mutex_unlock((pthread_mutex_t *)*mutex);
100 }
101
SoftBusMutexDestroy(SoftBusMutex * mutex)102 int32_t SoftBusMutexDestroy(SoftBusMutex *mutex)
103 {
104 if ((mutex == NULL) || ((void *)(*mutex) == NULL)) {
105 COMM_LOGD(COMM_ADAPTER, "mutex is null");
106 return SOFTBUS_INVALID_PARAM;
107 }
108
109 int32_t ret = pthread_mutex_destroy((pthread_mutex_t *)*mutex);
110 if (ret != 0) {
111 COMM_LOGE(COMM_ADAPTER, "SoftBusMutexDestroy failed, ret=%{public}d", ret);
112 SoftBusFree((void *)*mutex);
113 *mutex = (SoftBusMutex)NULL;
114 return SOFTBUS_ERR;
115 }
116
117 SoftBusFree((void *)*mutex);
118 *mutex = (SoftBusMutex)NULL;
119 return SOFTBUS_OK;
120 }
121
122 /* pthread */
SoftBusThreadAttrInit(SoftBusThreadAttr * threadAttr)123 int32_t SoftBusThreadAttrInit(SoftBusThreadAttr *threadAttr)
124 {
125 if (threadAttr == NULL) {
126 COMM_LOGE(COMM_ADAPTER, "threadAttr is null");
127 return SOFTBUS_INVALID_PARAM;
128 }
129
130 #ifndef __LITEOS_M__
131 threadAttr->policy = SOFTBUS_SCHED_OTHER;
132 #else
133 threadAttr->policy = SOFTBUS_SCHED_RR;
134 #endif
135 threadAttr->detachState = SOFTBUS_THREAD_JOINABLE;
136 threadAttr->stackSize = 0;
137 threadAttr->prior = SOFTBUS_PRIORITY_DEFAULT;
138 threadAttr->taskName = NULL;
139
140 return SOFTBUS_OK;
141 }
142
SoftbusSetThreadPolicy(SoftBusThreadAttr * threadAttr,pthread_attr_t * attr)143 static int32_t SoftbusSetThreadPolicy(SoftBusThreadAttr *threadAttr, pthread_attr_t *attr)
144 {
145 if (threadAttr->policy == SOFTBUS_SCHED_OTHER) {
146 pthread_attr_setschedpolicy(attr, SCHED_OTHER);
147 } else if (threadAttr->policy == SOFTBUS_SCHED_RR) {
148 pthread_attr_setschedpolicy(attr, SCHED_RR);
149 } else {
150 COMM_LOGE(COMM_ADAPTER, "set policy error");
151 return SOFTBUS_INVALID_PARAM;
152 }
153
154 return SOFTBUS_OK;
155 }
156
SoftbusSetThreadDetachState(SoftBusThreadAttr * threadAttr,pthread_attr_t * attr)157 static int32_t SoftbusSetThreadDetachState(SoftBusThreadAttr *threadAttr, pthread_attr_t *attr)
158 {
159 if (threadAttr->detachState == SOFTBUS_THREAD_JOINABLE) {
160 pthread_attr_setdetachstate(attr, PTHREAD_CREATE_JOINABLE);
161 } else if (threadAttr->detachState == SOFTBUS_THREAD_DETACH) {
162 pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED);
163 } else {
164 COMM_LOGE(COMM_ADAPTER, "set detachState error");
165 return SOFTBUS_INVALID_PARAM;
166 }
167
168 return SOFTBUS_OK;
169 }
170
SoftbusSetThreadPeriority(SoftBusThreadAttr * threadAttr,pthread_attr_t * attr)171 static int32_t SoftbusSetThreadPeriority(SoftBusThreadAttr *threadAttr, pthread_attr_t *attr)
172 {
173 #ifdef __linux__
174 /* periorityParam is between 1 and 99 in linux */
175 #define PTHREAD_PERIOR_LOWEST 1
176 #define PTHREAD_PERIOR_LOW 33
177 #define PTHREAD_PERIOR_HIGH 66
178 #define PTHREAD_PERIOR_HIGHEST 99
179 #else
180 /* periorityParam is between 0 and 31 in liteOS */
181 #define PTHREAD_PERIOR_LOWEST 30
182 #define PTHREAD_PERIOR_LOW 20
183 #define PTHREAD_PERIOR_HIGH 10
184 #define PTHREAD_PERIOR_HIGHEST 0
185 #endif
186
187 struct sched_param periorityParam;
188 (void)memset_s(&periorityParam, sizeof(periorityParam), 0, sizeof(periorityParam));
189 struct sched_param defaultPeri;
190 pthread_attr_getschedparam(attr, &defaultPeri);
191 switch (threadAttr->prior) {
192 case SOFTBUS_PRIORITY_DEFAULT:
193 periorityParam.sched_priority = defaultPeri.sched_priority;
194 break;
195 case SOFTBUS_PRIORITY_LOWEST:
196 periorityParam.sched_priority = PTHREAD_PERIOR_LOWEST;
197 break;
198 case SOFTBUS_PRIORITY_LOW:
199 periorityParam.sched_priority = PTHREAD_PERIOR_LOW;
200 break;
201 case SOFTBUS_PRIORITY_HIGH:
202 periorityParam.sched_priority = PTHREAD_PERIOR_HIGH;
203 break;
204 case SOFTBUS_PRIORITY_HIGHEST:
205 periorityParam.sched_priority = PTHREAD_PERIOR_HIGHEST;
206 break;
207 default:
208 periorityParam.sched_priority = defaultPeri.sched_priority;
209 break;
210 }
211 pthread_attr_setschedparam(attr, &periorityParam);
212
213 return SOFTBUS_OK;
214 }
215
SoftBusConfTransPthreadAttr(SoftBusThreadAttr * threadAttr,pthread_attr_t * attr)216 static int32_t SoftBusConfTransPthreadAttr(SoftBusThreadAttr *threadAttr, pthread_attr_t *attr)
217 {
218 if ((threadAttr == NULL) || (attr == NULL)) {
219 COMM_LOGE(COMM_ADAPTER, "threadAttr or attr is null");
220 return SOFTBUS_INVALID_PARAM;
221 }
222
223 int32_t ret = SoftbusSetThreadPolicy(threadAttr, attr);
224 if (ret != SOFTBUS_OK) {
225 COMM_LOGE(COMM_ADAPTER, "SoftbusSetThreadPolicy failed, ret=%{public}d", ret);
226 return SOFTBUS_ERR;
227 }
228
229 ret = SoftbusSetThreadDetachState(threadAttr, attr);
230 if (ret != SOFTBUS_OK) {
231 COMM_LOGE(COMM_ADAPTER, "SoftbusSetThreadDetachState failed, ret=%{public}d", ret);
232 return SOFTBUS_ERR;
233 }
234
235 ret = SoftbusSetThreadPeriority(threadAttr, attr);
236 if (ret != SOFTBUS_OK) {
237 COMM_LOGE(COMM_ADAPTER, "SoftbusSetThreadPeriority failed, ret=%{public}d", ret);
238 return SOFTBUS_ERR;
239 }
240
241 uint64_t stackSize = threadAttr->stackSize;
242 if (stackSize != 0) {
243 ret = pthread_attr_setstacksize(attr, stackSize);
244 if (ret != 0) {
245 COMM_LOGE(COMM_ADAPTER, "pthread_attr_setstacksize failed, ret=%{public}d", ret);
246 return SOFTBUS_ERR;
247 }
248 }
249
250 return SOFTBUS_OK;
251 }
252
SoftBusThreadCreate(SoftBusThread * thread,SoftBusThreadAttr * threadAttr,void * (* threadEntry)(void *),void * arg)253 int32_t SoftBusThreadCreate(SoftBusThread *thread, SoftBusThreadAttr *threadAttr,
254 void *(*threadEntry) (void *), void *arg)
255 {
256 if (thread == NULL) {
257 COMM_LOGE(COMM_ADAPTER, "thread is null");
258 return SOFTBUS_INVALID_PARAM;
259 }
260
261 if (threadEntry == NULL) {
262 COMM_LOGE(COMM_ADAPTER, "threadEntry is null");
263 return SOFTBUS_INVALID_PARAM;
264 }
265
266 int32_t ret;
267 if (threadAttr == NULL) {
268 ret = pthread_create((pthread_t *)thread, NULL, threadEntry, arg);
269 if (ret != 0) {
270 COMM_LOGE(COMM_ADAPTER, "Thread create failed, ret=%{public}d", ret);
271 return SOFTBUS_ERR;
272 }
273 } else {
274 pthread_attr_t attr;
275 ret = pthread_attr_init(&attr);
276 if (ret != 0) {
277 COMM_LOGE(COMM_ADAPTER, "pthread_attr_init failed, ret=%{public}d", ret);
278 return SOFTBUS_ERR;
279 }
280 ret = SoftBusConfTransPthreadAttr(threadAttr, &attr);
281 if (ret != 0) {
282 COMM_LOGE(COMM_ADAPTER, "SoftBusConfTransPthreadAttr failed, ret=%{public}d", ret);
283 return SOFTBUS_ERR;
284 }
285 ret = pthread_create((pthread_t *)thread, &attr, threadEntry, arg);
286 if (ret != 0) {
287 COMM_LOGE(COMM_ADAPTER, "Thread create failed, ret=%{public}d", ret);
288 return SOFTBUS_ERR;
289 }
290
291 if (threadAttr->taskName != NULL) {
292 ret = SoftBusThreadSetName(*thread, threadAttr->taskName);
293 if (ret != 0) {
294 COMM_LOGE(COMM_ADAPTER, "Thread set name failed, ret=%{public}d", ret);
295 }
296 }
297 }
298
299 return SOFTBUS_OK;
300 }
301
SoftBusThreadJoin(SoftBusThread thread,void ** value)302 int32_t SoftBusThreadJoin(SoftBusThread thread, void **value)
303 {
304 if (thread <= 0) {
305 COMM_LOGE(COMM_ADAPTER, "thread is invalid");
306 return SOFTBUS_INVALID_PARAM;
307 }
308
309 int32_t ret = pthread_join((pthread_t)thread, value);
310 if (ret != 0) {
311 COMM_LOGE(COMM_ADAPTER, "Thread join failed, ret=%{public}d", ret);
312 return SOFTBUS_ERR;
313 }
314
315 return SOFTBUS_OK;
316 }
317
SoftBusThreadSetName(SoftBusThread thread,const char * name)318 int32_t SoftBusThreadSetName(SoftBusThread thread, const char *name)
319 {
320 if (thread <= 0) {
321 COMM_LOGE(COMM_ADAPTER, "thread is invalid");
322 return SOFTBUS_INVALID_PARAM;
323 }
324
325 if (name == NULL) {
326 COMM_LOGE(COMM_ADAPTER, "name is null");
327 return SOFTBUS_INVALID_PARAM;
328 }
329
330 if (strlen(name) >= TASK_NAME_MAX_LEN) {
331 COMM_LOGE(COMM_ADAPTER, "set thread name length >= TASK_NAME_MAX_LEN");
332 return SOFTBUS_INVALID_PARAM;
333 }
334 int32_t ret = pthread_setname_np((pthread_t)thread, name);
335 if (ret != 0) {
336 COMM_LOGE(COMM_ADAPTER, "Thread set name failed, ret=%{public}d", ret);
337 return SOFTBUS_ERR;
338 }
339
340 return SOFTBUS_OK;
341 }
342
SoftBusThreadGetSelf(void)343 SoftBusThread SoftBusThreadGetSelf(void)
344 {
345 return (SoftBusThread)pthread_self();
346 }
347
348 /* cond */
SoftBusCondInit(SoftBusCond * cond)349 int32_t SoftBusCondInit(SoftBusCond *cond)
350 {
351 if (cond == NULL) {
352 COMM_LOGE(COMM_ADAPTER, "cond is null");
353 return SOFTBUS_INVALID_PARAM;
354 }
355 pthread_condattr_t attr = {0};
356 int32_t ret = pthread_condattr_init(&attr);
357 if (ret != 0) {
358 COMM_LOGE(COMM_ADAPTER, "pthread_condattr_init failed, ret=%{public}d", ret);
359 return SOFTBUS_ERR;
360 }
361 ret = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
362 if (ret != 0) {
363 COMM_LOGE(COMM_ADAPTER, "set clock failed, ret=%{public}d", ret);
364 return SOFTBUS_ERR;
365 }
366
367 pthread_cond_t *tempCond = (pthread_cond_t *)SoftBusCalloc(sizeof(pthread_cond_t));
368 if (tempCond == NULL) {
369 COMM_LOGE(COMM_ADAPTER, "tempCond is null");
370 return SOFTBUS_ERR;
371 }
372 ret = pthread_cond_init(tempCond, &attr);
373 if (ret != 0) {
374 COMM_LOGE(COMM_ADAPTER, "SoftBusCondInit failed, ret=%{public}d", ret);
375 SoftBusFree(tempCond);
376 tempCond = NULL;
377 return SOFTBUS_ERR;
378 }
379
380 *cond = (SoftBusCond)tempCond;
381 return SOFTBUS_OK;
382 }
383
SoftBusCondSignal(SoftBusCond * cond)384 int32_t SoftBusCondSignal(SoftBusCond *cond)
385 {
386 if ((cond == NULL) || ((void *)(*cond) == NULL)) {
387 COMM_LOGE(COMM_ADAPTER, "cond is null");
388 return SOFTBUS_INVALID_PARAM;
389 }
390
391 int32_t ret = pthread_cond_signal((pthread_cond_t *)*cond);
392 if (ret != 0) {
393 COMM_LOGE(COMM_ADAPTER, "SoftBusCondSignal failed, ret=%{public}d", ret);
394 return SOFTBUS_ERR;
395 }
396
397 return SOFTBUS_OK;
398 }
399
SoftBusCondBroadcast(SoftBusCond * cond)400 int32_t SoftBusCondBroadcast(SoftBusCond *cond)
401 {
402 if ((cond == NULL) || ((void *)(*cond) == NULL)) {
403 COMM_LOGE(COMM_ADAPTER, "cond is null");
404 return SOFTBUS_INVALID_PARAM;
405 }
406
407 int32_t ret = pthread_cond_broadcast((pthread_cond_t *)*cond);
408 if (ret != 0) {
409 COMM_LOGE(COMM_ADAPTER, "SoftBusCondBroadcast failed, ret=%{public}d", ret);
410 return SOFTBUS_ERR;
411 }
412
413 return SOFTBUS_OK;
414 }
415
SoftBusCondWait(SoftBusCond * cond,SoftBusMutex * mutex,SoftBusSysTime * time)416 int32_t SoftBusCondWait(SoftBusCond *cond, SoftBusMutex *mutex, SoftBusSysTime *time)
417 {
418 #define USECTONSEC 1000
419 if ((cond == NULL) || ((void *)(*cond) == NULL)) {
420 COMM_LOGE(COMM_ADAPTER, "cond is null");
421 return SOFTBUS_INVALID_PARAM;
422 }
423
424 if ((mutex == NULL) || ((void *)(*mutex) == NULL)) {
425 COMM_LOGE(COMM_ADAPTER, "mutex is null");
426 return SOFTBUS_INVALID_PARAM;
427 }
428
429 int32_t ret;
430 if (time == NULL) {
431 ret = pthread_cond_wait((pthread_cond_t *)*cond, (pthread_mutex_t *)*mutex);
432 if (ret != 0) {
433 COMM_LOGE(COMM_ADAPTER, "SoftBusCondWait failed, ret=%{public}d", ret);
434 return SOFTBUS_ERR;
435 }
436 } else {
437 struct timespec tv;
438 tv.tv_sec = time->sec;
439 tv.tv_nsec = time->usec * USECTONSEC;
440 ret = pthread_cond_timedwait((pthread_cond_t *)*cond, (pthread_mutex_t *)*mutex, &tv);
441 if (ret == ETIMEDOUT) {
442 COMM_LOGD(COMM_ADAPTER, "SoftBusCondTimedWait timeout, ret=%{public}d", ret);
443 return SOFTBUS_TIMOUT;
444 }
445
446 if (ret != 0) {
447 COMM_LOGE(COMM_ADAPTER, "SoftBusCondTimedWait failed, ret=%{public}d", ret);
448 return SOFTBUS_ERR;
449 }
450 }
451
452 return SOFTBUS_OK;
453 }
454
SoftBusCondDestroy(SoftBusCond * cond)455 int32_t SoftBusCondDestroy(SoftBusCond *cond)
456 {
457 if ((cond == NULL) || ((void *)(*cond) == NULL)) {
458 COMM_LOGE(COMM_ADAPTER, "cond is null");
459 return SOFTBUS_INVALID_PARAM;
460 }
461
462 int32_t ret = pthread_cond_destroy((pthread_cond_t *)*cond);
463 if (ret != 0) {
464 COMM_LOGE(COMM_ADAPTER, "SoftBusCondDestroy failed, ret=%{public}d", ret);
465 SoftBusFree((void *)*cond);
466 *cond = (SoftBusCond)NULL;
467 return SOFTBUS_ERR;
468 }
469
470 SoftBusFree((void *)*cond);
471 *cond = (SoftBusCond)NULL;
472 return SOFTBUS_OK;
473 }
474