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 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 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 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 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 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 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 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 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 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 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 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 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 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