nsresult
Monitor::Wait(PRIntervalTime interval)
{
    AssertCurrentThreadIn();

    // save monitor state and reset it to empty
    PRInt32 savedEntryCount = mEntryCount;
    CallStack savedAcquisitionContext = GetAcquisitionContext();
    BlockingResourceBase* savedChainPrev = mChainPrev;
    mEntryCount = 0;
    SetAcquisitionContext(CallStack::kNone);
    mChainPrev = 0;

    // give up the monitor until we're back from Wait()
    nsresult rv =
        PR_Wait(mMonitor, interval) == PR_SUCCESS ?
            NS_OK : NS_ERROR_FAILURE;
    
    // restore saved state
    mEntryCount = savedEntryCount;
    SetAcquisitionContext(savedAcquisitionContext);
    mChainPrev = savedChainPrev;

    return rv;
}
Ejemplo n.º 2
0
nsresult
ReentrantMonitor::Wait(PRIntervalTime aInterval)
{
  AssertCurrentThreadIn();

  // save monitor state and reset it to empty
  int32_t savedEntryCount = mEntryCount;
  CallStack savedAcquisitionContext = GetAcquisitionContext();
  BlockingResourceBase* savedChainPrev = mChainPrev;
  mEntryCount = 0;
  SetAcquisitionContext(CallStack::kNone);
  mChainPrev = 0;

  nsresult rv;
#ifdef MOZILLA_INTERNAL_API
  {
    GeckoProfilerSleepRAII profiler_sleep;
#endif //MOZILLA_INTERNAL_API

    // give up the monitor until we're back from Wait()
    rv = PR_Wait(mReentrantMonitor, aInterval) == PR_SUCCESS ? NS_OK :
                                                               NS_ERROR_FAILURE;

#ifdef MOZILLA_INTERNAL_API
  }
#endif //MOZILLA_INTERNAL_API

  // restore saved state
  mEntryCount = savedEntryCount;
  SetAcquisitionContext(savedAcquisitionContext);
  mChainPrev = savedChainPrev;

  return rv;
}
//
// Debug implementation of Monitor
void
Monitor::Enter()
{
    BlockingResourceBase* chainFront = ResourceChainFront();

    // the code below implements monitor reentrancy semantics

    if (this == chainFront) {
        // immediately re-entered the monitor: acceptable
        PR_EnterMonitor(mMonitor);
        ++mEntryCount;
        return;
    }

    CallStack callContext = CallStack();
    
    // this is sort of a hack around not recording the thread that
    // owns this monitor
    if (chainFront) {
        for (BlockingResourceBase* br = ResourceChainPrev(chainFront);
             br;
             br = ResourceChainPrev(br)) {
            if (br == this) {
                NS_WARNING(
                    "Re-entering Monitor after acquiring other resources.\n"
                    "At calling context\n");
                GetAcquisitionContext().Print(stderr);

                // show the caller why this is potentially bad
                CheckAcquire(callContext);

                PR_EnterMonitor(mMonitor);
                ++mEntryCount;
                return;
            }
        }
    }

    CheckAcquire(callContext);
    PR_EnterMonitor(mMonitor);
    NS_ASSERTION(0 == mEntryCount, "Monitor isn't free!");
    Acquire(callContext);       // protected by mMonitor
    mEntryCount = 1;
}