VirtualBox

Ignore:
Timestamp:
Jul 2, 2010 1:25:25 PM (15 years ago)
Author:
vboxsync
Message:

semeventmulti-r0drv-solaris.c: The atomic+volatile mess isn't needed because of the mutex.

File:
1 edited

Legend:

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

    r30576 r30578  
    4949*******************************************************************************/
    5050/**
    51  * FreeBSD multiple release event semaphore.
     51 * Solaris multiple release event semaphore.
    5252 */
    5353typedef struct RTSEMEVENTMULTIINTERNAL
     
    5656    uint32_t volatile   u32Magic;
    5757    /** The number of waiting threads. */
    58     uint32_t volatile   cWaiters;
     58    uint32_t            cWaiters;
    5959    /** Set if the event object is signaled. */
    60     uint8_t volatile    fSignaled;
     60    uint8_t             fSignaled;
    6161    /** The number of threads in the process of waking up, doubles up as a ref counter. */
    62     uint32_t volatile   cWaking;
    63     /** Object version that is incremented every time the object is signaled. */
    64     uint32_t volatile   u32Version;
     62    uint32_t            cWaking;
     63    /** Object generation.
     64     * This is incremented every time the object is signalled and used to
     65     * check for spurious wake-ups. */
     66    uint32_t            uSignalGen;
    6567    /** The Solaris mutex protecting this structure and pairing up the with the cv. */
    6668    kmutex_t            Mtx;
     
    8890    if (pThis)
    8991    {
    90         pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
    91         pThis->cWaiters = 0;
    92         pThis->cWaking = 0;
    93         pThis->fSignaled = 0;
    94         pThis->u32Version = 0;
     92        pThis->u32Magic   = RTSEMEVENTMULTI_MAGIC;
     93        pThis->cWaiters   = 0;
     94        pThis->cWaking    = 0;
     95        pThis->fSignaled  = 0;
     96        pThis->uSignalGen = 0;
    9597        mutex_init(&pThis->Mtx, "IPRT Multiple Release Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
    9698        cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL);
     
    113115
    114116    mutex_enter(&pThis->Mtx);
    115     ASMAtomicIncU32(&pThis->u32Magic); /* make the handle invalid */
     117
     118    Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
     119    pThis->u32Magic = RTSEMEVENTMULTI_MAGIC_DEAD;
    116120    if (pThis->cWaiters > 0)
    117121    {
    118122        /* abort waiting thread, last man cleans up. */
    119         ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
     123        pThis->cWaking += pThis->cWaiters;
     124        pThis->cWaiters = 0;
    120125        cv_broadcast(&pThis->Cnd);
     126
    121127        mutex_exit(&pThis->Mtx);
    122128    }
     
    127133    {
    128134        mutex_exit(&pThis->Mtx);
     135
    129136        cv_destroy(&pThis->Cnd);
    130137        mutex_destroy(&pThis->Mtx);
     
    166173    }
    167174
    168     ASMAtomicXchgU8(&pThis->fSignaled, true);
     175    pThis->fSignaled = true;
     176    pThis->uSignalGen++;
    169177    if (pThis->cWaiters > 0)
    170178    {
    171         ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
    172         ASMAtomicXchgU32(&pThis->cWaiters, 0);
    173         ASMAtomicIncU32(&pThis->u32Version);
     179        pThis->cWaking += pThis->cWaiters;
     180        pThis->cWaiters = 0;
    174181        cv_broadcast(&pThis->Cnd);
    175182    }
     
    212219    }
    213220
    214     ASMAtomicXchgU8(&pThis->fSignaled, false);
     221    pThis->fSignaled = false;
    215222    mutex_exit(&pThis->Mtx);
    216223
     
    220227
    221228
     229/**
     230 * Translate milliseconds into ticks and go to sleep using the right method.
     231 *
     232 * @retval  >0 on normal or spurious wake-up.
     233 * @retval  -1 on timeout.
     234 * @retval  0 on signal.
     235 */
    222236static int rtSemEventMultiWaitWorker(PRTSEMEVENTMULTIINTERNAL pThis, RTMSINTERVAL cMillies, bool fInterruptible)
    223237{
    224     /*
    225      * Translate milliseconds into ticks and go to sleep.
    226      */
    227     int rc = 0;
     238    int rc;
    228239    if (cMillies != RT_INDEFINITE_WAIT)
    229240    {
     
    269280    else
    270281    {
    271         ASMAtomicIncU32(&pThis->cWaiters);
     282        pThis->cWaiters++;
     283
     284        /* This loop is only for continuing after a spurious wake-up. */
    272285        for (;;)
    273286        {
    274             uint32_t u32VersionBeforeWait = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->u32Version);
     287            uint32_t const uSignalGenBeforeWait = pThis->uSignalGen;
    275288            rc = rtSemEventMultiWaitWorker(pThis, cMillies, fInterruptible);
    276             uint32_t u32Version = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->u32Version);
    277289            if (rc > 0)
    278290            {
    279291                if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC))
    280292                {
     293                    if (pThis->uSignalGen == uSignalGenBeforeWait)
     294                        continue; /* Spurious wake-up, go back to waiting. */
     295
    281296                    /* Retured due to call to cv_signal() or cv_broadcast() */
    282                     if (u32Version != u32VersionBeforeWait)
    283                     {
    284                         rc = VINF_SUCCESS;
    285                         ASMAtomicDecU32(&pThis->cWaking);
    286                         break;
    287                     }
    288                     else
    289                     {
    290                         /* Spurious wakeup, go back to waiting */
    291                         continue;
    292                     }
     297                    pThis->cWaking--;
     298                    rc = VINF_SUCCESS;
    293299                }
    294300                else
     
    296302                    /* We're being destroyed */
    297303                    rc = VERR_SEM_DESTROYED;
    298                     if (!ASMAtomicDecU32(&pThis->cWaking))
     304                    if (!--pThis->cWaiters)
    299305                    {
    300306                        mutex_exit(&pThis->Mtx);
     
    304310                        return rc;
    305311                    }
    306                     break;
    307312                }
    308313            }
     
    311316                /* Returned due to timeout being reached */
    312317                if (pThis->cWaiters > 0)
    313                     ASMAtomicDecU32(&pThis->cWaiters);
     318                    pThis->cWaiters--;
    314319                rc = VERR_TIMEOUT;
    315                 break;
    316320            }
    317321            else
     
    319323                /* Returned due to pending signal */
    320324                if (pThis->cWaiters > 0)
    321                     ASMAtomicDecU32(&pThis->cWaiters);
     325                    pThis->cWaiters--;
    322326                rc = VERR_INTERRUPTED;
    323                 break;
    324327            }
     328            break;
    325329        }
    326330    }
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