1 /*
2 * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3 */
4
5 #include <errno.h>
6 #include <pthread.h>
7 #include <sched.h>
8 #include <aos/kernel.h>
9
10 #include "internal/pthread.h"
11
12
13 #define PTHREAD_MUTEXATTR_IS_INITED(x) do { if ((x)->flag != PTHREAD_DYN_INIT) return EINVAL; } \
14 while (0)
15
16
pthread_mutex_init(pthread_mutex_t * mutex,const pthread_mutexattr_t * attr)17 int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
18 {
19 int ret = 0;
20
21 if (mutex == NULL) {
22 return EINVAL;
23 }
24 memset(mutex, 0, sizeof(pthread_mutex_t));
25
26 if (attr != NULL) {
27 mutex->attr = *attr;
28 }
29
30 ret = aos_mutex_new((aos_mutex_t*)(&(mutex->mutex)));
31 if (ret != 0) {
32 return -1;
33 }
34
35 mutex->flag = PTHREAD_DYN_INIT;
36 return 0;
37 }
38
pthread_mutex_destroy(pthread_mutex_t * mutex)39 int pthread_mutex_destroy(pthread_mutex_t *mutex)
40 {
41 if (mutex == NULL) {
42 return EINVAL;
43 }
44
45 if (mutex->flag == PTHREAD_STATIC_INIT) {
46 memset(mutex, 0, sizeof(pthread_mutex_t));
47 return 0;
48 } else if (mutex->flag == PTHREAD_DYN_INIT) {
49 aos_mutex_free((aos_mutex_t*)(&(mutex->mutex)));
50 memset(mutex, 0, sizeof(pthread_mutex_t));
51 return 0;
52 } else {
53 return EINVAL;
54 }
55 }
56
pthread_mutex_lock(pthread_mutex_t * mutex)57 int pthread_mutex_lock(pthread_mutex_t *mutex)
58 {
59 int ret = 0;
60
61 if (mutex == NULL) {
62 return EINVAL;
63 }
64
65 /* The mutex is initted by PTHREAD_MUTEX_INITIALIZER */
66 if (mutex->flag == PTHREAD_STATIC_INIT) {
67 ret = pthread_mutex_init(mutex, NULL);
68 if (ret != 0) {
69 return -1;
70 }
71 }
72
73 ret = aos_mutex_lock((aos_mutex_t*)(&(mutex->mutex)), AOS_WAIT_FOREVER);
74 if (ret != 0) {
75 return -1;
76 }
77
78 return 0;
79 }
80
pthread_mutex_unlock(pthread_mutex_t * mutex)81 int pthread_mutex_unlock(pthread_mutex_t *mutex)
82 {
83 int ret = 0;
84
85 if (mutex == NULL) {
86 return EINVAL;
87 }
88
89 if (mutex->flag != PTHREAD_DYN_INIT) {
90 return -1;
91 }
92
93 ret = aos_mutex_unlock((aos_mutex_t*)(&(mutex->mutex)));
94 if (ret != 0) {
95 return -1;
96 }
97
98 return 0;
99 }
100
pthread_mutex_trylock(pthread_mutex_t * mutex)101 int pthread_mutex_trylock(pthread_mutex_t *mutex)
102 {
103 int ret = 0;
104
105 if (mutex == NULL) {
106 return EINVAL;
107 }
108
109 /* The mutex is initted by PTHREAD_MUTEX_INITIALIZER */
110 if (mutex->flag == PTHREAD_STATIC_INIT) {
111 ret = pthread_mutex_init(mutex, NULL);
112 if (ret != 0) {
113 return -1;
114 }
115 }
116
117 ret = aos_mutex_lock((aos_mutex_t*)(&(mutex->mutex)), AOS_NO_WAIT);
118 if (ret == -ETIMEDOUT) {
119 return EBUSY;
120 } else if (ret != 0) {
121 return -1;
122 } else {
123 return 0;
124 }
125 }
126
pthread_mutex_timedlock(pthread_mutex_t * mutex,const struct timespec * at)127 int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *at)
128 {
129 int ret = 0;
130
131 if (mutex == NULL) {
132 return EINVAL;
133 }
134
135 /* The mutex is initted by PTHREAD_MUTEX_INITIALIZER */
136 if (mutex->flag == PTHREAD_STATIC_INIT) {
137 ret = pthread_mutex_init(mutex, NULL);
138 if (ret != 0) {
139 return -1;
140 }
141 }
142
143 ret = pthread_mutex_trylock(mutex);
144 if (ret != EBUSY) {
145 return ret;
146 }
147
148 unsigned int timeout = at->tv_sec * 1000 + at->tv_nsec / 1000;
149 ret = aos_mutex_lock((aos_mutex_t*)(&(mutex->mutex)), timeout);
150 if (ret != 0) {
151 return -1;
152 }
153
154 return 0;
155 }
156
pthread_mutex_getprioceiling(const pthread_mutex_t * mutex,int * prioceiling)157 int pthread_mutex_getprioceiling(const pthread_mutex_t *mutex, int *prioceiling)
158 {
159 if ((mutex == NULL) || (prioceiling == NULL)) {
160 return EINVAL;
161 }
162
163 PTHREAD_MUTEXATTR_IS_INITED(&(mutex->attr));
164
165 *prioceiling = mutex->attr.prioceiling;
166
167 return 0;
168 }
169
pthread_mutex_setprioceiling(pthread_mutex_t * mutex,int prioceiling,int * old_ceiling)170 int pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling,
171 int *old_ceiling)
172 {
173 if (mutex == NULL) {
174 return EINVAL;
175 }
176
177 if ((prioceiling < sched_get_priority_min(SCHED_FIFO)) ||
178 (prioceiling > sched_get_priority_max(SCHED_FIFO))) {
179 return EINVAL;
180 }
181
182 PTHREAD_MUTEXATTR_IS_INITED(&(mutex->attr));
183
184 if (old_ceiling != NULL) {
185 *old_ceiling = mutex->attr.prioceiling;
186 }
187
188 mutex->attr.prioceiling = prioceiling;
189
190 return 0;
191 }
192
pthread_mutexattr_init(pthread_mutexattr_t * attr)193 int pthread_mutexattr_init(pthread_mutexattr_t *attr)
194 {
195 if (attr == NULL) {
196 return EINVAL;
197 }
198
199 attr->flag = PTHREAD_DYN_INIT;
200 attr->type = PTHREAD_MUTEX_DEFAULT;
201 attr->protocol = DEFAULT_MUTEX_PROCOCOL;
202 attr->prioceiling = DEFAULT_MUTEX_PRIOCEILING;
203 attr->pshared = DEFAULT_MUTEX_PSHARED;
204
205 return 0;
206 }
207
pthread_mutexattr_destroy(pthread_mutexattr_t * attr)208 int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
209 {
210 if (attr == NULL) {
211 return EINVAL;
212 }
213
214 memset(attr, 0, sizeof(pthread_mutexattr_t));
215
216 return 0;
217 }
218
pthread_mutexattr_gettype(const pthread_mutexattr_t * attr,int * type)219 int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type)
220 {
221 if ((attr == NULL) || (type == NULL)) {
222 return EINVAL;
223 }
224
225 PTHREAD_MUTEXATTR_IS_INITED(attr);
226
227 *type = attr->type;
228
229 return 0;
230 }
231
pthread_mutexattr_settype(pthread_mutexattr_t * attr,int type)232 int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
233 {
234 if (attr == NULL) {
235 return EINVAL;
236 }
237
238 if ((type < PTHREAD_MUTEX_NORMAL) || (type > PTHREAD_MUTEX_ERRORCHECK)) {
239 return EINVAL;
240 }
241
242 PTHREAD_MUTEXATTR_IS_INITED(attr);
243
244 attr->type = type;
245
246 return 0;
247 }
248
pthread_mutexattr_getprotocol(const pthread_mutexattr_t * attr,int * protocol)249 int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol)
250 {
251 if ((attr == NULL) || (protocol == NULL)) {
252 return EINVAL;
253 }
254
255 PTHREAD_MUTEXATTR_IS_INITED(attr);
256
257 *protocol = attr->protocol;
258
259 return 0;
260 }
261
pthread_mutexattr_setprotocol(pthread_mutexattr_t * attr,int protocol)262 int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol)
263 {
264 if (attr == NULL) {
265 return EINVAL;
266 }
267
268 if ((protocol < PTHREAD_PRIO_NONE) || (protocol > PTHREAD_PRIO_PROTECT)) {
269 return EINVAL;
270 }
271
272 PTHREAD_MUTEXATTR_IS_INITED(attr);
273
274 attr->protocol = protocol;
275
276 return 0;
277 }
278
pthread_mutexattr_getprioceiling(const pthread_mutexattr_t * attr,int * prioceiling)279 int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr,
280 int *prioceiling)
281 {
282 if ((attr == NULL) || (prioceiling == NULL)) {
283 return EINVAL;
284 }
285
286 PTHREAD_MUTEXATTR_IS_INITED(attr);
287
288 *prioceiling = attr->prioceiling;
289
290 return 0;
291 }
292
pthread_mutexattr_setprioceiling(pthread_mutexattr_t * attr,int prioceiling)293 int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling)
294 {
295 if (attr == NULL) {
296 return EINVAL;
297 }
298
299 if ((prioceiling < sched_get_priority_min(SCHED_FIFO)) ||
300 (prioceiling > sched_get_priority_max(SCHED_FIFO))) {
301 return EINVAL;
302 }
303
304 PTHREAD_MUTEXATTR_IS_INITED(attr);
305
306 attr->prioceiling = prioceiling;
307
308 return 0;
309 }
310
pthread_mutexattr_setpshared(pthread_mutexattr_t * attr,int pshared)311 int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
312 {
313 if (attr == NULL) {
314 return EINVAL;
315 }
316
317 if ((pshared < PTHREAD_PROCESS_PRIVATE) || (pshared > PTHREAD_PROCESS_SHARED)) {
318 return EINVAL;
319 }
320
321 PTHREAD_MUTEXATTR_IS_INITED(attr);
322
323 attr->pshared = pshared;
324
325 return 0;
326 }
327
pthread_mutexattr_getpshared(pthread_mutexattr_t * attr,int * pshared)328 int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared)
329 {
330 if ((attr == NULL) || (pshared == NULL)) {
331 return EINVAL;
332 }
333
334 PTHREAD_MUTEXATTR_IS_INITED(attr);
335
336 *pshared = attr->pshared;
337
338 return 0;
339 }
340