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 <pthread.h>
11 #include "hdf_base.h"
12 #include "hdf_log.h"
13 #include "osal_mem.h"
14 #ifndef PTHREAD_STACK_MIN
15 #define OSAL_PTHREAD_STACK_MIN 4096
16 #else
17 #define OSAL_PTHREAD_STACK_MIN PTHREAD_STACK_MIN
18 #endif
19
20 #define HDF_LOG_TAG osal_thread
21
22 typedef void *(*PosixEntry)(void *data);
23
24 struct ThreadWrapper {
25 OsalThreadEntry threadEntry;
26 void *entryPara;
27 pthread_t id;
28 };
29 #ifdef _LINUX_USER_
30 enum {
31 OSAL_PRIORITY_LOW = 10,
32 OSAL_PRIORITY_MIDDLE = 50,
33 OSAL_PRIORITY_HIGH = 90,
34 OSAL_PRIORITY_HIGHEST = 99,
35 };
36 #else
37 enum {
38 OSAL_PRIORITY_HIGHEST = 5,
39 OSAL_PRIORITY_HIGH = 15,
40 OSAL_PRIORITY_MIDDLE = 25,
41 OSAL_PRIORITY_LOW = 30,
42 };
43 #endif
44
OsalThreadRemapSched(int priority,struct sched_param * param)45 static void OsalThreadRemapSched(int priority, struct sched_param *param)
46 {
47 if (priority == OSAL_THREAD_PRI_HIGHEST) {
48 param->sched_priority = OSAL_PRIORITY_HIGHEST;
49 } else if (priority == OSAL_THREAD_PRI_HIGH) {
50 param->sched_priority = OSAL_PRIORITY_HIGH;
51 } else if (priority == OSAL_THREAD_PRI_DEFAULT) {
52 param->sched_priority = OSAL_PRIORITY_MIDDLE;
53 } else {
54 param->sched_priority = OSAL_PRIORITY_LOW;
55 }
56 }
57
OsalThreadCreate(struct OsalThread * thread,OsalThreadEntry threadEntry,void * entryPara)58 int32_t OsalThreadCreate(struct OsalThread *thread, OsalThreadEntry threadEntry, void *entryPara)
59 {
60 struct ThreadWrapper *para = NULL;
61
62 if (thread == NULL || threadEntry == NULL) {
63 HDF_LOGE("%s invalid param", __func__);
64 return HDF_ERR_INVALID_PARAM;
65 }
66
67 thread->realThread = NULL;
68 para = (struct ThreadWrapper *)OsalMemCalloc(sizeof(*para));
69 if (para == NULL) {
70 HDF_LOGE("%s malloc fail", __func__);
71 return HDF_FAILURE;
72 }
73
74 para->entryPara = entryPara;
75 para->threadEntry = threadEntry;
76 thread->realThread = para;
77
78 return HDF_SUCCESS;
79 }
80
OsalThreadDestroy(struct OsalThread * thread)81 int32_t OsalThreadDestroy(struct OsalThread *thread)
82 {
83 if (thread != NULL && thread->realThread != NULL) {
84 OsalMemFree(thread->realThread);
85 thread->realThread = NULL;
86 }
87 return HDF_SUCCESS;
88 }
89
OsalCreatePthread(pthread_t * threadId,pthread_attr_t * attribute,struct ThreadWrapper * para)90 static int OsalCreatePthread(pthread_t *threadId, pthread_attr_t *attribute, struct ThreadWrapper *para)
91 {
92 int resultCode = pthread_create(threadId, attribute, (PosixEntry)para->threadEntry, para->entryPara);
93 if (resultCode != 0) {
94 HDF_LOGE("pthread_create errorno: %d", resultCode);
95 return resultCode;
96 }
97 resultCode = pthread_detach(*threadId);
98 if (resultCode != 0) {
99 HDF_LOGE("pthread_detach errorno: %d", resultCode);
100 return resultCode;
101 }
102 resultCode = pthread_attr_destroy(attribute);
103 if (resultCode != 0) {
104 HDF_LOGE("pthread_attr_destroy errorno: %d", resultCode);
105 return resultCode;
106 }
107 return HDF_SUCCESS;
108 }
109
OsalThreadStart(struct OsalThread * thread,const struct OsalThreadParam * param)110 int32_t OsalThreadStart(struct OsalThread *thread, const struct OsalThreadParam *param)
111 {
112 pthread_attr_t attribute;
113 struct sched_param priorityHolder;
114
115 if (thread == NULL || thread->realThread == NULL || param == NULL) {
116 HDF_LOGE("%s invalid param", __func__);
117 return HDF_ERR_INVALID_PARAM;
118 }
119
120 struct ThreadWrapper *para = (struct ThreadWrapper *)thread->realThread;
121
122 int resultCode = pthread_attr_init(&attribute);
123 if (resultCode != 0) {
124 HDF_LOGE("pthread_attr_init errorno: %d", resultCode);
125 goto DEAL_FAIL;
126 }
127
128 size_t stackSize = param->stackSize;
129 if (stackSize > 0) {
130 stackSize = (stackSize < OSAL_PTHREAD_STACK_MIN) ? OSAL_PTHREAD_STACK_MIN : stackSize;
131 resultCode = pthread_attr_setstacksize(&attribute, stackSize);
132 if (resultCode != 0) {
133 HDF_LOGE("pthread_attr_setstacksize errorno: %d", resultCode);
134 goto DEAL_FAIL;
135 }
136 }
137
138 resultCode = pthread_attr_getschedparam(&attribute, &priorityHolder);
139 if (resultCode != 0) {
140 HDF_LOGE("pthread_attr_getschedparam errorno: %d", resultCode);
141 goto DEAL_FAIL;
142 }
143
144 OsalThreadRemapSched(param->priority, &priorityHolder);
145
146 resultCode = pthread_attr_setschedparam(&attribute, &priorityHolder);
147 if (resultCode != 0) {
148 HDF_LOGE("pthread_attr_setschedparam errorno: %d", resultCode);
149 goto DEAL_FAIL;
150 }
151
152 resultCode = OsalCreatePthread(¶->id, &attribute, thread->realThread);
153 if (resultCode != 0) {
154 HDF_LOGE("OsalCreatePthread errorno: %d", resultCode);
155 goto DEAL_FAIL;
156 }
157 return HDF_SUCCESS;
158
159 DEAL_FAIL:
160 (void)OsalThreadDestroy(thread);
161 return HDF_FAILURE;
162 }
163
164