| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 */ |
| OLD | NEW |