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