xref: /nrf52832-nimble/rt-thread/components/libc/pthreads/pthread_cond.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 <pthread.h>
12*10465441SEvalZero #include "pthread_internal.h"
13*10465441SEvalZero 
pthread_condattr_destroy(pthread_condattr_t * attr)14*10465441SEvalZero int pthread_condattr_destroy(pthread_condattr_t *attr)
15*10465441SEvalZero {
16*10465441SEvalZero     if (!attr)
17*10465441SEvalZero         return EINVAL;
18*10465441SEvalZero 
19*10465441SEvalZero     return 0;
20*10465441SEvalZero }
21*10465441SEvalZero RTM_EXPORT(pthread_condattr_destroy);
22*10465441SEvalZero 
pthread_condattr_init(pthread_condattr_t * attr)23*10465441SEvalZero int pthread_condattr_init(pthread_condattr_t *attr)
24*10465441SEvalZero {
25*10465441SEvalZero     if (!attr)
26*10465441SEvalZero         return EINVAL;
27*10465441SEvalZero     *attr = PTHREAD_PROCESS_PRIVATE;
28*10465441SEvalZero 
29*10465441SEvalZero     return 0;
30*10465441SEvalZero }
31*10465441SEvalZero RTM_EXPORT(pthread_condattr_init);
32*10465441SEvalZero 
pthread_condattr_getclock(const pthread_condattr_t * attr,clockid_t * clock_id)33*10465441SEvalZero int pthread_condattr_getclock(const pthread_condattr_t *attr,
34*10465441SEvalZero                               clockid_t                *clock_id)
35*10465441SEvalZero {
36*10465441SEvalZero     return 0;
37*10465441SEvalZero }
38*10465441SEvalZero RTM_EXPORT(pthread_condattr_getclock);
39*10465441SEvalZero 
pthread_condattr_setclock(pthread_condattr_t * attr,clockid_t clock_id)40*10465441SEvalZero int pthread_condattr_setclock(pthread_condattr_t *attr,
41*10465441SEvalZero                               clockid_t           clock_id)
42*10465441SEvalZero {
43*10465441SEvalZero     return 0;
44*10465441SEvalZero }
45*10465441SEvalZero RTM_EXPORT(pthread_condattr_setclock);
46*10465441SEvalZero 
pthread_condattr_getpshared(const pthread_condattr_t * attr,int * pshared)47*10465441SEvalZero int pthread_condattr_getpshared(const pthread_condattr_t *attr, int *pshared)
48*10465441SEvalZero {
49*10465441SEvalZero     if (!attr || !pshared)
50*10465441SEvalZero         return EINVAL;
51*10465441SEvalZero 
52*10465441SEvalZero     *pshared = PTHREAD_PROCESS_PRIVATE;
53*10465441SEvalZero 
54*10465441SEvalZero     return 0;
55*10465441SEvalZero }
56*10465441SEvalZero RTM_EXPORT(pthread_condattr_getpshared);
57*10465441SEvalZero 
pthread_condattr_setpshared(pthread_condattr_t * attr,int pshared)58*10465441SEvalZero int pthread_condattr_setpshared(pthread_condattr_t*attr, int pshared)
59*10465441SEvalZero {
60*10465441SEvalZero     if ((pshared != PTHREAD_PROCESS_PRIVATE) &&
61*10465441SEvalZero         (pshared != PTHREAD_PROCESS_SHARED))
62*10465441SEvalZero     {
63*10465441SEvalZero         return EINVAL;
64*10465441SEvalZero     }
65*10465441SEvalZero 
66*10465441SEvalZero     if (pshared != PTHREAD_PROCESS_PRIVATE)
67*10465441SEvalZero         return ENOSYS;
68*10465441SEvalZero 
69*10465441SEvalZero     return 0;
70*10465441SEvalZero }
71*10465441SEvalZero RTM_EXPORT(pthread_condattr_setpshared);
72*10465441SEvalZero 
pthread_cond_init(pthread_cond_t * cond,const pthread_condattr_t * attr)73*10465441SEvalZero int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
74*10465441SEvalZero {
75*10465441SEvalZero     rt_err_t result;
76*10465441SEvalZero     char cond_name[RT_NAME_MAX];
77*10465441SEvalZero     static rt_uint16_t cond_num = 0;
78*10465441SEvalZero 
79*10465441SEvalZero     /* parameter check */
80*10465441SEvalZero     if (cond == RT_NULL)
81*10465441SEvalZero         return EINVAL;
82*10465441SEvalZero     if ((attr != RT_NULL) && (*attr != PTHREAD_PROCESS_PRIVATE))
83*10465441SEvalZero         return EINVAL;
84*10465441SEvalZero 
85*10465441SEvalZero     rt_snprintf(cond_name, sizeof(cond_name), "cond%02d", cond_num++);
86*10465441SEvalZero 
87*10465441SEvalZero 	if (attr == RT_NULL) /* use default value */
88*10465441SEvalZero 		cond->attr = PTHREAD_PROCESS_PRIVATE;
89*10465441SEvalZero 	else
90*10465441SEvalZero 	    cond->attr = *attr;
91*10465441SEvalZero 
92*10465441SEvalZero     result = rt_sem_init(&cond->sem, cond_name, 0, RT_IPC_FLAG_FIFO);
93*10465441SEvalZero     if (result != RT_EOK)
94*10465441SEvalZero         return EINVAL;
95*10465441SEvalZero 
96*10465441SEvalZero     /* detach the object from system object container */
97*10465441SEvalZero     rt_object_detach(&(cond->sem.parent.parent));
98*10465441SEvalZero     cond->sem.parent.parent.type = RT_Object_Class_Semaphore;
99*10465441SEvalZero 
100*10465441SEvalZero     return 0;
101*10465441SEvalZero }
102*10465441SEvalZero RTM_EXPORT(pthread_cond_init);
103*10465441SEvalZero 
pthread_cond_destroy(pthread_cond_t * cond)104*10465441SEvalZero int pthread_cond_destroy(pthread_cond_t *cond)
105*10465441SEvalZero {
106*10465441SEvalZero     rt_err_t result;
107*10465441SEvalZero     if (cond == RT_NULL)
108*10465441SEvalZero         return EINVAL;
109*10465441SEvalZero     if (cond->attr == -1)
110*10465441SEvalZero         return 0; /* which is not initialized */
111*10465441SEvalZero 
112*10465441SEvalZero     result = rt_sem_trytake(&(cond->sem));
113*10465441SEvalZero     if (result != RT_EOK)
114*10465441SEvalZero         return EBUSY;
115*10465441SEvalZero 
116*10465441SEvalZero     /* clean condition */
117*10465441SEvalZero     rt_memset(cond, 0, sizeof(pthread_cond_t));
118*10465441SEvalZero     cond->attr = -1;
119*10465441SEvalZero 
120*10465441SEvalZero     return 0;
121*10465441SEvalZero }
122*10465441SEvalZero RTM_EXPORT(pthread_cond_destroy);
123*10465441SEvalZero 
pthread_cond_broadcast(pthread_cond_t * cond)124*10465441SEvalZero int pthread_cond_broadcast(pthread_cond_t *cond)
125*10465441SEvalZero {
126*10465441SEvalZero     rt_err_t result;
127*10465441SEvalZero 
128*10465441SEvalZero     if (cond == RT_NULL)
129*10465441SEvalZero         return EINVAL;
130*10465441SEvalZero     if (cond->attr == -1)
131*10465441SEvalZero         pthread_cond_init(cond, RT_NULL);
132*10465441SEvalZero 
133*10465441SEvalZero     rt_enter_critical();
134*10465441SEvalZero     while (1)
135*10465441SEvalZero     {
136*10465441SEvalZero         /* try to take condition semaphore */
137*10465441SEvalZero         result = rt_sem_trytake(&(cond->sem));
138*10465441SEvalZero         if (result == -RT_ETIMEOUT)
139*10465441SEvalZero         {
140*10465441SEvalZero             /* it's timeout, release this semaphore */
141*10465441SEvalZero             rt_sem_release(&(cond->sem));
142*10465441SEvalZero         }
143*10465441SEvalZero         else if (result == RT_EOK)
144*10465441SEvalZero         {
145*10465441SEvalZero             /* has taken this semaphore, release it */
146*10465441SEvalZero             rt_sem_release(&(cond->sem));
147*10465441SEvalZero             break;
148*10465441SEvalZero         }
149*10465441SEvalZero         else
150*10465441SEvalZero         {
151*10465441SEvalZero             rt_exit_critical();
152*10465441SEvalZero 
153*10465441SEvalZero             return EINVAL;
154*10465441SEvalZero         }
155*10465441SEvalZero     }
156*10465441SEvalZero     rt_exit_critical();
157*10465441SEvalZero 
158*10465441SEvalZero     return 0;
159*10465441SEvalZero }
160*10465441SEvalZero RTM_EXPORT(pthread_cond_broadcast);
161*10465441SEvalZero 
pthread_cond_signal(pthread_cond_t * cond)162*10465441SEvalZero int pthread_cond_signal(pthread_cond_t *cond)
163*10465441SEvalZero {
164*10465441SEvalZero     rt_err_t result;
165*10465441SEvalZero 
166*10465441SEvalZero     if (cond == RT_NULL)
167*10465441SEvalZero         return EINVAL;
168*10465441SEvalZero     if (cond->attr == -1)
169*10465441SEvalZero         pthread_cond_init(cond, RT_NULL);
170*10465441SEvalZero 
171*10465441SEvalZero     result = rt_sem_release(&(cond->sem));
172*10465441SEvalZero     if (result == RT_EOK)
173*10465441SEvalZero         return 0;
174*10465441SEvalZero 
175*10465441SEvalZero     return 0;
176*10465441SEvalZero }
177*10465441SEvalZero RTM_EXPORT(pthread_cond_signal);
178*10465441SEvalZero 
_pthread_cond_timedwait(pthread_cond_t * cond,pthread_mutex_t * mutex,rt_int32_t timeout)179*10465441SEvalZero rt_err_t _pthread_cond_timedwait(pthread_cond_t  *cond,
180*10465441SEvalZero                                  pthread_mutex_t *mutex,
181*10465441SEvalZero                                  rt_int32_t       timeout)
182*10465441SEvalZero {
183*10465441SEvalZero     rt_err_t result;
184*10465441SEvalZero 
185*10465441SEvalZero     if (!cond || !mutex)
186*10465441SEvalZero         return -RT_ERROR;
187*10465441SEvalZero     /* check whether initialized */
188*10465441SEvalZero     if (cond->attr == -1)
189*10465441SEvalZero         pthread_cond_init(cond, RT_NULL);
190*10465441SEvalZero 
191*10465441SEvalZero     /* The mutex was not owned by the current thread at the time of the call. */
192*10465441SEvalZero     if (mutex->lock.owner != pthread_self())
193*10465441SEvalZero         return -RT_ERROR;
194*10465441SEvalZero     /* unlock a mutex failed */
195*10465441SEvalZero     if (pthread_mutex_unlock(mutex) != 0)
196*10465441SEvalZero         return -RT_ERROR;
197*10465441SEvalZero 
198*10465441SEvalZero     result = rt_sem_take(&(cond->sem), timeout);
199*10465441SEvalZero     /* lock mutex again */
200*10465441SEvalZero     pthread_mutex_lock(mutex);
201*10465441SEvalZero 
202*10465441SEvalZero     return result;
203*10465441SEvalZero }
204*10465441SEvalZero RTM_EXPORT(_pthread_cond_timedwait);
205*10465441SEvalZero 
pthread_cond_wait(pthread_cond_t * cond,pthread_mutex_t * mutex)206*10465441SEvalZero int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
207*10465441SEvalZero {
208*10465441SEvalZero     rt_err_t result;
209*10465441SEvalZero 
210*10465441SEvalZero     result = _pthread_cond_timedwait(cond, mutex, RT_WAITING_FOREVER);
211*10465441SEvalZero     if (result == RT_EOK)
212*10465441SEvalZero         return 0;
213*10465441SEvalZero 
214*10465441SEvalZero     return EINVAL;
215*10465441SEvalZero }
216*10465441SEvalZero RTM_EXPORT(pthread_cond_wait);
217*10465441SEvalZero 
pthread_cond_timedwait(pthread_cond_t * cond,pthread_mutex_t * mutex,const struct timespec * abstime)218*10465441SEvalZero int pthread_cond_timedwait(pthread_cond_t        *cond,
219*10465441SEvalZero                            pthread_mutex_t       *mutex,
220*10465441SEvalZero                            const struct timespec *abstime)
221*10465441SEvalZero {
222*10465441SEvalZero     int timeout;
223*10465441SEvalZero     rt_err_t result;
224*10465441SEvalZero 
225*10465441SEvalZero     timeout = clock_time_to_tick(abstime);
226*10465441SEvalZero     result = _pthread_cond_timedwait(cond, mutex, timeout);
227*10465441SEvalZero     if (result == RT_EOK)
228*10465441SEvalZero         return 0;
229*10465441SEvalZero     if (result == -RT_ETIMEOUT)
230*10465441SEvalZero         return ETIMEDOUT;
231*10465441SEvalZero 
232*10465441SEvalZero     return EINVAL;
233*10465441SEvalZero }
234*10465441SEvalZero RTM_EXPORT(pthread_cond_timedwait);
235*10465441SEvalZero 
236