• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "osal_thread.h"
10 #include <securec.h>
11 #include <pthread.h>
12 #include "hdf_base.h"
13 #include "hdf_log.h"
14 #include "osal_mem.h"
15 #ifndef PTHREAD_STACK_MIN
16 #define OSAL_PTHREAD_STACK_MIN 4096
17 #else
18 #define OSAL_PTHREAD_STACK_MIN PTHREAD_STACK_MIN
19 #endif
20 
21 #define HDF_LOG_TAG osal_thread
22 #define THREAD_NAME_LEN_MAX 16
23 
24 typedef void *(*PosixEntry)(void *data);
25 
26 struct ThreadWrapper {
27     OsalThreadEntry threadEntry;
28     void *entryPara;
29     pthread_t id;
30 };
31 #ifdef _LINUX_USER_
32 enum {
33     OSAL_PRIORITY_LOW      = 10,
34     OSAL_PRIORITY_MIDDLE   = 50,
35     OSAL_PRIORITY_HIGH     = 90,
36     OSAL_PRIORITY_HIGHEST  = 99,
37 };
38 #else
39 enum {
40     OSAL_PRIORITY_HIGHEST  = 5,
41     OSAL_PRIORITY_HIGH     = 15,
42     OSAL_PRIORITY_MIDDLE   = 25,
43     OSAL_PRIORITY_LOW      = 30,
44 };
45 #endif
46 
OsalThreadRemapSched(int priority,struct sched_param * param)47 static void OsalThreadRemapSched(int priority, struct sched_param *param)
48 {
49     if (priority == OSAL_THREAD_PRI_HIGHEST) {
50         param->sched_priority = OSAL_PRIORITY_HIGHEST;
51     } else if (priority == OSAL_THREAD_PRI_HIGH) {
52         param->sched_priority = OSAL_PRIORITY_HIGH;
53     } else if (priority == OSAL_THREAD_PRI_DEFAULT) {
54         param->sched_priority = OSAL_PRIORITY_MIDDLE;
55     } else {
56         param->sched_priority = OSAL_PRIORITY_LOW;
57     }
58 }
59 
OsalThreadCreate(struct OsalThread * thread,OsalThreadEntry threadEntry,void * entryPara)60 int32_t OsalThreadCreate(struct OsalThread *thread, OsalThreadEntry threadEntry, void *entryPara)
61 {
62     struct ThreadWrapper *para = NULL;
63 
64     if (thread == NULL || threadEntry == NULL) {
65         HDF_LOGE("%s invalid param", __func__);
66         return HDF_ERR_INVALID_PARAM;
67     }
68 
69     thread->realThread = NULL;
70     para = (struct ThreadWrapper *)OsalMemCalloc(sizeof(*para));
71     if (para == NULL) {
72         HDF_LOGE("%s malloc fail", __func__);
73         return HDF_FAILURE;
74     }
75 
76     para->entryPara = entryPara;
77     para->threadEntry = threadEntry;
78     thread->realThread = para;
79 
80     return HDF_SUCCESS;
81 }
82 
OsalThreadDestroy(struct OsalThread * thread)83 int32_t OsalThreadDestroy(struct OsalThread *thread)
84 {
85     if (thread != NULL && thread->realThread != NULL) {
86         OsalMemFree(thread->realThread);
87         thread->realThread = NULL;
88     }
89     return HDF_SUCCESS;
90 }
91 
OsalCreatePthread(pthread_t * threadId,pthread_attr_t * attribute,struct ThreadWrapper * para,char * name)92 static int OsalCreatePthread(pthread_t *threadId, pthread_attr_t *attribute, struct ThreadWrapper *para, char *name)
93 {
94     int resultCode = pthread_create(threadId, attribute, (PosixEntry)para->threadEntry, para->entryPara);
95     if (resultCode != 0) {
96         HDF_LOGE("pthread_create errorno: %d", resultCode);
97         return resultCode;
98     }
99     if (name != NULL) {
100         char threadName[THREAD_NAME_LEN_MAX] = {0};
101         resultCode = strncpy_s(threadName, THREAD_NAME_LEN_MAX, name, THREAD_NAME_LEN_MAX - 1);
102         if (resultCode == EOK) {
103             pthread_setname_np(*threadId, threadName);
104         }
105     }
106     resultCode = pthread_detach(*threadId);
107     if (resultCode != 0) {
108         HDF_LOGE("pthread_detach errorno: %d", resultCode);
109         return resultCode;
110     }
111     resultCode = pthread_attr_destroy(attribute);
112     if (resultCode != 0) {
113         HDF_LOGE("pthread_attr_destroy errorno: %d", resultCode);
114         return resultCode;
115     }
116     return HDF_SUCCESS;
117 }
118 
OsalThreadStart(struct OsalThread * thread,const struct OsalThreadParam * param)119 int32_t OsalThreadStart(struct OsalThread *thread, const struct OsalThreadParam *param)
120 {
121     pthread_attr_t attribute;
122     struct sched_param priorityHolder;
123 
124     if (thread == NULL || thread->realThread == NULL || param == NULL) {
125         HDF_LOGE("%s invalid param", __func__);
126         return HDF_ERR_INVALID_PARAM;
127     }
128 
129     struct ThreadWrapper *para = (struct ThreadWrapper *)thread->realThread;
130 
131     int resultCode = pthread_attr_init(&attribute);
132     if (resultCode != 0) {
133         HDF_LOGE("pthread_attr_init errorno: %d", resultCode);
134         goto DEAL_FAIL;
135     }
136 
137     size_t stackSize = param->stackSize;
138     if (stackSize > 0) {
139         stackSize = (stackSize < OSAL_PTHREAD_STACK_MIN) ? OSAL_PTHREAD_STACK_MIN : stackSize;
140         resultCode = pthread_attr_setstacksize(&attribute, stackSize);
141         if (resultCode != 0) {
142             HDF_LOGE("pthread_attr_setstacksize errorno: %d", resultCode);
143             goto DEAL_FAIL;
144         }
145     }
146 
147     resultCode = pthread_attr_getschedparam(&attribute, &priorityHolder);
148     if (resultCode != 0) {
149         HDF_LOGE("pthread_attr_getschedparam errorno: %d", resultCode);
150         goto DEAL_FAIL;
151     }
152 
153     OsalThreadRemapSched(param->priority, &priorityHolder);
154 
155     resultCode = pthread_attr_setschedparam(&attribute, &priorityHolder);
156     if (resultCode != 0) {
157         HDF_LOGE("pthread_attr_setschedparam errorno: %d", resultCode);
158         goto DEAL_FAIL;
159     }
160 
161     resultCode = OsalCreatePthread(&para->id, &attribute, thread->realThread, param->name);
162     if (resultCode != 0) {
163         HDF_LOGE("OsalCreatePthread errorno: %d", resultCode);
164         goto DEAL_FAIL;
165     }
166     return HDF_SUCCESS;
167 
168 DEAL_FAIL:
169     (void)OsalThreadDestroy(thread);
170     return HDF_FAILURE;
171 }
172