VirtualBox

Changeset 30472 in vbox


Ignore:
Timestamp:
Jun 28, 2010 2:15:54 PM (14 years ago)
Author:
vboxsync
Message:

Runtime/r0drv/Solaris: Fix RTSemEvent for spurious wakeups (#5090)

File:
1 edited

Legend:

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

    r29284 r30472  
    5757    /** The number of waiting threads. */
    5858    uint32_t volatile   cWaiters;
    59     /** Set if the next waiter is to be signaled. */
    60     uint8_t volatile    fPendingSignal;
    61     /** Set if the event object is signaled. */
    62     uint8_t volatile    fSignaled;
     59    /** The number of signalled threads. */
     60    uint32_t volatile   cWakeUp;
    6361    /** The number of threads referencing this object. */
    6462    uint32_t volatile   cRefs;
     
    9088    pThis->u32Magic       = RTSEMEVENT_MAGIC;
    9189    pThis->cWaiters       = 0;
     90    pThis->cWakeUp        = 0;
    9291    pThis->cRefs          = 1;
    93     pThis->fSignaled      = 0;
    94     pThis->fPendingSignal = 0;
    9592    mutex_init(&pThis->Mtx, "IPRT Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
    9693    cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL);
     
    178175    }
    179176
    180     if (pThis->cWaiters > 0)
     177    ASMAtomicIncU32(&pThis->cWakeUp);
     178    if (pThis->cWakeUp <= pThis->cWaiters)
    181179    {
    182180        /*
     
    185183         * 0 even when there are threads actually waiting.
    186184         */
    187         ASMAtomicDecU32(&pThis->cWaiters);
    188         ASMAtomicXchgU8(&pThis->fSignaled, true);
    189185        cv_signal(&pThis->Cnd);
    190186    }
    191     else
    192         ASMAtomicXchgU8(&pThis->fPendingSignal, true);
    193187
    194188    mutex_exit(&pThis->Mtx);
     
    196190    RT_ASSERT_PREEMPT_CPUID();
    197191    return VINF_SUCCESS;
     192}
     193
     194
     195static int rtSemEventWaitWorker(PRTSEMEVENTINTERNAL pThis, RTMSINTERVAL cMillies, bool fInterruptible)
     196{
     197    /*
     198     * Translate milliseconds into ticks and go to sleep.
     199     */
     200    int rc = 0;
     201    if (cMillies != RT_INDEFINITE_WAIT)
     202    {
     203        clock_t cTicks = drv_usectohz((clock_t)(cMillies * 1000L));
     204        clock_t cTimeout = ddi_get_lbolt();
     205        cTimeout += cTicks;
     206        if (fInterruptible)
     207            rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, cTimeout);
     208        else
     209            rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, cTimeout);
     210    }
     211    else
     212    {
     213        if (fInterruptible)
     214            rc = cv_wait_sig(&pThis->Cnd, &pThis->Mtx);
     215        else
     216        {
     217            cv_wait(&pThis->Cnd, &pThis->Mtx);
     218            rc = 1;
     219        }
     220    }
     221
     222    return rc;
    198223}
    199224
     
    212237    ASMAtomicIncU32(&pThis->cRefs);
    213238
    214     if (pThis->fPendingSignal)
     239    if (pThis->cWakeUp > 0)
    215240    {
    216241        /*
     
    219244         */
    220245        Assert(!pThis->cWaiters);
    221         ASMAtomicXchgU8(&pThis->fPendingSignal, false);
     246        ASMAtomicWriteU32((uint32_t volatile *)&pThis->cWakeUp, 0);
    222247        rc = VINF_SUCCESS;
    223248    }
     
    226251    else
    227252    {
     253        uint32_t cWakeUp = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->cWakeUp);
    228254        ASMAtomicIncU32(&pThis->cWaiters);
    229 
    230         /*
    231          * Translate milliseconds into ticks and go to sleep.
    232          */
    233         if (cMillies != RT_INDEFINITE_WAIT)
     255        for (;;)
    234256        {
    235             clock_t cTicks = drv_usectohz((clock_t)(cMillies * 1000L));
    236             clock_t cTimeout = ddi_get_lbolt();
    237             cTimeout += cTicks;
    238             if (fInterruptible)
    239                 rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, cTimeout);
    240             else
    241                 rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, cTimeout);
    242         }
    243         else
    244         {
    245             if (fInterruptible)
    246                 rc = cv_wait_sig(&pThis->Cnd, &pThis->Mtx);
    247             else
     257            rc = rtSemEventWaitWorker(pThis, cMillies, fInterruptible);
     258            if (rc > 0)
    248259            {
    249                 cv_wait(&pThis->Cnd, &pThis->Mtx);
    250                 rc = 1;
     260                if (pThis->u32Magic != RTSEMEVENT_MAGIC)
     261                {
     262                    /*
     263                     * We're being destroyed.
     264                     */
     265                    ASMAtomicDecU32(&pThis->cWaiters);
     266                    rc = VERR_SEM_DESTROYED;
     267                    break;
     268                }
     269                else
     270                {
     271                    uint32_t cWakeUpNow = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->cWakeUp);
     272                    if (cWakeUpNow > cWakeUp)
     273                    {
     274                        /*
     275                         * We've been signaled by RTSemEventSignal(), consume the wake up.
     276                         */
     277                        ASMAtomicDecU32(&pThis->cWaiters);
     278                        ASMAtomicDecU32(&pThis->cWakeUp);
     279                        rc = VINF_SUCCESS;
     280                        break;
     281                    }
     282                    else
     283                    {
     284                        /*
     285                         * Premature wakeup due to some signal, go back to waiting.
     286                         */
     287                        continue;
     288                    }
     289                }
    251290            }
    252         }
    253 
    254         if (rc > 0)
    255         {
    256             if (pThis->u32Magic != RTSEMEVENT_MAGIC)
     291            else if (rc == -1)
    257292            {
    258293                /*
    259                  * We're being destroyed.
     294                 * Timeout reached.
    260295                 */
    261                 rc = VERR_SEM_DESTROYED;
    262296                ASMAtomicDecU32(&pThis->cWaiters);
     297                rc = VERR_TIMEOUT;
     298                break;
    263299            }
    264300            else
    265301            {
    266                 if (pThis->fSignaled)
    267                 {
    268                     /*
    269                      * We've been signaled by RTSemEventSignal().
    270                      */
    271                     ASMAtomicXchgU8(&pThis->fSignaled, false);
    272                     rc = VINF_SUCCESS;
    273                 }
    274                 else
    275                 {
    276                     /*
    277                      * Premature wakeup due to some signal.
    278                      */
    279                     rc = VERR_INTERRUPTED;
    280                     ASMAtomicDecU32(&pThis->cWaiters);
    281                 }
     302                /* Returned due to pending signal */
     303                ASMAtomicDecU32(&pThis->cWaiters);
     304                rc = VERR_INTERRUPTED;
     305                break;
    282306            }
    283         }
    284         else if (rc == -1)
    285         {
    286             /*
    287              * Timeout reached.
    288              */
    289             rc = VERR_TIMEOUT;
    290             ASMAtomicDecU32(&pThis->cWaiters);
    291         }
    292         else
    293         {
    294             /* Returned due to pending signal */
    295             rc = VERR_INTERRUPTED;
    296             ASMAtomicDecU32(&pThis->cWaiters);
    297307        }
    298308    }
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