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