• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <errno.h>
33 #include <pthread.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <securec.h>
37 #include "los_config.h"
38 #include "los_task.h"
39 #include "los_swtmr.h"
40 #include "time_internal.h"
41 #include "los_atomic.h"
42 #include "los_event.h"
43 #include "los_mux.h"
44 
45 #define INLINE inline
46 
47 #define BROADCAST_EVENT     1
48 #define COND_COUNTER_STEP   0x0004U
49 #define COND_FLAGS_MASK     0x0003U
50 #define COND_COUNTER_MASK   (~COND_FLAGS_MASK)
51 
pthread_condattr_getpshared(const pthread_condattr_t * attr,int * shared)52 int pthread_condattr_getpshared(const pthread_condattr_t *attr, int *shared)
53 {
54     if ((attr == NULL) || (shared == NULL)) {
55         return EINVAL;
56     }
57 
58     *shared = PTHREAD_PROCESS_PRIVATE;
59 
60     return 0;
61 }
62 
pthread_condattr_setpshared(pthread_condattr_t * attr,int shared)63 int pthread_condattr_setpshared(pthread_condattr_t *attr, int shared)
64 {
65     (VOID)attr;
66     if ((shared != PTHREAD_PROCESS_PRIVATE) && (shared != PTHREAD_PROCESS_SHARED)) {
67         return EINVAL;
68     }
69 
70     if (shared != PTHREAD_PROCESS_PRIVATE) {
71         return ENOSYS;
72     }
73 
74     return 0;
75 }
76 
pthread_condattr_destroy(pthread_condattr_t * attr)77 int pthread_condattr_destroy(pthread_condattr_t *attr)
78 {
79     if (attr == NULL) {
80         return EINVAL;
81     }
82 
83     (VOID)memset_s(attr, sizeof(pthread_condattr_t), 0, sizeof(pthread_condattr_t));
84     attr->clock = INT32_MAX;
85 
86     return 0;
87 }
88 
pthread_condattr_getclock(const pthread_condattr_t * attr,clockid_t * clock)89 int pthread_condattr_getclock(const pthread_condattr_t *attr, clockid_t *clock)
90 {
91     if ((attr == NULL) || (clock == NULL)) {
92         return -1;
93     }
94 
95     *clock = attr->clock;
96 
97     return 0;
98 }
99 
pthread_condattr_init(pthread_condattr_t * attr)100 int pthread_condattr_init(pthread_condattr_t *attr)
101 {
102     if (attr == NULL) {
103         return EINVAL;
104     }
105 
106     attr->clock = CLOCK_REALTIME;
107 
108     return 0;
109 }
110 
pthread_condattr_setclock(pthread_condattr_t * attr,clockid_t clk)111 int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clk)
112 {
113     if ((attr == NULL) || (clk < 0)) {
114         return EINVAL;
115     }
116 
117     if ((clk != CLOCK_REALTIME) && (clk != CLOCK_MONOTONIC) &&
118         (clk != CLOCK_PROCESS_CPUTIME_ID) && (clk != CLOCK_THREAD_CPUTIME_ID)) {
119         return EINVAL;
120     }
121 
122     attr->clock = clk;
123 
124     return 0;
125 }
126 
CondInitCheck(const pthread_cond_t * cond)127 STATIC INLINE INT32 CondInitCheck(const pthread_cond_t *cond)
128 {
129     if ((cond->event.stEventList.pstPrev == NULL) &&
130         (cond->event.stEventList.pstNext == NULL)) {
131         return 1;
132     }
133 
134     return 0;
135 }
136 
pthread_cond_init(pthread_cond_t * cond,const pthread_condattr_t * attr)137 int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
138 {
139     int ret = 0;
140     pthread_condattr_t condAttr;
141 
142     if (cond == NULL) {
143         return EINVAL;
144     }
145 
146     if (attr == NULL) {
147         pthread_condattr_init(&condAttr);
148         attr = &condAttr;
149     }
150 
151     (VOID)LOS_EventInit(&(cond->event));
152 
153     cond->mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
154     if (cond->mutex == NULL) {
155         return ENOMEM;
156     }
157 
158     (VOID)pthread_mutex_init(cond->mutex, NULL);
159 
160     cond->value = 0;
161     (VOID)pthread_mutex_lock(cond->mutex);
162     cond->count = 0;
163     cond->clock = attr->clock;
164     (VOID)pthread_mutex_unlock(cond->mutex);
165 
166     return ret;
167 }
168 
pthread_cond_destroy(pthread_cond_t * cond)169 int pthread_cond_destroy(pthread_cond_t *cond)
170 {
171     if (cond == NULL) {
172         return EINVAL;
173     }
174 
175     if (CondInitCheck(cond)) {
176         return 0;
177     }
178 
179     if (LOS_EventDestroy(&cond->event) != LOS_OK) {
180         return EBUSY;
181     }
182     if (pthread_mutex_destroy(cond->mutex) != 0) {
183         PRINT_ERR("%s mutex destroy fail!\n", __FUNCTION__);
184         return EINVAL;
185     }
186     free(cond->mutex);
187     cond->mutex = NULL;
188 
189     return 0;
190 }
191 
PthreadCountSub(pthread_cond_t * cond)192 STATIC VOID PthreadCountSub(pthread_cond_t *cond)
193 {
194     (VOID)pthread_mutex_lock(cond->mutex);
195     if (cond->count > 0) {
196         cond->count--;
197     }
198     (VOID)pthread_mutex_unlock(cond->mutex);
199 }
200 
201 
pthread_cond_broadcast(pthread_cond_t * cond)202 int pthread_cond_broadcast(pthread_cond_t *cond)
203 {
204     int ret = 0;
205 
206     if (cond == NULL) {
207         return EINVAL;
208     }
209 
210     (VOID)pthread_mutex_lock(cond->mutex);
211     if (cond->count > 0) {
212         cond->count = 0;
213         (VOID)pthread_mutex_unlock(cond->mutex);
214         (VOID)LOS_EventWrite(&(cond->event), BROADCAST_EVENT);
215         return ret;
216     }
217     (VOID)pthread_mutex_unlock(cond->mutex);
218 
219     return ret;
220 }
221 
pthread_cond_signal(pthread_cond_t * cond)222 int pthread_cond_signal(pthread_cond_t *cond)
223 {
224     int ret = 0;
225 
226     if (cond == NULL) {
227         return EINVAL;
228     }
229 
230     (VOID)pthread_mutex_lock(cond->mutex);
231     if (cond->count > 0) {
232         cond->count--;
233         (VOID)pthread_mutex_unlock(cond->mutex);
234         // This should modify to once.
235         (VOID)LOS_EventWrite(&(cond->event), BROADCAST_EVENT);
236 
237         return ret;
238     }
239     (VOID)pthread_mutex_unlock(cond->mutex);
240 
241     return ret;
242 }
243 
ProcessReturnVal(pthread_cond_t * cond,INT32 val)244 STATIC INT32 ProcessReturnVal(pthread_cond_t *cond, INT32 val)
245 {
246     INT32 ret;
247     switch (val) {
248         /* 0: event does not occur */
249         case 0:
250         case BROADCAST_EVENT:
251             ret = 0;
252             break;
253         case LOS_ERRNO_EVENT_READ_TIMEOUT:
254             PthreadCountSub(cond);
255             ret = ETIMEDOUT;
256             break;
257         default:
258             PthreadCountSub(cond);
259             ret = EINVAL;
260             break;
261     }
262 
263     return ret;
264 }
265 
pthread_cond_timedwait(pthread_cond_t * cond,pthread_mutex_t * mutex,const struct timespec * ts)266 int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
267                            const struct timespec *ts)
268 {
269     INT32 ret;
270     UINT64 absTicks;
271     LosMuxCB *muxPosted = NULL;
272     pthread_testcancel();
273     if ((cond == NULL) || (mutex == NULL) || (ts == NULL) || (mutex->magic != _MUX_MAGIC)) {
274         return EINVAL;
275     }
276 
277     muxPosted = GET_MUX(mutex->handle);
278     if ((mutex->stAttr.type == PTHREAD_MUTEX_ERRORCHECK) && (g_losTask.runTask != muxPosted->owner)) {
279         return EPERM;
280     }
281 
282     if (CondInitCheck(cond)) {
283         ret = pthread_cond_init(cond, NULL);
284         if (ret != 0) {
285             return ret;
286         }
287     }
288 
289     (VOID)pthread_mutex_lock(cond->mutex);
290     cond->count++;
291     (VOID)pthread_mutex_unlock(cond->mutex);
292 
293     ret = OsGetTickTimeFromNow(ts, cond->clock, &absTicks);
294     if (ret != 0) {
295         return ret;
296     }
297 
298     if (absTicks >= UINT32_MAX) {
299         return EINVAL;
300     }
301 
302     if (pthread_mutex_unlock(mutex) != 0) {
303         PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
304     }
305 
306     ret = (INT32)LOS_EventRead(&(cond->event), 0x0f, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, (UINT32)absTicks);
307 
308     if (pthread_mutex_lock(mutex) != 0) {
309         PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
310     }
311 
312     ret = ProcessReturnVal(cond, ret);
313     pthread_testcancel();
314 
315     return ret;
316 }
317 
pthread_cond_wait(pthread_cond_t * cond,pthread_mutex_t * mutex)318 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
319 {
320     int ret;
321 
322     if ((cond == NULL) || (mutex == NULL)) {
323         return EINVAL;
324     }
325 
326     if (CondInitCheck(cond)) {
327         ret = pthread_cond_init(cond, NULL);
328         if (ret != 0) {
329             return ret;
330         }
331     }
332 
333     (VOID)pthread_mutex_lock(cond->mutex);
334     cond->count++;
335     (VOID)pthread_mutex_unlock(cond->mutex);
336 
337     if (pthread_mutex_unlock(mutex) != 0) {
338         PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
339     }
340     ret = (INT32)LOS_EventRead(&(cond->event), 0x0f, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
341     if (pthread_mutex_lock(mutex) != 0) {
342         PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
343     }
344 
345     switch (ret) {
346         /* 0: event does not occur */
347         case 0:
348         case BROADCAST_EVENT:
349             ret = 0;
350             break;
351         default:
352             PthreadCountSub(cond);
353             ret = EINVAL;
354             break;
355     }
356 
357     return ret;
358 }
359