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