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