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(¶->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