VirtualBox

Changeset 28566 in vbox


Ignore:
Timestamp:
Apr 21, 2010 2:46:09 PM (15 years ago)
Author:
vboxsync
Message:

Solaris/r0drv: semevent mutex fixes.

File:
1 edited

Legend:

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

    r25724 r28566  
    5858    /** The number of waiting threads. */
    5959    uint32_t volatile   cWaiters;
     60    /** Set if the next waiter is to be signaled. */
     61    uint8_t volatile    fPendingSignal;
    6062    /** Set if the event object is signaled. */
    6163    uint8_t volatile    fSignaled;
    62     /** The number of threads in the process of waking up. */
    63     uint32_t volatile   cWaking;
     64    /** The number of threads referencing this object. */
     65    uint32_t volatile   cRefs;
    6466    /** The Solaris mutex protecting this structure and pairing up the with the cv. */
    6567    kmutex_t            Mtx;
     
    8789        return VERR_NO_MEMORY;
    8890
    89     pThis->u32Magic = RTSEMEVENT_MAGIC;
    90     pThis->cWaiters = 0;
    91     pThis->cWaking = 0;
    92     pThis->fSignaled = 0;
     91    pThis->u32Magic       = RTSEMEVENT_MAGIC;
     92    pThis->cWaiters       = 0;
     93    pThis->cRefs          = 1;
     94    pThis->fSignaled      = 0;
     95    pThis->fPendingSignal = 0;
    9396    mutex_init(&pThis->Mtx, "IPRT Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
    9497    cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL);
     
    112115    if (pThis->cWaiters > 0)
    113116    {
    114         /* abort waiting thread, last man cleans up. */
    115         ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
     117        /*
     118         * Signal all threads to destroy.
     119         */
    116120        cv_broadcast(&pThis->Cnd);
    117121        mutex_exit(&pThis->Mtx);
    118122    }
    119     else if (pThis->cWaking)
    120     {
    121         /* the last waking thread is gonna do the cleanup */
    122         mutex_exit(&pThis->Mtx);
    123     }
    124     else
    125     {
     123    else if (pThis->cRefs == 0)
     124    {
     125        /*
     126         * We're the last thread referencing this object, destroy it.
     127         */
    126128        mutex_exit(&pThis->Mtx);
    127129        cv_destroy(&pThis->Cnd);
    128130        mutex_destroy(&pThis->Mtx);
    129131        RTMemFree(pThis);
     132    }
     133    else
     134    {
     135        /*
     136         * There are other threads still referencing this object, last one cleans up.
     137         */
     138        mutex_exit(&pThis->Mtx);
    130139    }
    131140
     
    169178    if (pThis->cWaiters > 0)
    170179    {
     180        /*
     181         * We decrement waiters here so that we don't keep signalling threads that
     182         * have already been signalled but not yet scheduled. So cWaiters might be
     183         * 0 even when there are threads actually waiting.
     184         */
    171185        ASMAtomicDecU32(&pThis->cWaiters);
    172         ASMAtomicIncU32(&pThis->cWaking);
     186        ASMAtomicXchgU8(&pThis->fSignaled, true);
    173187        cv_signal(&pThis->Cnd);
    174188    }
    175189    else
    176         ASMAtomicXchgU8(&pThis->fSignaled, true);
     190        ASMAtomicXchgU8(&pThis->fPendingSignal, true);
    177191
    178192    mutex_exit(&pThis->Mtx);
     
    194208    mutex_enter(&pThis->Mtx);
    195209
    196     if (pThis->fSignaled)
    197     {
     210    if (pThis->fPendingSignal)
     211    {
     212        /*
     213         * The last signal occurred without any waiters and now we're the first thread
     214         * waiting for the event signal. So no real need to wait for one.
     215         */
    198216        Assert(!pThis->cWaiters);
    199         ASMAtomicXchgU8(&pThis->fSignaled, false);
     217        ASMAtomicXchgU8(&pThis->fPendingSignal, false);
    200218        rc = VINF_SUCCESS;
    201219    }
     
    232250        if (rc > 0)
    233251        {
    234             /* Retured due to call to cv_signal() or cv_broadcast() */
    235252            if (pThis->u32Magic != RTSEMEVENT_MAGIC)
    236253            {
     254                /*
     255                 * We're being destroyed.
     256                 */
    237257                rc = VERR_SEM_DESTROYED;
    238                 if (!ASMAtomicDecU32(&pThis->cWaking))
     258                if (!ASMAtomicDecU32(&pThis->cRefs))
    239259                {
    240260                    mutex_exit(&pThis->Mtx);
     
    244264                    return rc;
    245265                }
     266                ASMAtomicDecU32(&pThis->cWaiters);
    246267            }
    247 
    248             ASMAtomicDecU32(&pThis->cWaking);
    249             rc = VINF_SUCCESS;
     268            else
     269            {
     270                if (pThis->fSignaled)
     271                {
     272                    /*
     273                     * We've been signaled by RTSemEventSignal().
     274                     */
     275                    ASMAtomicXchgU8(&pThis->fSignaled, false);
     276                    rc = VINF_SUCCESS;
     277                }
     278                else
     279                {
     280                    /*
     281                     * Premature wakeup due to some signal.
     282                     */
     283                    rc = VERR_INTERRUPTED;
     284                    ASMAtomicDecU32(&pThis->cWaiters);
     285                }
     286            }
    250287        }
    251288        else if (rc == -1)
    252289        {
    253             /* Returned due to timeout being reached */
    254             if (pThis->cWaiters > 0)
    255                 ASMAtomicDecU32(&pThis->cWaiters);
     290            /*
     291             * Timeout reached.
     292             */
    256293            rc = VERR_TIMEOUT;
     294            ASMAtomicDecU32(&pThis->cWaiters);
    257295        }
    258296        else
    259297        {
    260298            /* Returned due to pending signal */
    261             if (pThis->cWaiters > 0)
    262                 ASMAtomicDecU32(&pThis->cWaiters);
    263299            rc = VERR_INTERRUPTED;
     300            ASMAtomicDecU32(&pThis->cWaiters);
    264301        }
    265302    }
     
    280317    return rtSemEventWait(hEventSem, cMillies, true /* interruptible */);
    281318}
     319
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