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