VirtualBox

Changeset 5335 in vbox for trunk/src


Ignore:
Timestamp:
Oct 16, 2007 5:59:15 PM (17 years ago)
Author:
vboxsync
Message:

all threads must wakeup on destroy; check for the right macro (bug copied from the freebsd implementation); interruptible/non-interruptible waiting.

File:
1 edited

Legend:

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

    r4717 r5335  
    5959    AssertPtrReturn(pEventMultiSem, VERR_INVALID_POINTER);
    6060
    61     PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pEventMultiInt));
    62     if (pEventMultiInt)
    63     {
    64         pEventMultiInt->u32Magic = RTSEMEVENTMULTI_MAGIC;
    65         pEventMultiInt->cWaiters = 0;
    66         pEventMultiInt->cWaking = 0;
    67         pEventMultiInt->fSignaled = 0;
    68         mutex_init(&pEventMultiInt->Mtx, "IPRT Multiple Release Event Semaphore", MUTEX_DRIVER, NULL);
    69         cv_init(&pEventMultiInt->Cnd, "IPRT CV", CV_DRIVER, NULL);
    70         *pEventMultiSem = pEventMultiInt;
     61    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pThis));
     62    if (pThis)
     63    {
     64        pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
     65        pThis->cWaiters = 0;
     66        pThis->cWaking = 0;
     67        pThis->fSignaled = 0;
     68        mutex_init(&pThis->Mtx, "IPRT Multiple Release Event Semaphore", MUTEX_DRIVER, NULL);
     69        cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL);
     70        *pEventMultiSem = pThis;
    7171        return VINF_SUCCESS;
    7272    }
     
    7979    if (EventMultiSem == NIL_RTSEMEVENTMULTI)     /* don't bitch */
    8080        return VERR_INVALID_HANDLE;
    81     PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
    82     AssertPtrReturn(pEventMultiInt, VERR_INVALID_HANDLE);
    83     AssertMsgReturn(pEventMultiInt->u32Magic == RTSEMEVENTMULTI_MAGIC,
    84                     ("pEventMultiInt=%p u32Magic=%#x\n", pEventMultiInt, pEventMultiInt->u32Magic),
    85                     VERR_INVALID_HANDLE);
    86 
    87     mutex_enter(&pEventMultiInt->Mtx);
    88     ASMAtomicIncU32(&pEventMultiInt->u32Magic); /* make the handle invalid */
    89     if (pEventMultiInt->cWaiters > 0)
     81    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
     82    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     83    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
     84                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
     85                    VERR_INVALID_HANDLE);
     86
     87    mutex_enter(&pThis->Mtx);
     88    ASMAtomicIncU32(&pThis->u32Magic); /* make the handle invalid */
     89    if (pThis->cWaiters > 0)
    9090    {
    9191        /* abort waiting thread, last man cleans up. */
    92         ASMAtomicXchgU32(&pEventMultiInt->cWaking, pEventMultiInt->cWaking + pEventMultiInt->cWaiters);
    93         cv_signal(&pEventMultiInt->Cnd);
    94         mutex_exit(&pEventMultiInt->Mtx);
    95     }
    96     else if (pEventMultiInt->cWaking)
     92        ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
     93        cv_broadcast(&pThis->Cnd);
     94        mutex_exit(&pThis->Mtx);
     95    }
     96    else if (pThis->cWaking)
    9797        /* the last waking thread is gonna do the cleanup */
    98         mutex_exit(&pEventMultiInt->Mtx);
     98        mutex_exit(&pThis->Mtx);
    9999    else
    100100    {
    101         mutex_exit(&pEventMultiInt->Mtx);
    102         cv_destroy(&pEventMultiInt->Cnd);
    103         mutex_destroy(&pEventMultiInt->Mtx);
    104         RTMemFree(pEventMultiInt);
     101        mutex_exit(&pThis->Mtx);
     102        cv_destroy(&pThis->Cnd);
     103        mutex_destroy(&pThis->Mtx);
     104        RTMemFree(pThis);
    105105    }
    106106
     
    111111RTDECL(int)  RTSemEventMultiSignal(RTSEMEVENTMULTI EventMultiSem)
    112112{
    113     PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
    114     AssertPtrReturn(pEventMultiInt, VERR_INVALID_HANDLE);
    115     AssertMsgReturn(pEventMultiInt->u32Magic == RTSEMEVENTMULTI_MAGIC,
    116                     ("pEventMultiInt=%p u32Magic=%#x\n", pEventMultiInt, pEventMultiInt->u32Magic),
    117                     VERR_INVALID_HANDLE);
    118 
    119     mutex_enter(&pEventMultiInt->Mtx);
    120 
    121     ASMAtomicXchgU8(&pEventMultiInt->fSignaled, true);
    122     if (pEventMultiInt->cWaiters > 0)
    123     {
    124         ASMAtomicXchgU32(&pEventMultiInt->cWaking, pEventMultiInt->cWaking + pEventMultiInt->cWaiters);
    125         ASMAtomicXchgU32(&pEventMultiInt->cWaiters, 0);
    126         cv_signal(&pEventMultiInt->Cnd);
    127     }
    128 
    129     mutex_exit(&pEventMultiInt->Mtx);
     113    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
     114    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     115    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
     116                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
     117                    VERR_INVALID_HANDLE);
     118
     119    mutex_enter(&pThis->Mtx);
     120
     121    ASMAtomicXchgU8(&pThis->fSignaled, true);
     122    if (pThis->cWaiters > 0)
     123    {
     124        ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
     125        ASMAtomicXchgU32(&pThis->cWaiters, 0);
     126        cv_signal(&pThis->Cnd);
     127    }
     128
     129    mutex_exit(&pThis->Mtx);
    130130    return VINF_SUCCESS;
    131131}
     
    134134RTDECL(int)  RTSemEventMultiReset(RTSEMEVENTMULTI EventMultiSem)
    135135{
    136     PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
    137     AssertPtrReturn(pEventMultiInt, VERR_INVALID_HANDLE);
    138     AssertMsgReturn(pEventMultiInt->u32Magic == RTSEMEVENTMULTI_MAGIC,
    139                     ("pEventMultiInt=%p u32Magic=%#x\n", pEventMultiInt, pEventMultiInt->u32Magic),
    140                     VERR_INVALID_HANDLE);
    141 
    142     mutex_enter(&pEventMultiInt->Mtx);
    143     ASMAtomicXchgU8(&pEventMultiInt->fSignaled, false);
    144     mutex_exit(&pEventMultiInt->Mtx);
     136    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
     137    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     138    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
     139                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
     140                    VERR_INVALID_HANDLE);
     141
     142    mutex_enter(&pThis->Mtx);
     143    ASMAtomicXchgU8(&pThis->fSignaled, false);
     144    mutex_exit(&pThis->Mtx);
    145145    return VINF_SUCCESS;
    146146}
     
    150150{
    151151    int rc;
    152     PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
    153     AssertPtrReturn(pEventMultiInt, VERR_INVALID_HANDLE);
    154     AssertMsgReturn(pEventMultiInt->u32Magic == RTSEMEVENTMULTI_MAGIC,
    155                     ("pEventMultiInt=%p u32Magic=%#x\n", pEventMultiInt, pEventMultiInt->u32Magic),
    156                     VERR_INVALID_HANDLE);
    157 
    158     mutex_enter(&pEventMultiInt->Mtx);
    159 
    160     if (pEventMultiInt->fSignaled)
     152    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
     153    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     154    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
     155                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
     156                    VERR_INVALID_HANDLE);
     157
     158    mutex_enter(&pThis->Mtx);
     159
     160    if (pThis->fSignaled)
    161161        rc = VINF_SUCCESS;
    162162    else
     
    175175        timeout += cTicks;
    176176       
    177         ASMAtomicIncU32(&pEventMultiInt->cWaiters);
    178 
    179         /** @todo r=bird: Is this interruptible or non-interruptible? */
    180         rc = cv_timedwait_sig(&pEventMultiInt->Cnd, &pEventMultiInt->Mtx, timeout);
     177        ASMAtomicIncU32(&pThis->cWaiters);
     178
     179        if (fInterruptible)
     180            rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, timeout);
     181        else
     182            rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, timeout);
    181183        if (rc > 0)
    182184        {
    183185            /* Retured due to call to cv_signal() or cv_broadcast() */
    184             if (pEventMultiInt->u32Magic != RTSEMEVENT_MAGIC)
     186            if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC))
     187                rc = VINF_SUCCESS;
     188            else
    185189            {
    186190                rc = VERR_SEM_DESTROYED;
    187                 if (!ASMAtomicDecU32(&pEventMultiInt->cWaking))
     191                if (!ASMAtomicDecU32(&pThis->cWaking))
    188192                {
    189                     mutex_exit(&pEventMultiInt->Mtx);
    190                     cv_destroy(&pEventMultiInt->Cnd);
    191                     mutex_destroy(&pEventMultiInt->Mtx);
    192                     RTMemFree(pEventMultiInt);
     193                    mutex_exit(&pThis->Mtx);
     194                    cv_destroy(&pThis->Cnd);
     195                    mutex_destroy(&pThis->Mtx);
     196                    RTMemFree(pThis);
    193197                    return rc;
    194198                }
    195199            }
    196 
    197             ASMAtomicDecU32(&pEventMultiInt->cWaking);
    198             rc = VINF_SUCCESS;
     200            ASMAtomicDecU32(&pThis->cWaking);
    199201        }
    200202        else if (rc == -1)
    201203        {
    202204            /* Returned due to timeout being reached */
    203             if (pEventMultiInt->cWaiters > 0)
    204                 ASMAtomicDecU32(&pEventMultiInt->cWaiters);
     205            if (pThis->cWaiters > 0)
     206                ASMAtomicDecU32(&pThis->cWaiters);
    205207            rc = VERR_TIMEOUT;
    206208        }
     
    208210        {
    209211            /* Returned due to pending signal */
    210             if (pEventMultiInt->cWaiters > 0)
    211                 ASMAtomicDecU32(&pEventMultiInt->cWaiters);
     212            if (pThis->cWaiters > 0)
     213                ASMAtomicDecU32(&pThis->cWaiters);
    212214            rc = VERR_INTERRUPTED;
    213215        }
    214216    }
    215217
    216     mutex_exit(&pEventMultiInt->Mtx);
     218    mutex_exit(&pThis->Mtx);
    217219    return rc;
    218220}
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