VirtualBox

Changeset 25515 in vbox


Ignore:
Timestamp:
Dec 20, 2009 2:44:16 PM (15 years ago)
Author:
vboxsync
Message:

semrw-generic.cpp: Fixed timeout handling.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/generic/semrw-generic.cpp

    r25513 r25515  
    214214    unsigned    cMilliesInitial = cMillies;
    215215    uint64_t    tsStart = 0;
    216     if (cMillies != RT_INDEFINITE_WAIT)
     216    if (cMillies != RT_INDEFINITE_WAIT && cMillies != 0)
    217217        tsStart = RTTimeNanoTS();
    218218
     
    227227    }
    228228
     229    /*
     230     * Check if the state of affairs allows read access.
     231     * Do not block further readers if there is a writer waiting, as
     232     * that will break/deadlock reader recursion.
     233     */
     234    if (!pThis->cWrites
     235        /** @todo && (   pThis->cReads
     236         *            || !pThis->cWritesWaiting) ?? - making sure not to race waiting
     237         *        writers.  */
     238       )
     239    {
     240        pThis->cReads++;
     241
     242        RTCritSectLeave(&pThis->CritSect);
     243        return VINF_SUCCESS;
     244    }
     245
     246    if (pThis->Writer == Self)
     247    {
     248        pThis->cWriterReads++;
     249
     250        RTCritSectLeave(&pThis->CritSect);
     251        return VINF_SUCCESS;
     252    }
     253
     254    RTCritSectLeave(&pThis->CritSect);
     255
     256    /*
     257     * Wait till it's ready for reading.
     258     */
     259    if (cMillies == 0)
     260        return VERR_TIMEOUT;
     261
    229262    for (;;)
    230263    {
     264        if (cMillies != RT_INDEFINITE_WAIT)
     265        {
     266            int64_t tsDelta = RTTimeNanoTS() - tsStart;
     267            if (tsDelta >= 1000000)
     268            {
     269                tsDelta /= 1000000;
     270                if ((uint64_t)tsDelta < cMilliesInitial)
     271                    cMilliesInitial = (unsigned)tsDelta;
     272                else
     273                    cMilliesInitial = 1;
     274            }
     275        }
     276        int rcWait = rc = RTSemEventMultiWait(pThis->ReadEvent, cMillies);
     277        if (RT_FAILURE(rc) && rc != VERR_TIMEOUT) /* handle timeout below */
     278        {
     279            AssertMsgRC(rc, ("RTSemEventMultiWait failed on rwsem %p, rc=%Rrc\n", RWSem, rc));
     280            break;
     281        }
     282
     283        if (pThis->u32Magic != RTSEMRW_MAGIC)
     284        {
     285            rc = VERR_SEM_DESTROYED;
     286            break;
     287        }
     288
    231289        /*
    232          * Check if the state of affairs allows read access.
    233          * Do not block further readers if there is a writer waiting, as
    234          * that will break/deadlock reader recursion.
     290         * Re-take critsect and repeate the exact same checks as we did before
     291         * the loop.
    235292         */
     293        rc = RTCritSectEnter(&pThis->CritSect);
     294        if (RT_FAILURE(rc))
     295        {
     296            AssertMsgFailed(("RTCritSectEnter failed on rwsem %p, rc=%Rrc\n", RWSem, rc));
     297            break;
     298        }
     299
    236300        if (!pThis->cWrites
    237301            /** @todo && (   pThis->cReads
     
    257321
    258322        /*
    259          * Wait till it's ready for reading.
     323         * Quit if the wait already timed out.
    260324         */
    261         if (cMillies != RT_INDEFINITE_WAIT)
    262         {
    263             int64_t tsDelta = RTTimeNanoTS() - tsStart;
    264             if (tsDelta >= 1000000)
    265             {
    266                 cMillies = cMilliesInitial - (unsigned)(tsDelta / 1000000);
    267                 if (cMillies > cMilliesInitial)
    268                     cMillies = cMilliesInitial ? 1 : 0;
    269             }
    270         }
    271         rc = RTSemEventMultiWait(pThis->ReadEvent, cMillies);
    272         if (RT_FAILURE(rc) && rc != VERR_TIMEOUT)
    273         {
    274             AssertMsgRC(rc, ("RTSemEventMultiWait failed on rwsem %p, rc=%Rrc\n", RWSem, rc));
    275             break;
    276         }
    277 
    278         if (pThis->u32Magic != RTSEMRW_MAGIC)
    279         {
    280             rc = VERR_SEM_DESTROYED;
    281             break;
    282         }
    283 
    284         /*
    285          * Re-take critsect.
    286          */
    287         rc = RTCritSectEnter(&pThis->CritSect);
    288         if (RT_FAILURE(rc))
    289         {
    290             AssertMsgFailed(("RTCritSectEnter failed on rwsem %p, rc=%Rrc\n", RWSem, rc));
     325        if (rcWait == VERR_TIMEOUT)
     326        {
     327            rc = VERR_TIMEOUT;
    291328            break;
    292329        }
     
    379416
    380417    /*
     418     * Check if the state of affairs allows write access.
     419     */
     420    if (!pThis->cReads && (!pThis->cWrites || pThis->Writer == Self))
     421    {
     422        /*
     423         * Reset the reader event semaphore if necessary.
     424         */
     425        if (pThis->fNeedResetReadEvent)
     426        {
     427            pThis->fNeedResetReadEvent = false;
     428            rc = RTSemEventMultiReset(pThis->ReadEvent);
     429            AssertMsgRC(rc, ("Failed to reset readers, rwsem %p, rc=%Rrc.\n", RWSem, rc));
     430        }
     431
     432        pThis->cWrites++;
     433        pThis->Writer = Self;
     434
     435        RTCritSectLeave(&pThis->CritSect);
     436        return VINF_SUCCESS;
     437    }
     438
     439    /*
    381440     * Signal writer presence.
    382441     */
    383     pThis->cWritesWaiting++;
     442    if (cMillies != 0)
     443        pThis->cWritesWaiting++;
     444
     445    RTCritSectLeave(&pThis->CritSect);
     446
     447    /*
     448     * Wait till it's ready for writing.
     449     */
     450    if (cMillies == 0)
     451        return VERR_TIMEOUT;
    384452
    385453    for (;;)
    386454    {
     455        if (cMillies != RT_INDEFINITE_WAIT)
     456        {
     457            int64_t tsDelta = RTTimeNanoTS() - tsStart;
     458            if (tsDelta >= 1000000)
     459            {
     460                tsDelta /= 1000000;
     461                if ((uint64_t)tsDelta < cMilliesInitial)
     462                    cMilliesInitial = (unsigned)tsDelta;
     463                else
     464                    cMilliesInitial = 1;
     465            }
     466        }
     467        int rcWait = rc = RTSemEventWait(pThis->WriteEvent, cMillies);
     468        if (RT_UNLIKELY(RT_FAILURE_NP(rc) && rc != VERR_TIMEOUT)) /* timeouts are handled below */
     469        {
     470            AssertMsgRC(rc, ("RTSemEventWait failed on rwsem %p, rc=%Rrc\n", RWSem, rc));
     471            break;
     472        }
     473
     474        if (RT_UNLIKELY(pThis->u32Magic != RTSEMRW_MAGIC))
     475        {
     476            rc = VERR_SEM_DESTROYED;
     477            break;
     478        }
     479
    387480        /*
    388          * Check if the state of affairs allows write access.
     481         * Re-take critsect and repeate the check we did prior to this loop.
    389482         */
     483        rc = RTCritSectEnter(&pThis->CritSect);
     484        if (RT_FAILURE(rc))
     485        {
     486            AssertMsgFailed(("RTCritSectEnter failed on rwsem %p, rc=%Rrc\n", RWSem, rc));
     487            break;
     488        }
     489
    390490        if (!pThis->cReads && (!pThis->cWrites || pThis->Writer == Self))
    391491        {
     
    402502            pThis->cWrites++;
    403503            pThis->Writer = Self;
    404             /* We're not waiting, so decrease counter. */
    405504            pThis->cWritesWaiting--;
     505
    406506            RTCritSectLeave(&pThis->CritSect);
    407507            return VINF_SUCCESS;
     
    411511
    412512        /*
    413          * Wait till it's ready for writing.
     513         * Quit if the wait already timed out.
    414514         */
    415         if (cMillies != RT_INDEFINITE_WAIT && cMillies != 0)
    416         {
    417             int64_t tsDelta = RTTimeNanoTS() - tsStart;
    418             if (tsDelta >= 1000000)
    419             {
    420                 cMillies = cMilliesInitial - (unsigned)(tsDelta / 1000000);
    421                 if (cMillies > cMilliesInitial)
    422                     cMillies = cMilliesInitial ? 1 : 0;
    423             }
    424         }
    425         rc = RTSemEventWait(pThis->WriteEvent, cMillies);
    426         if (RT_UNLIKELY(RT_FAILURE_NP(rc) && rc != VERR_TIMEOUT))
    427         {
    428             AssertMsgRC(rc, ("RTSemEventWait failed on rwsem %p, rc=%Rrc\n", RWSem, rc));
    429             break;
    430         }
    431 
    432         if (RT_UNLIKELY(pThis->u32Magic != RTSEMRW_MAGIC))
    433         {
    434             rc = VERR_SEM_DESTROYED;
    435             break;
    436         }
    437 
    438         /*
    439          * Re-take critsect.
    440          */
    441         rc = RTCritSectEnter(&pThis->CritSect);
    442         if (RT_FAILURE(rc))
    443         {
    444             AssertMsgFailed(("RTCritSectEnter failed on rwsem %p, rc=%Rrc\n", RWSem, rc));
    445             break;
    446         }
    447 //        AssertMsg(!pThis->cReads, ("We woke up and there are readers around!\n"));
     515        if (rcWait == VERR_TIMEOUT)
     516        {
     517            rc = VERR_TIMEOUT;
     518            break;
     519        }
    448520    }
    449521
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette