VirtualBox

Ignore:
Timestamp:
Jun 29, 2010 9:03:43 AM (15 years ago)
Author:
vboxsync
Message:

Runtime/r0drv/solaris: fix RTSemEventMulti for spurious wakeups (#5090)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/solaris/semeventmulti-r0drv-solaris.c

    r29284 r30490  
    216216
    217217
     218static int rtSemEventMultiWaitWorker(PRTSEMEVENTMULTIINTERNAL pThis, RTMSINTERVAL cMillies, bool fInterruptible)
     219{
     220    /*
     221     * Translate milliseconds into ticks and go to sleep.
     222     */
     223    int rc = 0;
     224    if (cMillies != RT_INDEFINITE_WAIT)
     225    {
     226        clock_t cTicks = drv_usectohz((clock_t)(cMillies * 1000L));
     227        clock_t cTimeout = ddi_get_lbolt();
     228        cTimeout += cTicks;
     229        if (fInterruptible)
     230            rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, cTimeout);
     231        else
     232            rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, cTimeout);
     233    }
     234    else
     235    {
     236        if (fInterruptible)
     237            rc = cv_wait_sig(&pThis->Cnd, &pThis->Mtx);
     238        else
     239        {
     240            cv_wait(&pThis->Cnd, &pThis->Mtx);
     241            rc = 1;
     242        }
     243    }
     244    return rc;
     245}
     246
     247
    218248static int rtSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies, bool fInterruptible)
    219249{
     
    235265    else
    236266    {
    237         ASMAtomicIncU32(&pThis->cWaiters);
    238 
    239         /*
    240          * Translate milliseconds into ticks and go to sleep.
    241          */
    242         if (cMillies != RT_INDEFINITE_WAIT)
     267        for (;;)
    243268        {
    244             clock_t cTicks = drv_usectohz((clock_t)(cMillies * 1000L));
    245             clock_t cTimeout = ddi_get_lbolt();
    246             cTimeout += cTicks;
    247             if (fInterruptible)
    248                 rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, cTimeout);
    249             else
    250                 rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, cTimeout);
    251         }
    252         else
    253         {
    254             if (fInterruptible)
    255                 rc = cv_wait_sig(&pThis->Cnd, &pThis->Mtx);
    256             else
     269            uint32_t cWakingBeforeWait = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->cWaking);
     270            ASMAtomicIncU32(&pThis->cWaiters);
     271            rc = rtSemEventMultiWaitWorker(pThis, cMillies, fInterruptible);
     272            if (rc > 0)
    257273            {
    258                 cv_wait(&pThis->Cnd, &pThis->Mtx);
    259                 rc = 1;
     274                /* Retured due to call to cv_signal() or cv_broadcast() */
     275                if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC))
     276                {
     277                    uint32_t cWaking = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->cWaking);
     278                    if (cWaking > cWakingBeforeWait)
     279                    {
     280                        rc = VINF_SUCCESS;
     281                        ASMAtomicDecU32(&pThis->cWaking);
     282                        break;
     283                    }
     284                    else
     285                    {
     286                        /* Spurious wakeup, go back to waiting */
     287                        cmn_err(CE_NOTE, "spurious\n");
     288                        continue;
     289                    }
     290                }
     291                else
     292                {
     293                    rc = VERR_SEM_DESTROYED;
     294                    if (!ASMAtomicDecU32(&pThis->cWaking))
     295                    {
     296                        mutex_exit(&pThis->Mtx);
     297                        cv_destroy(&pThis->Cnd);
     298                        mutex_destroy(&pThis->Mtx);
     299                        RTMemFree(pThis);
     300                        return rc;
     301                    }
     302                    break;
     303                }
    260304            }
    261         }
    262         if (rc > 0)
    263         {
    264             /* Retured due to call to cv_signal() or cv_broadcast() */
    265             if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC))
     305            else if (rc == -1)
    266306            {
    267                 rc = VINF_SUCCESS;
    268                 ASMAtomicDecU32(&pThis->cWaking);
     307                /* Returned due to timeout being reached */
     308                if (pThis->cWaiters > 0)
     309                    ASMAtomicDecU32(&pThis->cWaiters);
     310                rc = VERR_TIMEOUT;
     311                break;
    269312            }
    270313            else
    271314            {
    272                 rc = VERR_SEM_DESTROYED;
    273                 if (!ASMAtomicDecU32(&pThis->cWaking))
    274                 {
    275                     mutex_exit(&pThis->Mtx);
    276                     cv_destroy(&pThis->Cnd);
    277                     mutex_destroy(&pThis->Mtx);
    278                     RTMemFree(pThis);
    279                     return rc;
    280                 }
     315                /* Returned due to pending signal */
     316                if (pThis->cWaiters > 0)
     317                    ASMAtomicDecU32(&pThis->cWaiters);
     318                rc = VERR_INTERRUPTED;
     319                break;
    281320            }
    282321        }
    283         else if (rc == -1)
    284         {
    285             /* Returned due to timeout being reached */
    286             if (pThis->cWaiters > 0)
    287                 ASMAtomicDecU32(&pThis->cWaiters);
    288             rc = VERR_TIMEOUT;
    289         }
    290         else
    291         {
    292             /* Returned due to pending signal */
    293             if (pThis->cWaiters > 0)
    294                 ASMAtomicDecU32(&pThis->cWaiters);
    295             rc = VERR_INTERRUPTED;
    296         }
    297322    }
    298323
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