Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(388)

Side by Side Diff: nspr/pr/src/pthreads/ptsynch.c

Issue 200653003: Update to NSPR 4.10.4. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « nspr/pr/src/pthreads/ptio.c ('k') | nspr/pr/src/pthreads/ptthread.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public 2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 5
6 /* 6 /*
7 ** File: ptsynch.c 7 ** File: ptsynch.c
8 ** Descritpion: Implemenation for thread synchronization using pthreads 8 ** Descritpion: Implemenation for thread synchronization using pthreads
9 ** Exports: prlock.h, prcvar.h, prmon.h, prcmon.h 9 ** Exports: prlock.h, prcvar.h, prmon.h, prcmon.h
10 */ 10 */
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 PR_ASSERT(0 == rv); 162 PR_ASSERT(0 == rv);
163 #if defined(DEBUG) 163 #if defined(DEBUG)
164 memset(lock, 0xaf, sizeof(PRLock)); 164 memset(lock, 0xaf, sizeof(PRLock));
165 pt_debug.locks_destroyed += 1; 165 pt_debug.locks_destroyed += 1;
166 #endif 166 #endif
167 PR_Free(lock); 167 PR_Free(lock);
168 } /* PR_DestroyLock */ 168 } /* PR_DestroyLock */
169 169
170 PR_IMPLEMENT(void) PR_Lock(PRLock *lock) 170 PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
171 { 171 {
172 /* Nb: PR_Lock must not call PR_GetCurrentThread to access the |id| or
173 * |tid| field of the current thread's PRThread structure because
174 * _pt_root calls PR_Lock before setting thred->id and thred->tid. */
172 PRIntn rv; 175 PRIntn rv;
173 PR_ASSERT(lock != NULL); 176 PR_ASSERT(lock != NULL);
174 rv = pthread_mutex_lock(&lock->mutex); 177 rv = pthread_mutex_lock(&lock->mutex);
175 PR_ASSERT(0 == rv); 178 PR_ASSERT(0 == rv);
176 PR_ASSERT(0 == lock->notified.length); 179 PR_ASSERT(0 == lock->notified.length);
177 PR_ASSERT(NULL == lock->notified.link); 180 PR_ASSERT(NULL == lock->notified.link);
178 PR_ASSERT(PR_FALSE == lock->locked); 181 PR_ASSERT(PR_FALSE == lock->locked);
179 /* Nb: the order of the next two statements is not critical to 182 /* Nb: the order of the next two statements is not critical to
180 * the correctness of PR_AssertCurrentThreadOwnsLock(), but 183 * the correctness of PR_AssertCurrentThreadOwnsLock(), but
181 * this particular order makes the assertion more likely to 184 * this particular order makes the assertion more likely to
182 * catch errors. */ 185 * catch errors. */
183 lock->owner = pthread_self(); 186 lock->owner = pthread_self();
184 lock->locked = PR_TRUE; 187 lock->locked = PR_TRUE;
185 #if defined(DEBUG) 188 #if defined(DEBUG)
186 pt_debug.locks_acquired += 1; 189 pt_debug.locks_acquired += 1;
187 #endif 190 #endif
188 } /* PR_Lock */ 191 } /* PR_Lock */
189 192
190 PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock) 193 PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock)
191 { 194 {
195 pthread_t self = pthread_self();
192 PRIntn rv; 196 PRIntn rv;
193 197
194 PR_ASSERT(lock != NULL); 198 PR_ASSERT(lock != NULL);
195 PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(lock->mutex)); 199 PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(lock->mutex));
196 PR_ASSERT(PR_TRUE == lock->locked); 200 PR_ASSERT(PR_TRUE == lock->locked);
197 PR_ASSERT(pthread_equal(lock->owner, pthread_self())); 201 PR_ASSERT(pthread_equal(lock->owner, self));
198 202
199 if (!lock->locked || !pthread_equal(lock->owner, pthread_self())) 203 if (!lock->locked || !pthread_equal(lock->owner, self))
200 return PR_FAILURE; 204 return PR_FAILURE;
201 205
202 lock->locked = PR_FALSE; 206 lock->locked = PR_FALSE;
203 if (0 == lock->notified.length) /* shortcut */ 207 if (0 == lock->notified.length) /* shortcut */
204 { 208 {
205 rv = pthread_mutex_unlock(&lock->mutex); 209 rv = pthread_mutex_unlock(&lock->mutex);
206 PR_ASSERT(0 == rv); 210 PR_ASSERT(0 == rv);
207 } 211 }
208 else pt_PostNotifies(lock, PR_TRUE); 212 else pt_PostNotifies(lock, PR_TRUE);
209 213
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 while (1) 290 while (1)
287 { 291 {
288 for (index = 0; index < notified->length; ++index) 292 for (index = 0; index < notified->length; ++index)
289 { 293 {
290 if (notified->cv[index].cv == cvar) 294 if (notified->cv[index].cv == cvar)
291 { 295 {
292 if (broadcast) 296 if (broadcast)
293 notified->cv[index].times = -1; 297 notified->cv[index].times = -1;
294 else if (-1 != notified->cv[index].times) 298 else if (-1 != notified->cv[index].times)
295 notified->cv[index].times += 1; 299 notified->cv[index].times += 1;
296 goto finished; /* we're finished */ 300 return; /* we're finished */
297 } 301 }
298 } 302 }
299 /* if not full, enter new CV in this array */ 303 /* if not full, enter new CV in this array */
300 if (notified->length < PT_CV_NOTIFIED_LENGTH) break; 304 if (notified->length < PT_CV_NOTIFIED_LENGTH) break;
301 305
302 /* if there's no link, create an empty array and link it */ 306 /* if there's no link, create an empty array and link it */
303 if (NULL == notified->link) 307 if (NULL == notified->link)
304 notified->link = PR_NEWZAP(_PT_Notified); 308 notified->link = PR_NEWZAP(_PT_Notified);
305 notified = notified->link; 309 notified = notified->link;
306 } 310 }
307 311
308 /* A brand new entry in the array */ 312 /* A brand new entry in the array */
309 (void)PR_ATOMIC_INCREMENT(&cvar->notify_pending); 313 (void)PR_ATOMIC_INCREMENT(&cvar->notify_pending);
310 notified->cv[index].times = (broadcast) ? -1 : 1; 314 notified->cv[index].times = (broadcast) ? -1 : 1;
311 notified->cv[index].cv = cvar; 315 notified->cv[index].cv = cvar;
312 notified->length += 1; 316 notified->length += 1;
313
314 finished:
315 PR_ASSERT(PR_TRUE == cvar->lock->locked);
316 PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
317 } /* pt_PostNotifyToCvar */ 317 } /* pt_PostNotifyToCvar */
318 318
319 PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock) 319 PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock)
320 { 320 {
321 PRCondVar *cv = PR_NEW(PRCondVar); 321 PRCondVar *cv = PR_NEW(PRCondVar);
322 PR_ASSERT(lock != NULL); 322 PR_ASSERT(lock != NULL);
323 if (cv != NULL) 323 if (cv != NULL)
324 { 324 {
325 int rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr); 325 int rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr);
326 PR_ASSERT(0 == rv); 326 PR_ASSERT(0 == rv);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 pt_PostNotifyToCvar(cvar, PR_TRUE); 420 pt_PostNotifyToCvar(cvar, PR_TRUE);
421 return PR_SUCCESS; 421 return PR_SUCCESS;
422 } /* PR_NotifyAllCondVar */ 422 } /* PR_NotifyAllCondVar */
423 423
424 /**************************************************************/ 424 /**************************************************************/
425 /**************************************************************/ 425 /**************************************************************/
426 /***************************MONITORS***************************/ 426 /***************************MONITORS***************************/
427 /**************************************************************/ 427 /**************************************************************/
428 /**************************************************************/ 428 /**************************************************************/
429 429
430 /*
431 * Notifies just get posted to the monitor. The actual notification is done
432 * when the monitor is fully exited so that MP systems don't contend for a
433 * monitor that they can't enter.
434 */
435 static void pt_PostNotifyToMonitor(PRMonitor *mon, PRBool broadcast)
436 {
437 PR_ASSERT(NULL != mon);
438 PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mon);
439
440 /* mon->notifyTimes is protected by the monitor, so we don't need to
441 * acquire mon->lock.
442 */
443 if (broadcast)
444 mon->notifyTimes = -1;
445 else if (-1 != mon->notifyTimes)
446 mon->notifyTimes += 1;
447 } /* pt_PostNotifyToMonitor */
448
449 static void pt_PostNotifiesFromMonitor(pthread_cond_t *cv, PRIntn times)
450 {
451 PRIntn rv;
452
453 /*
454 * Time to actually notify any waits that were affected while the monitor
455 * was entered.
456 */
457 PR_ASSERT(NULL != cv);
458 PR_ASSERT(0 != times);
459 if (-1 == times)
460 {
461 rv = pthread_cond_broadcast(cv);
462 PR_ASSERT(0 == rv);
463 }
464 else
465 {
466 while (times-- > 0)
467 {
468 rv = pthread_cond_signal(cv);
469 PR_ASSERT(0 == rv);
470 }
471 }
472 } /* pt_PostNotifiesFromMonitor */
473
430 PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void) 474 PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void)
431 { 475 {
432 PRMonitor *mon; 476 PRMonitor *mon;
433 PRCondVar *cvar;
434 int rv; 477 int rv;
435 478
436 if (!_pr_initialized) _PR_ImplicitInitialization(); 479 if (!_pr_initialized) _PR_ImplicitInitialization();
437 480
438 cvar = PR_NEWZAP(PRCondVar); 481 mon = PR_NEWZAP(PRMonitor);
439 if (NULL == cvar) 482 if (mon == NULL)
440 { 483 {
441 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 484 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
442 return NULL; 485 return NULL;
443 } 486 }
444 mon = PR_NEWZAP(PRMonitor);
445 if (mon == NULL)
446 {
447 PR_Free(cvar);
448 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
449 return NULL;
450 }
451 487
452 rv = _PT_PTHREAD_MUTEX_INIT(mon->lock.mutex, _pt_mattr); 488 rv = _PT_PTHREAD_MUTEX_INIT(mon->lock, _pt_mattr);
453 PR_ASSERT(0 == rv); 489 PR_ASSERT(0 == rv);
454 if (0 != rv) 490 if (0 != rv)
455 { 491 goto error1;
456 PR_Free(mon);
457 PR_Free(cvar);
458 PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
459 return NULL;
460 }
461 492
462 _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner); 493 _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
463 494
464 mon->cvar = cvar; 495 rv = _PT_PTHREAD_COND_INIT(mon->entryCV, _pt_cvar_attr);
465 rv = _PT_PTHREAD_COND_INIT(mon->cvar->cv, _pt_cvar_attr);
466 PR_ASSERT(0 == rv); 496 PR_ASSERT(0 == rv);
497 if (0 != rv)
498 goto error2;
499
500 rv = _PT_PTHREAD_COND_INIT(mon->waitCV, _pt_cvar_attr);
501 PR_ASSERT(0 == rv);
502 if (0 != rv)
503 goto error3;
504
505 mon->notifyTimes = 0;
467 mon->entryCount = 0; 506 mon->entryCount = 0;
468 mon->cvar->lock = &mon->lock; 507 mon->refCount = 1;
469 if (0 != rv) 508 mon->name = NULL;
470 {
471 pthread_mutex_destroy(&mon->lock.mutex);
472 PR_Free(mon);
473 PR_Free(cvar);
474 PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
475 return NULL;
476 }
477 return mon; 509 return mon;
510
511 error3:
512 pthread_cond_destroy(&mon->entryCV);
513 error2:
514 pthread_mutex_destroy(&mon->lock);
515 error1:
516 PR_Free(mon);
517 PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
518 return NULL;
478 } /* PR_NewMonitor */ 519 } /* PR_NewMonitor */
479 520
480 PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name) 521 PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
481 { 522 {
482 PRMonitor* mon = PR_NewMonitor(); 523 PRMonitor* mon = PR_NewMonitor();
483 if (mon) 524 if (mon)
484 mon->name = name; 525 mon->name = name;
485 return mon; 526 return mon;
486 } 527 }
487 528
488 PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon) 529 PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon)
489 { 530 {
490 int rv; 531 int rv;
532
491 PR_ASSERT(mon != NULL); 533 PR_ASSERT(mon != NULL);
492 PR_DestroyCondVar(mon->cvar); 534 if (PR_ATOMIC_DECREMENT(&mon->refCount) == 0)
493 rv = pthread_mutex_destroy(&mon->lock.mutex); PR_ASSERT(0 == rv); 535 {
536 rv = pthread_cond_destroy(&mon->waitCV); PR_ASSERT(0 == rv);
537 rv = pthread_cond_destroy(&mon->entryCV); PR_ASSERT(0 == rv);
538 rv = pthread_mutex_destroy(&mon->lock); PR_ASSERT(0 == rv);
494 #if defined(DEBUG) 539 #if defined(DEBUG)
495 memset(mon, 0xaf, sizeof(PRMonitor)); 540 memset(mon, 0xaf, sizeof(PRMonitor));
496 #endif 541 #endif
497 PR_Free(mon); 542 PR_Free(mon);
543 }
498 } /* PR_DestroyMonitor */ 544 } /* PR_DestroyMonitor */
499 545
500
501 /* The GC uses this; it is quite arguably a bad interface. I'm just 546 /* The GC uses this; it is quite arguably a bad interface. I'm just
502 * duplicating it for now - XXXMB 547 * duplicating it for now - XXXMB
503 */ 548 */
504 PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon) 549 PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon)
505 { 550 {
506 pthread_t self = pthread_self(); 551 pthread_t self = pthread_self();
552 PRIntn rv;
553 PRIntn count = 0;
554
555 rv = pthread_mutex_lock(&mon->lock);
556 PR_ASSERT(0 == rv);
507 if (pthread_equal(mon->owner, self)) 557 if (pthread_equal(mon->owner, self))
508 return mon->entryCount; 558 count = mon->entryCount;
509 return 0; 559 rv = pthread_mutex_unlock(&mon->lock);
560 PR_ASSERT(0 == rv);
561 return count;
510 } 562 }
511 563
512 PR_IMPLEMENT(void) PR_AssertCurrentThreadInMonitor(PRMonitor *mon) 564 PR_IMPLEMENT(void) PR_AssertCurrentThreadInMonitor(PRMonitor *mon)
513 { 565 {
514 PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(&mon->lock); 566 #if defined(DEBUG) || defined(FORCE_PR_ASSERT)
567 PRIntn rv;
568
569 rv = pthread_mutex_lock(&mon->lock);
570 PR_ASSERT(0 == rv);
571 PR_ASSERT(mon->entryCount != 0 &&
572 pthread_equal(mon->owner, pthread_self()));
573 rv = pthread_mutex_unlock(&mon->lock);
574 PR_ASSERT(0 == rv);
575 #endif
515 } 576 }
516 577
517 PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon) 578 PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon)
518 { 579 {
519 pthread_t self = pthread_self(); 580 pthread_t self = pthread_self();
581 PRIntn rv;
520 582
521 PR_ASSERT(mon != NULL); 583 PR_ASSERT(mon != NULL);
522 /* 584 rv = pthread_mutex_lock(&mon->lock);
523 * This is safe only if mon->owner (a pthread_t) can be 585 PR_ASSERT(0 == rv);
524 * read in one instruction. Perhaps mon->owner should be 586 if (mon->entryCount != 0)
525 * a "PRThread *"?
526 */
527 if (!pthread_equal(mon->owner, self))
528 { 587 {
529 PR_Lock(&mon->lock); 588 if (pthread_equal(mon->owner, self))
530 /* and now I have the lock */ 589 goto done;
531 PR_ASSERT(0 == mon->entryCount); 590 while (mon->entryCount != 0)
532 PR_ASSERT(_PT_PTHREAD_THR_HANDLE_IS_INVALID(mon->owner)); 591 {
533 _PT_PTHREAD_COPY_THR_HANDLE(self, mon->owner); 592 rv = pthread_cond_wait(&mon->entryCV, &mon->lock);
593 PR_ASSERT(0 == rv);
594 }
534 } 595 }
596 /* and now I have the monitor */
597 PR_ASSERT(0 == mon->notifyTimes);
598 PR_ASSERT(_PT_PTHREAD_THR_HANDLE_IS_INVALID(mon->owner));
599 _PT_PTHREAD_COPY_THR_HANDLE(self, mon->owner);
600
601 done:
535 mon->entryCount += 1; 602 mon->entryCount += 1;
603 rv = pthread_mutex_unlock(&mon->lock);
604 PR_ASSERT(0 == rv);
536 } /* PR_EnterMonitor */ 605 } /* PR_EnterMonitor */
537 606
538 PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon) 607 PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon)
539 { 608 {
540 pthread_t self = pthread_self(); 609 pthread_t self = pthread_self();
610 PRIntn rv;
611 PRBool notifyEntryWaiter = PR_FALSE;
612 PRIntn notifyTimes = 0;
541 613
542 PR_ASSERT(mon != NULL); 614 PR_ASSERT(mon != NULL);
543 /* The lock better be that - locked */ 615 rv = pthread_mutex_lock(&mon->lock);
544 PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex)); 616 PR_ASSERT(0 == rv);
545 /* we'd better be the owner */ 617 /* the entries should be > 0 and we'd better be the owner */
618 PR_ASSERT(mon->entryCount > 0);
546 PR_ASSERT(pthread_equal(mon->owner, self)); 619 PR_ASSERT(pthread_equal(mon->owner, self));
547 if (!pthread_equal(mon->owner, self)) 620 if (mon->entryCount == 0 || !pthread_equal(mon->owner, self))
621 {
622 rv = pthread_mutex_unlock(&mon->lock);
623 PR_ASSERT(0 == rv);
548 return PR_FAILURE; 624 return PR_FAILURE;
625 }
549 626
550 /* if it's locked and we have it, then the entries should be > 0 */
551 PR_ASSERT(mon->entryCount > 0);
552 mon->entryCount -= 1; /* reduce by one */ 627 mon->entryCount -= 1; /* reduce by one */
553 if (mon->entryCount == 0) 628 if (mon->entryCount == 0)
554 { 629 {
555 /* and if it transitioned to zero - unlock */ 630 /* and if it transitioned to zero - notify an entry waiter */
556 _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner); /* make the owner unknow n */ 631 /* make the owner unknown */
557 PR_Unlock(&mon->lock); 632 _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
633 notifyEntryWaiter = PR_TRUE;
634 notifyTimes = mon->notifyTimes;
635 mon->notifyTimes = 0;
636 /* We will access the members of 'mon' after unlocking mon->lock.
637 * Add a reference. */
638 PR_ATOMIC_INCREMENT(&mon->refCount);
639 }
640 rv = pthread_mutex_unlock(&mon->lock);
641 PR_ASSERT(0 == rv);
642 if (notifyEntryWaiter)
643 {
644 if (notifyTimes)
645 pt_PostNotifiesFromMonitor(&mon->waitCV, notifyTimes);
646 rv = pthread_cond_signal(&mon->entryCV);
647 PR_ASSERT(0 == rv);
648 /* We are done accessing the members of 'mon'. Release the
649 * reference. */
650 PR_DestroyMonitor(mon);
558 } 651 }
559 return PR_SUCCESS; 652 return PR_SUCCESS;
560 } /* PR_ExitMonitor */ 653 } /* PR_ExitMonitor */
561 654
562 PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout) 655 PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout)
563 { 656 {
564 PRStatus rv; 657 PRStatus rv;
565 PRInt16 saved_entries; 658 PRUint32 saved_entries;
566 pthread_t saved_owner; 659 pthread_t saved_owner;
567 660
568 PR_ASSERT(mon != NULL); 661 PR_ASSERT(mon != NULL);
569 /* we'd better be locked */ 662 rv = pthread_mutex_lock(&mon->lock);
570 PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex)); 663 PR_ASSERT(0 == rv);
571 /* and the entries better be positive */ 664 /* the entries better be positive */
572 PR_ASSERT(mon->entryCount > 0); 665 PR_ASSERT(mon->entryCount > 0);
573 /* and it better be by us */ 666 /* and it better be owned by us */
574 PR_ASSERT(pthread_equal(mon->owner, pthread_self())); 667 PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
575 668
576 /* tuck these away 'till later */ 669 /* tuck these away 'till later */
577 saved_entries = mon->entryCount; 670 saved_entries = mon->entryCount;
578 mon->entryCount = 0; 671 mon->entryCount = 0;
579 _PT_PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner); 672 _PT_PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner);
580 _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner); 673 _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
581 674 /*
582 rv = PR_WaitCondVar(mon->cvar, timeout); 675 * If we have pending notifies, post them now.
676 *
677 * This is not optimal. We're going to post these notifies
678 * while we're holding the lock. That means on MP systems
679 * that they are going to collide for the lock that we will
680 * hold until we actually wait.
681 */
682 if (0 != mon->notifyTimes)
683 {
684 pt_PostNotifiesFromMonitor(&mon->waitCV, mon->notifyTimes);
685 mon->notifyTimes = 0;
686 }
687 rv = pthread_cond_signal(&mon->entryCV);
688 PR_ASSERT(0 == rv);
583 689
584 /* reinstate the intresting information */ 690 if (timeout == PR_INTERVAL_NO_TIMEOUT)
691 rv = pthread_cond_wait(&mon->waitCV, &mon->lock);
692 else
693 rv = pt_TimedWait(&mon->waitCV, &mon->lock, timeout);
694 PR_ASSERT(0 == rv);
695
696 while (mon->entryCount != 0)
697 {
698 rv = pthread_cond_wait(&mon->entryCV, &mon->lock);
699 PR_ASSERT(0 == rv);
700 }
701 PR_ASSERT(0 == mon->notifyTimes);
702 /* reinstate the interesting information */
585 mon->entryCount = saved_entries; 703 mon->entryCount = saved_entries;
586 _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner); 704 _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner);
587 705
706 rv = pthread_mutex_unlock(&mon->lock);
707 PR_ASSERT(0 == rv);
588 return rv; 708 return rv;
589 } /* PR_Wait */ 709 } /* PR_Wait */
590 710
591 PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon) 711 PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon)
592 { 712 {
593 PR_ASSERT(NULL != mon); 713 pt_PostNotifyToMonitor(mon, PR_FALSE);
594 /* we'd better be locked */
595 PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
596 /* and the entries better be positive */
597 PR_ASSERT(mon->entryCount > 0);
598 /* and it better be by us */
599 PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
600
601 pt_PostNotifyToCvar(mon->cvar, PR_FALSE);
602
603 return PR_SUCCESS; 714 return PR_SUCCESS;
604 } /* PR_Notify */ 715 } /* PR_Notify */
605 716
606 PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon) 717 PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon)
607 { 718 {
608 PR_ASSERT(mon != NULL); 719 pt_PostNotifyToMonitor(mon, PR_TRUE);
609 /* we'd better be locked */
610 PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
611 /* and the entries better be positive */
612 PR_ASSERT(mon->entryCount > 0);
613 /* and it better be by us */
614 PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
615
616 pt_PostNotifyToCvar(mon->cvar, PR_TRUE);
617
618 return PR_SUCCESS; 720 return PR_SUCCESS;
619 } /* PR_NotifyAll */ 721 } /* PR_NotifyAll */
620 722
621 /**************************************************************/ 723 /**************************************************************/
622 /**************************************************************/ 724 /**************************************************************/
623 /**************************SEMAPHORES**************************/ 725 /**************************SEMAPHORES**************************/
624 /**************************************************************/ 726 /**************************************************************/
625 /**************************************************************/ 727 /**************************************************************/
626 PR_IMPLEMENT(void) PR_PostSem(PRSemaphore *semaphore) 728 PR_IMPLEMENT(void) PR_PostSem(PRSemaphore *semaphore)
627 { 729 {
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after
1129 int rv; 1231 int rv;
1130 PR_ASSERT(cvar != NULL); 1232 PR_ASSERT(cvar != NULL);
1131 rv = pthread_cond_broadcast(&cvar->cv); 1233 rv = pthread_cond_broadcast(&cvar->cv);
1132 PR_ASSERT(0 == rv); 1234 PR_ASSERT(0 == rv);
1133 return PR_SUCCESS; 1235 return PR_SUCCESS;
1134 } /* PRP_NakedBroadcast */ 1236 } /* PRP_NakedBroadcast */
1135 1237
1136 #endif /* defined(_PR_PTHREADS) */ 1238 #endif /* defined(_PR_PTHREADS) */
1137 1239
1138 /* ptsynch.c */ 1240 /* ptsynch.c */
OLDNEW
« no previous file with comments | « nspr/pr/src/pthreads/ptio.c ('k') | nspr/pr/src/pthreads/ptthread.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698