1*10465441SEvalZero /*
2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date Author Notes
8*10465441SEvalZero * 2010-10-26 Bernard the first version
9*10465441SEvalZero */
10*10465441SEvalZero
11*10465441SEvalZero #include <rtthread.h>
12*10465441SEvalZero #include "pthread.h"
13*10465441SEvalZero
14*10465441SEvalZero #define MUTEXATTR_SHARED_MASK 0x0010
15*10465441SEvalZero #define MUTEXATTR_TYPE_MASK 0x000f
16*10465441SEvalZero
17*10465441SEvalZero const pthread_mutexattr_t pthread_default_mutexattr = PTHREAD_PROCESS_PRIVATE;
18*10465441SEvalZero
pthread_mutexattr_init(pthread_mutexattr_t * attr)19*10465441SEvalZero int pthread_mutexattr_init(pthread_mutexattr_t *attr)
20*10465441SEvalZero {
21*10465441SEvalZero if (attr)
22*10465441SEvalZero {
23*10465441SEvalZero *attr = pthread_default_mutexattr;
24*10465441SEvalZero
25*10465441SEvalZero return 0;
26*10465441SEvalZero }
27*10465441SEvalZero
28*10465441SEvalZero return EINVAL;
29*10465441SEvalZero }
30*10465441SEvalZero RTM_EXPORT(pthread_mutexattr_init);
31*10465441SEvalZero
pthread_mutexattr_destroy(pthread_mutexattr_t * attr)32*10465441SEvalZero int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
33*10465441SEvalZero {
34*10465441SEvalZero if (attr)
35*10465441SEvalZero {
36*10465441SEvalZero *attr = -1;
37*10465441SEvalZero
38*10465441SEvalZero return 0;
39*10465441SEvalZero }
40*10465441SEvalZero
41*10465441SEvalZero return EINVAL;
42*10465441SEvalZero }
43*10465441SEvalZero RTM_EXPORT(pthread_mutexattr_destroy);
44*10465441SEvalZero
pthread_mutexattr_gettype(const pthread_mutexattr_t * attr,int * type)45*10465441SEvalZero int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type)
46*10465441SEvalZero {
47*10465441SEvalZero if (attr && type)
48*10465441SEvalZero {
49*10465441SEvalZero int atype = (*attr & MUTEXATTR_TYPE_MASK);
50*10465441SEvalZero
51*10465441SEvalZero if (atype >= PTHREAD_MUTEX_NORMAL && atype <= PTHREAD_MUTEX_ERRORCHECK)
52*10465441SEvalZero {
53*10465441SEvalZero *type = atype;
54*10465441SEvalZero
55*10465441SEvalZero return 0;
56*10465441SEvalZero }
57*10465441SEvalZero }
58*10465441SEvalZero
59*10465441SEvalZero return EINVAL;
60*10465441SEvalZero }
61*10465441SEvalZero RTM_EXPORT(pthread_mutexattr_gettype);
62*10465441SEvalZero
pthread_mutexattr_settype(pthread_mutexattr_t * attr,int type)63*10465441SEvalZero int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
64*10465441SEvalZero {
65*10465441SEvalZero if (attr && type >= PTHREAD_MUTEX_NORMAL && type <= PTHREAD_MUTEX_ERRORCHECK)
66*10465441SEvalZero {
67*10465441SEvalZero *attr = (*attr & ~MUTEXATTR_TYPE_MASK) | type;
68*10465441SEvalZero
69*10465441SEvalZero return 0;
70*10465441SEvalZero }
71*10465441SEvalZero
72*10465441SEvalZero return EINVAL;
73*10465441SEvalZero }
74*10465441SEvalZero RTM_EXPORT(pthread_mutexattr_settype);
75*10465441SEvalZero
pthread_mutexattr_setpshared(pthread_mutexattr_t * attr,int pshared)76*10465441SEvalZero int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
77*10465441SEvalZero {
78*10465441SEvalZero if (!attr)
79*10465441SEvalZero return EINVAL;
80*10465441SEvalZero
81*10465441SEvalZero switch (pshared)
82*10465441SEvalZero {
83*10465441SEvalZero case PTHREAD_PROCESS_PRIVATE:
84*10465441SEvalZero *attr &= ~MUTEXATTR_SHARED_MASK;
85*10465441SEvalZero return 0;
86*10465441SEvalZero
87*10465441SEvalZero case PTHREAD_PROCESS_SHARED:
88*10465441SEvalZero *attr |= MUTEXATTR_SHARED_MASK;
89*10465441SEvalZero return 0;
90*10465441SEvalZero }
91*10465441SEvalZero
92*10465441SEvalZero return EINVAL;
93*10465441SEvalZero }
94*10465441SEvalZero RTM_EXPORT(pthread_mutexattr_setpshared);
95*10465441SEvalZero
pthread_mutexattr_getpshared(pthread_mutexattr_t * attr,int * pshared)96*10465441SEvalZero int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared)
97*10465441SEvalZero {
98*10465441SEvalZero if (!attr || !pshared)
99*10465441SEvalZero return EINVAL;
100*10465441SEvalZero
101*10465441SEvalZero *pshared = (*attr & MUTEXATTR_SHARED_MASK) ? PTHREAD_PROCESS_SHARED
102*10465441SEvalZero : PTHREAD_PROCESS_PRIVATE;
103*10465441SEvalZero return 0;
104*10465441SEvalZero }
105*10465441SEvalZero RTM_EXPORT(pthread_mutexattr_getpshared);
106*10465441SEvalZero
pthread_mutex_init(pthread_mutex_t * mutex,const pthread_mutexattr_t * attr)107*10465441SEvalZero int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
108*10465441SEvalZero {
109*10465441SEvalZero rt_err_t result;
110*10465441SEvalZero char name[RT_NAME_MAX];
111*10465441SEvalZero static rt_uint16_t pthread_mutex_number = 0;
112*10465441SEvalZero
113*10465441SEvalZero if (!mutex)
114*10465441SEvalZero return EINVAL;
115*10465441SEvalZero
116*10465441SEvalZero /* build mutex name */
117*10465441SEvalZero rt_snprintf(name, sizeof(name), "pmtx%02d", pthread_mutex_number ++);
118*10465441SEvalZero if (attr == RT_NULL)
119*10465441SEvalZero mutex->attr = pthread_default_mutexattr;
120*10465441SEvalZero else
121*10465441SEvalZero mutex->attr = *attr;
122*10465441SEvalZero
123*10465441SEvalZero /* init mutex lock */
124*10465441SEvalZero result = rt_mutex_init(&(mutex->lock), name, RT_IPC_FLAG_FIFO);
125*10465441SEvalZero if (result != RT_EOK)
126*10465441SEvalZero return EINVAL;
127*10465441SEvalZero
128*10465441SEvalZero /* detach the object from system object container */
129*10465441SEvalZero rt_object_detach(&(mutex->lock.parent.parent));
130*10465441SEvalZero mutex->lock.parent.parent.type = RT_Object_Class_Mutex;
131*10465441SEvalZero
132*10465441SEvalZero return 0;
133*10465441SEvalZero }
134*10465441SEvalZero RTM_EXPORT(pthread_mutex_init);
135*10465441SEvalZero
pthread_mutex_destroy(pthread_mutex_t * mutex)136*10465441SEvalZero int pthread_mutex_destroy(pthread_mutex_t *mutex)
137*10465441SEvalZero {
138*10465441SEvalZero if (!mutex || mutex->attr == -1)
139*10465441SEvalZero return EINVAL;
140*10465441SEvalZero
141*10465441SEvalZero /* it's busy */
142*10465441SEvalZero if (mutex->lock.owner != RT_NULL)
143*10465441SEvalZero return EBUSY;
144*10465441SEvalZero
145*10465441SEvalZero rt_memset(mutex, 0, sizeof(pthread_mutex_t));
146*10465441SEvalZero mutex->attr = -1;
147*10465441SEvalZero
148*10465441SEvalZero return 0;
149*10465441SEvalZero }
150*10465441SEvalZero RTM_EXPORT(pthread_mutex_destroy);
151*10465441SEvalZero
pthread_mutex_lock(pthread_mutex_t * mutex)152*10465441SEvalZero int pthread_mutex_lock(pthread_mutex_t *mutex)
153*10465441SEvalZero {
154*10465441SEvalZero int mtype;
155*10465441SEvalZero rt_err_t result;
156*10465441SEvalZero
157*10465441SEvalZero if (!mutex)
158*10465441SEvalZero return EINVAL;
159*10465441SEvalZero
160*10465441SEvalZero if (mutex->attr == -1)
161*10465441SEvalZero {
162*10465441SEvalZero /* init mutex */
163*10465441SEvalZero pthread_mutex_init(mutex, RT_NULL);
164*10465441SEvalZero }
165*10465441SEvalZero
166*10465441SEvalZero mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
167*10465441SEvalZero rt_enter_critical();
168*10465441SEvalZero if (mutex->lock.owner == rt_thread_self() &&
169*10465441SEvalZero mtype != PTHREAD_MUTEX_RECURSIVE)
170*10465441SEvalZero {
171*10465441SEvalZero rt_exit_critical();
172*10465441SEvalZero
173*10465441SEvalZero return EDEADLK;
174*10465441SEvalZero }
175*10465441SEvalZero rt_exit_critical();
176*10465441SEvalZero
177*10465441SEvalZero result = rt_mutex_take(&(mutex->lock), RT_WAITING_FOREVER);
178*10465441SEvalZero if (result == RT_EOK)
179*10465441SEvalZero return 0;
180*10465441SEvalZero
181*10465441SEvalZero return EINVAL;
182*10465441SEvalZero }
183*10465441SEvalZero RTM_EXPORT(pthread_mutex_lock);
184*10465441SEvalZero
pthread_mutex_unlock(pthread_mutex_t * mutex)185*10465441SEvalZero int pthread_mutex_unlock(pthread_mutex_t *mutex)
186*10465441SEvalZero {
187*10465441SEvalZero rt_err_t result;
188*10465441SEvalZero
189*10465441SEvalZero if (!mutex)
190*10465441SEvalZero return EINVAL;
191*10465441SEvalZero if (mutex->attr == -1)
192*10465441SEvalZero {
193*10465441SEvalZero /* init mutex */
194*10465441SEvalZero pthread_mutex_init(mutex, RT_NULL);
195*10465441SEvalZero }
196*10465441SEvalZero
197*10465441SEvalZero if (mutex->lock.owner != rt_thread_self())
198*10465441SEvalZero {
199*10465441SEvalZero int mtype;
200*10465441SEvalZero mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
201*10465441SEvalZero
202*10465441SEvalZero /* error check, return EPERM */
203*10465441SEvalZero if (mtype == PTHREAD_MUTEX_ERRORCHECK)
204*10465441SEvalZero return EPERM;
205*10465441SEvalZero
206*10465441SEvalZero /* no thread waiting on this mutex */
207*10465441SEvalZero if (mutex->lock.owner == RT_NULL)
208*10465441SEvalZero return 0;
209*10465441SEvalZero }
210*10465441SEvalZero
211*10465441SEvalZero result = rt_mutex_release(&(mutex->lock));
212*10465441SEvalZero if (result == RT_EOK)
213*10465441SEvalZero return 0;
214*10465441SEvalZero
215*10465441SEvalZero return EINVAL;
216*10465441SEvalZero }
217*10465441SEvalZero RTM_EXPORT(pthread_mutex_unlock);
218*10465441SEvalZero
pthread_mutex_trylock(pthread_mutex_t * mutex)219*10465441SEvalZero int pthread_mutex_trylock(pthread_mutex_t *mutex)
220*10465441SEvalZero {
221*10465441SEvalZero rt_err_t result;
222*10465441SEvalZero int mtype;
223*10465441SEvalZero
224*10465441SEvalZero if (!mutex)
225*10465441SEvalZero return EINVAL;
226*10465441SEvalZero if (mutex->attr == -1)
227*10465441SEvalZero {
228*10465441SEvalZero /* init mutex */
229*10465441SEvalZero pthread_mutex_init(mutex, RT_NULL);
230*10465441SEvalZero }
231*10465441SEvalZero
232*10465441SEvalZero mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
233*10465441SEvalZero rt_enter_critical();
234*10465441SEvalZero if (mutex->lock.owner == rt_thread_self() &&
235*10465441SEvalZero mtype != PTHREAD_MUTEX_RECURSIVE)
236*10465441SEvalZero {
237*10465441SEvalZero rt_exit_critical();
238*10465441SEvalZero
239*10465441SEvalZero return EDEADLK;
240*10465441SEvalZero }
241*10465441SEvalZero rt_exit_critical();
242*10465441SEvalZero
243*10465441SEvalZero result = rt_mutex_take(&(mutex->lock), 0);
244*10465441SEvalZero if (result == RT_EOK) return 0;
245*10465441SEvalZero
246*10465441SEvalZero return EBUSY;
247*10465441SEvalZero }
248*10465441SEvalZero RTM_EXPORT(pthread_mutex_trylock);
249