1 /*
2 * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2022-11-15
13 * Description: pthread mutex功能实现
14 */
15 #include "pthread.h"
16 #include "prt_posix_internal.h"
17 #include "prt_sem.h"
18 #include "prt_sem_external.h"
19
20 #define PTHREAD_MUTEX_TYPE_ISVALID(type) ((type) >= PTHREAD_MUTEX_NORMAL && (type) <= PTHREAD_MUTEX_DEFAULT)
21
22 #if defined(OS_POSIX_TYPE_NEWLIB)
23 #define MUTEX_MAGIC 0xEBU
24 typedef struct prt_pthread_mutex_s {
25 U8 type;
26 U8 magic;
27 SemHandle mutex_sem;
28 } prt_pthread_mutex_t;
29 #else
30 #define MUTEX_MAGIC 0xEBCFDEA0U
31 typedef pthread_mutex_t prt_pthread_mutex_t;
32 #endif
33
OsSemBusy(SemHandle semHandle)34 bool OsSemBusy(SemHandle semHandle)
35 {
36 struct TagSemCb *semCb = NULL;
37
38 semCb = GET_SEM(semHandle);
39 if (GET_MUTEX_TYPE(semCb->semType) != PTHREAD_MUTEX_RECURSIVE && semCb->semCount == 0 &&
40 GET_SEM_TYPE(semCb->semType) == SEM_TYPE_BIN) {
41 return TRUE;
42 } else if (GET_MUTEX_TYPE(semCb->semType) == PTHREAD_MUTEX_RECURSIVE && semCb->semCount == 0 &&
43 semCb->semOwner != RUNNING_TASK->taskPid) {
44 return TRUE;
45 }
46
47 return FALSE;
48 }
49
pthread_mutexattr_init(pthread_mutexattr_t * attr)50 int pthread_mutexattr_init(pthread_mutexattr_t *attr)
51 {
52 if (attr == NULL) {
53 return EINVAL;
54 }
55 attr->type = PTHREAD_MUTEX_DEFAULT;
56 attr->protocol = PTHREAD_PRIO_NONE;
57 attr->is_initialized = PTHREAD_ATTR_INIT;
58
59 return OS_OK;
60 }
61
pthread_mutexattr_destroy(pthread_mutexattr_t * attr)62 int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
63 {
64 U32 ret;
65
66 if (attr == NULL) {
67 return EINVAL;
68 }
69 ret = memset_s(attr, sizeof(pthread_mutexattr_t), 0, sizeof(pthread_mutexattr_t));
70 if (ret != OS_OK) {
71 OsErrRecord(ret);
72 return EINVAL;
73 }
74
75 return OS_OK;
76 }
77
PRT_PthreadMutexInit(prt_pthread_mutex_t * mutex,const pthread_mutexattr_t * attr)78 int PRT_PthreadMutexInit(prt_pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
79 {
80 U32 ret;
81 U32 protocol;
82
83 if (mutex == NULL) {
84 return EINVAL;
85 }
86
87 if (attr == NULL) {
88 mutex->type = PTHREAD_MUTEX_DEFAULT;
89 protocol = PTHREAD_PRIO_NONE;
90 } else {
91 if (attr->is_initialized != PTHREAD_ATTR_INIT) {
92 return EINVAL;
93 }
94 mutex->type = (U8)attr->type;
95 protocol = (U32)attr->protocol;
96 }
97
98 switch (mutex->type) {
99 case PTHREAD_MUTEX_NORMAL:
100 case PTHREAD_MUTEX_ERRORCHECK:
101 case PTHREAD_MUTEX_DEFAULT:
102 ret = OsSemCreate(OS_SEM_FULL, SEM_TYPE_BIN | (protocol << 8), SEM_MODE_PRIOR, &mutex->mutex_sem, (U32)&mutex->mutex_sem);
103 break;
104
105 case PTHREAD_MUTEX_RECURSIVE:
106 ret = OsSemCreate(OS_SEM_FULL, SEM_TYPE_BIN | (PTHREAD_MUTEX_RECURSIVE << 4) | (protocol << 8), SEM_MODE_PRIOR,
107 &mutex->mutex_sem, (U32)&mutex->mutex_sem);
108 break;
109
110 default:
111 ret = EINVAL;
112 break;
113 }
114
115 if (ret != OS_OK) {
116 return EINVAL;
117 }
118 mutex->magic = MUTEX_MAGIC;
119
120 return OS_OK;
121 }
122
pthread_mutex_init(pthread_mutex_t * mutex,const pthread_mutexattr_t * attr)123 int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
124 {
125 return PRT_PthreadMutexInit((prt_pthread_mutex_t *)mutex, attr);
126 }
127
OsMutexParamCheck(prt_pthread_mutex_t * mutex)128 static int OsMutexParamCheck(prt_pthread_mutex_t *mutex)
129 {
130 int ret;
131 #if !defined(OS_POSIX_TYPE_NEWLIB)
132 prt_pthread_mutex_t tmp = PTHREAD_MUTEX_INITIALIZER;
133 #endif
134
135 if (mutex == NULL) {
136 return EINVAL;
137 }
138
139 #if defined(OS_POSIX_TYPE_NEWLIB)
140 if (*(U32 *)mutex == PTHREAD_MUTEX_INITIALIZER) {
141 #else
142 if (memcmp(mutex, &tmp, sizeof(prt_pthread_mutex_t)) == 0) {
143 #endif
144 ret = PRT_PthreadMutexInit(mutex, NULL);
145 if (ret != OS_OK) {
146 return EINVAL;
147 }
148 }
149
150 return OS_OK;
151 }
152
153 int PRT_PthreadMutexLock(prt_pthread_mutex_t *mutex)
154 {
155 U32 ret;
156 U32 intSave;
157
158 if (OsMutexParamCheck(mutex) != OS_OK) {
159 return EINVAL;
160 }
161
162 intSave = PRT_HwiLock();
163 if (mutex->magic != MUTEX_MAGIC) {
164 PRT_HwiRestore(intSave);
165 return EINVAL;
166 }
167
168 if (mutex->type == PTHREAD_MUTEX_ERRORCHECK && OsSemBusy(mutex->mutex_sem)) {
169 PRT_HwiRestore(intSave);
170 return EINVAL;
171 }
172 PRT_HwiRestore(intSave);
173
174 ret = PRT_SemPend(mutex->mutex_sem, OS_WAIT_FOREVER);
175 if (ret != OS_OK) {
176 return EINVAL;
177 }
178
179 return OS_OK;
180 }
181
182 int pthread_mutex_lock(pthread_mutex_t *mutex)
183 {
184 return PRT_PthreadMutexLock((prt_pthread_mutex_t *)mutex);
185 }
186
187 int PRT_PthreadMutexUnlock(prt_pthread_mutex_t *mutex)
188 {
189 U32 ret;
190 U32 intSave;
191
192 if (OsMutexParamCheck(mutex) != OS_OK) {
193 return EINVAL;
194 }
195
196 intSave = PRT_HwiLock();
197 if (mutex->magic != MUTEX_MAGIC) {
198 PRT_HwiRestore(intSave);
199 return EINVAL;
200 }
201 PRT_HwiRestore(intSave);
202
203 ret = PRT_SemPost(mutex->mutex_sem);
204 if (ret != OS_OK) {
205 return EINVAL;
206 }
207
208 return OS_OK;
209 }
210
211 int pthread_mutex_unlock(pthread_mutex_t *mutex)
212 {
213 return PRT_PthreadMutexUnlock((prt_pthread_mutex_t *)mutex);
214 }
215
216 int PRT_PthreadMutexTrylock(prt_pthread_mutex_t *mutex)
217 {
218 U32 ret;
219 U32 intSave;
220
221 if (OsMutexParamCheck(mutex) != OS_OK) {
222 return EINVAL;
223 }
224
225 intSave = PRT_HwiLock();
226 if (mutex->magic != MUTEX_MAGIC) {
227 PRT_HwiRestore(intSave);
228 return EINVAL;
229 }
230
231 if (OsSemBusy(mutex->mutex_sem)) {
232 PRT_HwiRestore(intSave);
233 return EBUSY;
234 }
235 PRT_HwiRestore(intSave);
236
237 ret = PRT_SemPend(mutex->mutex_sem, OS_WAIT_FOREVER);
238 if (ret != OS_OK) {
239 return EINVAL;
240 }
241
242 return OS_OK;
243 }
244
245 int pthread_mutex_trylock(pthread_mutex_t *mutex)
246 {
247 return PRT_PthreadMutexTrylock((prt_pthread_mutex_t *)mutex);
248 }
249
250 int PRT_PthreadMutexDestroy(prt_pthread_mutex_t *mutex)
251 {
252 U32 ret;
253 U32 intSave;
254
255 if (OsMutexParamCheck(mutex) != OS_OK) {
256 return EINVAL;
257 }
258
259 intSave = PRT_HwiLock();
260 if (mutex->magic != MUTEX_MAGIC) {
261 PRT_HwiRestore(intSave);
262 return EINVAL;
263 }
264 PRT_HwiRestore(intSave);
265
266 ret = PRT_SemDelete(mutex->mutex_sem);
267 if (ret != OS_OK) {
268 return EINVAL;
269 }
270 mutex->magic = 0;
271
272 return OS_OK;
273 }
274
275 int pthread_mutex_destroy(pthread_mutex_t *mutex)
276 {
277 return PRT_PthreadMutexDestroy((prt_pthread_mutex_t *)mutex);
278 }
279
280 int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type)
281 {
282 if (type == NULL || attr == NULL) {
283 return EINVAL;
284 }
285
286 if (attr->is_initialized != PTHREAD_ATTR_INIT) {
287 return EINVAL;
288 }
289
290 *type = attr->type;
291
292 return OS_OK;
293 }
294
295 int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
296 {
297 if (!PTHREAD_MUTEX_TYPE_ISVALID(type) || attr == NULL) {
298 return EINVAL;
299 }
300
301 if (attr->is_initialized != PTHREAD_ATTR_INIT) {
302 return EINVAL;
303 }
304
305 attr->type = type;
306
307 return OS_OK;
308 }
309
310 int PRT_PthreadMutexTimedlock(prt_pthread_mutex_t *mutex, const struct timespec *time)
311 {
312 U32 ret;
313 U32 intSave;
314 U32 ticks;
315
316 if (time == NULL) {
317 return EINVAL;
318 }
319
320 if (OsMutexParamCheck(mutex) != OS_OK) {
321 return EINVAL;
322 }
323
324 intSave = PRT_HwiLock();
325 if (mutex->magic != MUTEX_MAGIC) {
326 PRT_HwiRestore(intSave);
327 return EINVAL;
328 }
329
330 if (time->tv_sec < 0 || time->tv_nsec < 0) {
331 PRT_HwiRestore(intSave);
332 return EINVAL;
333 }
334
335 PRT_HwiRestore(intSave);
336
337 ret = OsTimeOut2Ticks(time, &ticks);
338 if (ret != OS_OK) {
339 return (int)ret;
340 }
341
342 ret = PRT_SemPend(mutex->mutex_sem, ticks);
343 if (ret != OS_OK) {
344 ret = (ret == OS_ERRNO_SEM_TIMEOUT) ? ETIMEDOUT : EINVAL;
345 }
346
347 return (int)ret;
348 }
349
350 int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *time)
351 {
352 return PRT_PthreadMutexTimedlock((prt_pthread_mutex_t *)mutex, time);
353 }
354
355 int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int ceiling)
356 {
357 (void)attr;
358 (void)ceiling;
359
360 return EINVAL;
361 }
362
363 int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *__restrict attr, int *ceiling)
364 {
365 (void)attr;
366 (void)ceiling;
367
368 return EINVAL;
369 }
370
371 int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol)
372 {
373 int ret;
374
375 if (attr == NULL) {
376 return EINVAL;
377 }
378
379 if (attr->is_initialized != PTHREAD_ATTR_INIT) {
380 return EINVAL;
381 }
382
383 switch (protocol) {
384 case PTHREAD_PRIO_NONE:
385 case PTHREAD_PRIO_INHERIT:
386 attr->protocol = protocol;
387 ret = OS_OK;
388 break;
389 case PTHREAD_PRIO_PROTECT:
390 ret = ENOTSUP;
391 break;
392 default:
393 ret = EINVAL;
394 break;
395 }
396
397 return ret;
398 }
399
400 int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol)
401 {
402 if (protocol == NULL || attr == NULL) {
403 return EINVAL;
404 }
405
406 if (attr->is_initialized != PTHREAD_ATTR_INIT) {
407 return EINVAL;
408 }
409
410 *protocol = attr->protocol;
411
412 return OS_OK;
413 }
414