thr_cond.c (164583) | thr_cond.c (164877) |
---|---|
1/* 2 * Copyright (c) 2005 David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * | 1/* 2 * Copyright (c) 2005 David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/lib/libthr/thread/thr_cond.c 164583 2006-11-24 09:57:38Z davidxu $ | 26 * $FreeBSD: head/lib/libthr/thread/thr_cond.c 164877 2006-12-04 14:20:41Z davidxu $ |
27 */ 28 29#include "namespace.h" 30#include <stdlib.h> 31#include <errno.h> 32#include <string.h> 33#include <pthread.h> 34#include <limits.h> --- 27 unchanged lines hidden (view full) --- 62 63static int 64cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) 65{ 66 pthread_cond_t pcond; 67 int rval = 0; 68 69 if ((pcond = (pthread_cond_t) | 27 */ 28 29#include "namespace.h" 30#include <stdlib.h> 31#include <errno.h> 32#include <string.h> 33#include <pthread.h> 34#include <limits.h> --- 27 unchanged lines hidden (view full) --- 62 63static int 64cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) 65{ 66 pthread_cond_t pcond; 67 int rval = 0; 68 69 if ((pcond = (pthread_cond_t) |
70 malloc(sizeof(struct pthread_cond))) == NULL) { | 70 calloc(1, sizeof(struct pthread_cond))) == NULL) { |
71 rval = ENOMEM; 72 } else { 73 /* 74 * Initialise the condition variable structure: 75 */ | 71 rval = ENOMEM; 72 } else { 73 /* 74 * Initialise the condition variable structure: 75 */ |
76 _thr_umutex_init(&pcond->c_lock); 77 pcond->c_seqno = 0; 78 pcond->c_waiters = 0; 79 pcond->c_wakeups = 0; | |
80 if (cond_attr == NULL || *cond_attr == NULL) { 81 pcond->c_pshared = 0; 82 pcond->c_clockid = CLOCK_REALTIME; 83 } else { 84 pcond->c_pshared = (*cond_attr)->c_pshared; 85 pcond->c_clockid = (*cond_attr)->c_clockid; 86 } | 76 if (cond_attr == NULL || *cond_attr == NULL) { 77 pcond->c_pshared = 0; 78 pcond->c_clockid = CLOCK_REALTIME; 79 } else { 80 pcond->c_pshared = (*cond_attr)->c_pshared; 81 pcond->c_clockid = (*cond_attr)->c_clockid; 82 } |
83 _thr_umutex_init(&pcond->c_lock); |
|
87 *cond = pcond; 88 } 89 /* Return the completion status: */ 90 return (rval); 91} 92 93static int 94init_static(struct pthread *thread, pthread_cond_t *cond) --- 18 unchanged lines hidden (view full) --- 113 114 *cond = NULL; 115 return (cond_init(cond, cond_attr)); 116} 117 118int 119_pthread_cond_destroy(pthread_cond_t *cond) 120{ | 84 *cond = pcond; 85 } 86 /* Return the completion status: */ 87 return (rval); 88} 89 90static int 91init_static(struct pthread *thread, pthread_cond_t *cond) --- 18 unchanged lines hidden (view full) --- 110 111 *cond = NULL; 112 return (cond_init(cond, cond_attr)); 113} 114 115int 116_pthread_cond_destroy(pthread_cond_t *cond) 117{ |
121 struct pthread_cond *cv; | |
122 struct pthread *curthread = _get_curthread(); | 118 struct pthread *curthread = _get_curthread(); |
119 struct pthread_cond *cv; |
|
123 int rval = 0; 124 125 if (*cond == NULL) 126 rval = EINVAL; 127 else { | 120 int rval = 0; 121 122 if (*cond == NULL) 123 rval = EINVAL; 124 else { |
125 cv = *cond; 126 THR_UMUTEX_LOCK(curthread, &cv->c_lock); |
|
128 /* Lock the condition variable structure: */ | 127 /* Lock the condition variable structure: */ |
129 THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock); 130 if ((*cond)->c_waiters + (*cond)->c_wakeups != 0) { 131 THR_LOCK_RELEASE(curthread, &(*cond)->c_lock); | 128 if (cv->c_kerncv.c_has_waiters) { 129 THR_UMUTEX_UNLOCK(curthread, &cv->c_lock); |
132 return (EBUSY); 133 } | 130 return (EBUSY); 131 } |
134 | |
135 /* 136 * NULL the caller's pointer now that the condition 137 * variable has been destroyed: 138 */ | 132 /* 133 * NULL the caller's pointer now that the condition 134 * variable has been destroyed: 135 */ |
139 cv = *cond; | |
140 *cond = NULL; | 136 *cond = NULL; |
137 THR_UMUTEX_UNLOCK(curthread, &cv->c_lock); |
|
141 | 138 |
142 /* Unlock the condition variable structure: */ 143 THR_LOCK_RELEASE(curthread, &cv->c_lock); 144 145 /* Free the cond lock structure: */ 146 | |
147 /* 148 * Free the memory allocated for the condition 149 * variable structure: 150 */ 151 free(cv); 152 153 } 154 /* Return the completion status: */ 155 return (rval); 156} 157 158struct cond_cancel_info 159{ 160 pthread_mutex_t *mutex; 161 pthread_cond_t *cond; | 139 /* 140 * Free the memory allocated for the condition 141 * variable structure: 142 */ 143 free(cv); 144 145 } 146 /* Return the completion status: */ 147 return (rval); 148} 149 150struct cond_cancel_info 151{ 152 pthread_mutex_t *mutex; 153 pthread_cond_t *cond; |
162 long seqno; | |
163 int count; 164}; 165 166static void 167cond_cancel_handler(void *arg) 168{ 169 struct pthread *curthread = _get_curthread(); 170 struct cond_cancel_info *info = (struct cond_cancel_info *)arg; | 154 int count; 155}; 156 157static void 158cond_cancel_handler(void *arg) 159{ 160 struct pthread *curthread = _get_curthread(); 161 struct cond_cancel_info *info = (struct cond_cancel_info *)arg; |
171 pthread_cond_t cv; | 162 pthread_cond_t cv; |
172 173 cv = *(info->cond); | 163 164 cv = *(info->cond); |
174 THR_LOCK_ACQUIRE(curthread, &cv->c_lock); 175 if (cv->c_seqno != info->seqno && cv->c_wakeups != 0) { 176 if (cv->c_waiters > 0) { 177 cv->c_seqno++; 178 _thr_umtx_wake(&cv->c_seqno, 1); 179 } else 180 cv->c_wakeups--; 181 } else { 182 cv->c_waiters--; 183 } 184 THR_LOCK_RELEASE(curthread, &cv->c_lock); 185 | 165 if ((cv->c_lock.m_owner & ~UMUTEX_CONTESTED) == TID(curthread)) 166 THR_UMUTEX_UNLOCK(curthread, &cv->c_lock); |
186 _mutex_cv_lock(info->mutex, info->count); 187} 188 189static int 190cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex, 191 const struct timespec *abstime, int cancel) 192{ 193 struct pthread *curthread = _get_curthread(); 194 struct timespec ts, ts2, *tsp; 195 struct cond_cancel_info info; 196 pthread_cond_t cv; | 167 _mutex_cv_lock(info->mutex, info->count); 168} 169 170static int 171cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex, 172 const struct timespec *abstime, int cancel) 173{ 174 struct pthread *curthread = _get_curthread(); 175 struct timespec ts, ts2, *tsp; 176 struct cond_cancel_info info; 177 pthread_cond_t cv; |
197 long seq, oldseq; | |
198 int ret = 0; 199 200 /* 201 * If the condition variable is statically initialized, 202 * perform the dynamic initialization: 203 */ 204 if (__predict_false(*cond == NULL && 205 (ret = init_static(curthread, cond)) != 0)) 206 return (ret); 207 208 cv = *cond; | 178 int ret = 0; 179 180 /* 181 * If the condition variable is statically initialized, 182 * perform the dynamic initialization: 183 */ 184 if (__predict_false(*cond == NULL && 185 (ret = init_static(curthread, cond)) != 0)) 186 return (ret); 187 188 cv = *cond; |
209 THR_LOCK_ACQUIRE(curthread, &cv->c_lock); | 189 THR_UMUTEX_LOCK(curthread, &cv->c_lock); |
210 ret = _mutex_cv_unlock(mutex, &info.count); 211 if (ret) { | 190 ret = _mutex_cv_unlock(mutex, &info.count); 191 if (ret) { |
212 THR_LOCK_RELEASE(curthread, &cv->c_lock); | 192 THR_UMUTEX_UNLOCK(curthread, &cv->c_lock); |
213 return (ret); 214 } | 193 return (ret); 194 } |
215 oldseq = seq = cv->c_seqno; | 195 |
216 info.mutex = mutex; 217 info.cond = cond; | 196 info.mutex = mutex; 197 info.cond = cond; |
218 info.seqno = oldseq; | |
219 | 198 |
220 cv->c_waiters++; 221 do { 222 THR_LOCK_RELEASE(curthread, &cv->c_lock); | 199 if (abstime != NULL) { 200 clock_gettime(cv->c_clockid, &ts); 201 TIMESPEC_SUB(&ts2, abstime, &ts); 202 tsp = &ts2; 203 } else 204 tsp = NULL; |
223 | 205 |
224 if (abstime != NULL) { 225 clock_gettime(cv->c_clockid, &ts); 226 TIMESPEC_SUB(&ts2, abstime, &ts); 227 tsp = &ts2; 228 } else 229 tsp = NULL; 230 231 if (cancel) { 232 THR_CLEANUP_PUSH(curthread, cond_cancel_handler, &info); 233 _thr_cancel_enter(curthread); 234 ret = _thr_umtx_wait(&cv->c_seqno, seq, tsp); 235 _thr_cancel_leave(curthread); 236 THR_CLEANUP_POP(curthread, 0); 237 } else { 238 ret = _thr_umtx_wait(&cv->c_seqno, seq, tsp); 239 } 240 241 THR_LOCK_ACQUIRE(curthread, &cv->c_lock); 242 seq = cv->c_seqno; 243 if (abstime != NULL && ret == ETIMEDOUT) 244 break; 245 246 /* 247 * loop if we have never been told to wake up 248 * or we lost a race. 249 */ 250 } while (seq == oldseq || cv->c_wakeups == 0); 251 252 if (seq != oldseq && cv->c_wakeups != 0) { 253 cv->c_wakeups--; 254 ret = 0; | 206 if (cancel) { 207 THR_CLEANUP_PUSH(curthread, cond_cancel_handler, &info); 208 _thr_cancel_enter_defer(curthread); 209 ret = _thr_ucond_wait(&cv->c_kerncv, &cv->c_lock, tsp, 1); 210 _thr_cancel_leave_defer(curthread, ret); 211 THR_CLEANUP_POP(curthread, 0); |
255 } else { | 212 } else { |
256 cv->c_waiters--; | 213 ret = _thr_ucond_wait(&cv->c_kerncv, &cv->c_lock, tsp, 0); |
257 } | 214 } |
258 THR_LOCK_RELEASE(curthread, &cv->c_lock); | 215 if (ret == EINTR) 216 ret = 0; |
259 _mutex_cv_lock(mutex, info.count); 260 return (ret); 261} 262 263int 264_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) 265{ 266 --- 31 unchanged lines hidden (view full) --- 298 return (cond_wait_common(cond, mutex, abstime, 1)); 299} 300 301static int 302cond_signal_common(pthread_cond_t *cond, int broadcast) 303{ 304 struct pthread *curthread = _get_curthread(); 305 pthread_cond_t cv; | 217 _mutex_cv_lock(mutex, info.count); 218 return (ret); 219} 220 221int 222_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) 223{ 224 --- 31 unchanged lines hidden (view full) --- 256 return (cond_wait_common(cond, mutex, abstime, 1)); 257} 258 259static int 260cond_signal_common(pthread_cond_t *cond, int broadcast) 261{ 262 struct pthread *curthread = _get_curthread(); 263 pthread_cond_t cv; |
306 int ret = 0, oldwaiters; | 264 int ret = 0; |
307 308 /* 309 * If the condition variable is statically initialized, perform dynamic 310 * initialization. 311 */ 312 if (__predict_false(*cond == NULL && 313 (ret = init_static(curthread, cond)) != 0)) 314 return (ret); 315 316 cv = *cond; | 265 266 /* 267 * If the condition variable is statically initialized, perform dynamic 268 * initialization. 269 */ 270 if (__predict_false(*cond == NULL && 271 (ret = init_static(curthread, cond)) != 0)) 272 return (ret); 273 274 cv = *cond; |
317 /* Lock the condition variable structure. */ 318 THR_LOCK_ACQUIRE(curthread, &cv->c_lock); 319 if (cv->c_waiters) { 320 if (!broadcast) { 321 cv->c_wakeups++; 322 cv->c_waiters--; 323 cv->c_seqno++; 324 _thr_umtx_wake(&cv->c_seqno, 1); 325 } else { 326 oldwaiters = cv->c_waiters; 327 cv->c_wakeups += cv->c_waiters; 328 cv->c_waiters = 0; 329 cv->c_seqno++; 330 _thr_umtx_wake(&cv->c_seqno, oldwaiters); 331 } | 275 THR_UMUTEX_LOCK(curthread, &cv->c_lock); 276 if (cv->c_kerncv.c_has_waiters) { 277 if (!broadcast) 278 ret = _thr_ucond_signal(&cv->c_kerncv); 279 else 280 ret = _thr_ucond_broadcast(&cv->c_kerncv); |
332 } | 281 } |
333 THR_LOCK_RELEASE(curthread, &cv->c_lock); | 282 THR_UMUTEX_UNLOCK(curthread, &cv->c_lock); |
334 return (ret); 335} 336 337int 338_pthread_cond_signal(pthread_cond_t * cond) 339{ 340 341 return (cond_signal_common(cond, 0)); 342} 343 344int 345_pthread_cond_broadcast(pthread_cond_t * cond) 346{ 347 348 return (cond_signal_common(cond, 1)); 349} | 283 return (ret); 284} 285 286int 287_pthread_cond_signal(pthread_cond_t * cond) 288{ 289 290 return (cond_signal_common(cond, 0)); 291} 292 293int 294_pthread_cond_broadcast(pthread_cond_t * cond) 295{ 296 297 return (cond_signal_common(cond, 1)); 298} |