xref: /nrf52832-nimble/rt-thread/components/libc/pthreads/pthread_mutex.c (revision 104654410c56c573564690304ae786df310c91fc)
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