thr_cond.c (127566) | thr_cond.c (129484) |
---|---|
1/* 2 * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. 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 --- 15 unchanged lines hidden (view full) --- 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * | 1/* 2 * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. 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 --- 15 unchanged lines hidden (view full) --- 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * |
32 * $FreeBSD: head/lib/libthr/thread/thr_cond.c 127566 2004-03-29 11:24:02Z mtm $ | 32 * $FreeBSD: head/lib/libthr/thread/thr_cond.c 129484 2004-05-20 12:06:16Z mtm $ |
33 */ 34#include <stdlib.h> 35#include <errno.h> 36#include <string.h> 37#include <pthread.h> 38#include "thr_private.h" 39 40/* --- 154 unchanged lines hidden (view full) --- 195 return (cond_wait_common(cond, mutex, abstime)); 196} 197 198static int 199cond_wait_common(pthread_cond_t * cond, pthread_mutex_t * mutex, 200 const struct timespec * abstime) 201{ 202 int rval = 0; | 33 */ 34#include <stdlib.h> 35#include <errno.h> 36#include <string.h> 37#include <pthread.h> 38#include "thr_private.h" 39 40/* --- 154 unchanged lines hidden (view full) --- 195 return (cond_wait_common(cond, mutex, abstime)); 196} 197 198static int 199cond_wait_common(pthread_cond_t * cond, pthread_mutex_t * mutex, 200 const struct timespec * abstime) 201{ 202 int rval = 0; |
203 int done = 0; 204 int seqno; | |
205 int mtxrval; 206 207 | 203 int mtxrval; 204 205 |
208 _thread_enter_cancellation_point(); 209 | |
210 if (cond == NULL) 211 return (EINVAL); 212 /* 213 * If the condition variable is statically initialized, perform dynamic 214 * initialization. 215 */ 216 if (*cond == PTHREAD_COND_INITIALIZER && (rval = cond_init(cond)) != 0) 217 return (rval); 218 | 206 if (cond == NULL) 207 return (EINVAL); 208 /* 209 * If the condition variable is statically initialized, perform dynamic 210 * initialization. 211 */ 212 if (*cond == PTHREAD_COND_INITIALIZER && (rval = cond_init(cond)) != 0) 213 return (rval); 214 |
215 if ((*cond)->c_type != COND_TYPE_FAST) 216 return (EINVAL); |
|
219 220 COND_LOCK(*cond); 221 222 /* 223 * If the condvar was statically allocated, properly 224 * initialize the tail queue. 225 */ 226 if (((*cond)->c_flags & COND_FLAGS_INITED) == 0) { 227 TAILQ_INIT(&(*cond)->c_queue); 228 (*cond)->c_flags |= COND_FLAGS_INITED; 229 } 230 | 217 218 COND_LOCK(*cond); 219 220 /* 221 * If the condvar was statically allocated, properly 222 * initialize the tail queue. 223 */ 224 if (((*cond)->c_flags & COND_FLAGS_INITED) == 0) { 225 TAILQ_INIT(&(*cond)->c_queue); 226 (*cond)->c_flags |= COND_FLAGS_INITED; 227 } 228 |
231 /* Process according to condition variable type. */ | 229 if ((mutex == NULL) || (((*cond)->c_mutex != NULL) && 230 ((*cond)->c_mutex != *mutex))) { 231 COND_UNLOCK(*cond); 232 return (EINVAL); 233 } 234 /* Remember the mutex */ 235 (*cond)->c_mutex = *mutex; |
232 | 236 |
233 switch ((*cond)->c_type) { 234 /* Fast condition variable: */ 235 case COND_TYPE_FAST: 236 if ((mutex == NULL) || (((*cond)->c_mutex != NULL) && 237 ((*cond)->c_mutex != *mutex))) { 238 COND_UNLOCK(*cond); 239 rval = EINVAL; 240 break; 241 } 242 /* Remember the mutex */ 243 (*cond)->c_mutex = *mutex; 244 245 if ((rval = _mutex_cv_unlock(mutex)) != 0) { 246 if (rval == -1){ 247 printf("foo"); 248 fflush(stdout); 249 abort(); 250 } 251 252 COND_UNLOCK(*cond); 253 break; | 237 _thread_enter_cancellation_point(); 238 if ((rval = _mutex_cv_unlock(mutex)) != 0) { 239 if (rval == -1){ 240 printf("mutex unlock by condvar failed!"); 241 fflush(stdout); 242 abort(); |
254 } | 243 } |
244 _thread_leave_cancellation_point(); 245 COND_UNLOCK(*cond); 246 return (rval); 247 } |
|
255 | 248 |
256 /* 257 * We need to protect the queue operations. It also 258 * protects c_seqno and the pthread flag fields. This is 259 * dropped before calling _thread_suspend() and reaquired 260 * when we return. 261 */ | 249 /* 250 * We need to protect the queue operations. It also 251 * protects the pthread flag field. This is 252 * dropped before calling _thread_suspend() and reaquired 253 * when we return. 254 */ 255 PTHREAD_LOCK(curthread); |
262 | 256 |
263 _thread_critical_enter(curthread); 264 /* 265 * c_seqno is protected. 266 */ 267 seqno = (*cond)->c_seqno; 268 269 do { | 257 /* 258 * Queue the running thread on the condition 259 * variable and wait to be signaled. 260 */ 261 cond_queue_enq(*cond, curthread); 262 do { 263 PTHREAD_UNLOCK(curthread); 264 COND_UNLOCK(*cond); 265 if (curthread->cancellation == CS_PENDING) { |
270 /* | 266 /* |
271 * Queue the running thread on the condition 272 * variable. | 267 * Posix says we must lock the mutex 268 * even if we're being canceled. |
273 */ | 269 */ |
274 cond_queue_enq(*cond, curthread); 275 276 if (curthread->cancelflags & PTHREAD_CANCELLING) { 277 /* 278 * POSIX Says that we must relock the mutex 279 * even if we're being canceled. 280 */ 281 _thread_critical_exit(curthread); 282 COND_UNLOCK(*cond); 283 _mutex_cv_lock(mutex); 284 pthread_testcancel(); 285 PANIC("Shouldn't have come back."); 286 } 287 288 PTHREAD_SET_STATE(curthread, PS_COND_WAIT); 289 _thread_critical_exit(curthread); 290 COND_UNLOCK(*cond); 291 rval = _thread_suspend(curthread, (struct timespec *)abstime); 292 if (rval != 0 && rval != ETIMEDOUT && rval != EINTR) { 293 printf("foo"); 294 fflush(stdout); 295 abort(); 296 } 297 COND_LOCK(*cond); 298 _thread_critical_enter(curthread); 299 300 done = (seqno != (*cond)->c_seqno); 301 | 270 _mutex_cv_lock(mutex); 271 _thread_leave_cancellation_point(); 272 PANIC("Shouldn't have come back."); 273 } 274 rval = _thread_suspend(curthread, (struct timespec *)abstime); 275 if (rval != 0 && rval != ETIMEDOUT && rval != EINTR) { 276 printf("thread suspend returned an invalid value"); 277 fflush(stdout); 278 abort(); 279 } 280 COND_LOCK(*cond); 281 PTHREAD_LOCK(curthread); 282 if (rval == ETIMEDOUT) { |
302 /* | 283 /* |
303 * If we timed out, this will remove us from the 304 * queue. Otherwise, if we were signaled it does 305 * nothing because this thread won't be on the queue. | 284 * Condition may have been signaled between the 285 * time the thread timed out and locked the condvar. 286 * If it wasn't, manually remove it from the queue. |
306 */ | 287 */ |
307 cond_queue_remove(*cond, curthread); 308 309 } while ((done == 0) && (rval == 0)); 310 /* 311 * If we timed out someone still may have signaled us 312 * before we got a chance to run again. We check for 313 * this by looking to see if our state is RUNNING. 314 */ 315 if (rval == ETIMEDOUT) { 316 if (curthread->state != PS_RUNNING) { 317 PTHREAD_SET_STATE(curthread, PS_RUNNING); 318 } else | 288 if ((curthread->flags & PTHREAD_FLAGS_IN_CONDQ) == 0) |
319 rval = 0; | 289 rval = 0; |
290 else 291 cond_queue_remove(*cond, curthread); |
|
320 } | 292 } |
321 _thread_critical_exit(curthread); 322 COND_UNLOCK(*cond); | 293 } while ((curthread->flags & PTHREAD_FLAGS_IN_CONDQ) != 0); |
323 | 294 |
324 mtxrval = _mutex_cv_lock(mutex); | 295 PTHREAD_UNLOCK(curthread); 296 COND_UNLOCK(*cond); 297 mtxrval = _mutex_cv_lock(mutex); |
325 | 298 |
326 /* 327 * If the mutex failed return that error, otherwise we're 328 * returning ETIMEDOUT. 329 */ 330 if (mtxrval == -1) { 331 printf("foo"); 332 fflush(stdout); 333 abort(); 334 } 335 if (mtxrval != 0) 336 rval = mtxrval; 337 338 break; 339 340 /* Trap invalid condition variable types: */ 341 default: 342 COND_UNLOCK(*cond); 343 rval = EINVAL; 344 break; | 299 /* If the mutex failed return that error. */ 300 if (mtxrval == -1) { 301 printf("mutex lock from condvar failed!"); 302 fflush(stdout); 303 abort(); |
345 } | 304 } |
305 if (mtxrval != 0) 306 rval = mtxrval; |
|
346 347 _thread_leave_cancellation_point(); | 307 308 _thread_leave_cancellation_point(); |
348 | |
349 return (rval); 350} 351 352int 353_pthread_cond_signal(pthread_cond_t * cond) 354{ 355 return (cond_signal(cond, 0)); 356} --- 14 unchanged lines hidden (view full) --- 371 return (EINVAL); 372 /* 373 * If the condition variable is statically initialized, perform dynamic 374 * initialization. 375 */ 376 if (*cond == PTHREAD_COND_INITIALIZER && (rval = cond_init(cond)) != 0) 377 return (rval); 378 | 309 return (rval); 310} 311 312int 313_pthread_cond_signal(pthread_cond_t * cond) 314{ 315 return (cond_signal(cond, 0)); 316} --- 14 unchanged lines hidden (view full) --- 331 return (EINVAL); 332 /* 333 * If the condition variable is statically initialized, perform dynamic 334 * initialization. 335 */ 336 if (*cond == PTHREAD_COND_INITIALIZER && (rval = cond_init(cond)) != 0) 337 return (rval); 338 |
339 if ((*cond)->c_type != COND_TYPE_FAST) 340 return (EINVAL); |
|
379 COND_LOCK(*cond); 380 | 341 COND_LOCK(*cond); 342 |
381 /* Process according to condition variable type: */ 382 switch ((*cond)->c_type) { 383 /* Fast condition variable: */ 384 case COND_TYPE_FAST: 385 (*cond)->c_seqno++; 386 | 343 /* 344 * Enter a loop to bring all (or only one) threads off the 345 * condition queue: 346 */ 347 do { |
387 /* | 348 /* |
388 * Enter a loop to bring all (or only one) threads off the 389 * condition queue: | 349 * Wake up the signaled thread. It will be returned 350 * to us locked. |
390 */ | 351 */ |
391 do { 392 /* 393 * Wake up the signaled thread. It will be returned 394 * to us locked, and with signals disabled. 395 */ 396 if ((pthread = cond_queue_deq(*cond)) != NULL) { 397 PTHREAD_NEW_STATE(pthread, PS_RUNNING); 398 _thread_critical_exit(pthread); 399 } 400 } while (broadcast && pthread != NULL); | 352 if ((pthread = cond_queue_deq(*cond)) != NULL) { 353 PTHREAD_WAKE(pthread); 354 PTHREAD_UNLOCK(pthread); 355 } 356 } while (broadcast && pthread != NULL); |
401 | 357 |
402 break; 403 404 /* Trap invalid condition variable types: */ 405 default: 406 rval = EINVAL; 407 break; 408 } 409 | |
410 COND_UNLOCK(*cond); | 358 COND_UNLOCK(*cond); |
411 412 | |
413 return (rval); 414} 415 416void 417_cond_wait_backout(pthread_t pthread) 418{ 419 pthread_cond_t cond; 420 --- 17 unchanged lines hidden (view full) --- 438 * descending priority order. 439 */ 440static pthread_t 441cond_queue_deq(pthread_cond_t cond) 442{ 443 pthread_t pthread; 444 445 while ((pthread = TAILQ_FIRST(&cond->c_queue)) != NULL) { | 359 return (rval); 360} 361 362void 363_cond_wait_backout(pthread_t pthread) 364{ 365 pthread_cond_t cond; 366 --- 17 unchanged lines hidden (view full) --- 384 * descending priority order. 385 */ 386static pthread_t 387cond_queue_deq(pthread_cond_t cond) 388{ 389 pthread_t pthread; 390 391 while ((pthread = TAILQ_FIRST(&cond->c_queue)) != NULL) { |
446 _thread_critical_enter(pthread); 447 TAILQ_REMOVE(&cond->c_queue, pthread, sqe); | 392 PTHREAD_LOCK(pthread); |
448 cond_queue_remove(cond, pthread); | 393 cond_queue_remove(cond, pthread); |
449 if ((pthread->cancelflags & PTHREAD_CANCELLING) == 0 && 450 pthread->state == PS_COND_WAIT) 451 /* 452 * Only exit the loop when we find a thread 453 * that hasn't timed out or been canceled; 454 * those threads are already running and don't 455 * need their run state changed. 456 */ | 394 395 /* 396 * Only exit the loop when we find a thread 397 * that hasn't been canceled. 398 */ 399 if (pthread->cancellation == CS_NULL) |
457 break; 458 else | 400 break; 401 else |
459 _thread_critical_exit(pthread); | 402 PTHREAD_UNLOCK(pthread); |
460 } 461 462 return(pthread); 463} 464 465/* 466 * Remove a waiting thread from a condition queue in descending priority 467 * order. --- 66 unchanged lines hidden --- | 403 } 404 405 return(pthread); 406} 407 408/* 409 * Remove a waiting thread from a condition queue in descending priority 410 * order. --- 66 unchanged lines hidden --- |