• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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