VirtualBox

Changeset 30579 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Jul 2, 2010 2:45:28 PM (14 years ago)
Author:
vboxsync
Message:

semeventmulti-r0drv-solaris.c: Simplified it. No need to spend a lot of code trying to avoid some cv_broadcast calls.

File:
1 edited

Legend:

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

    r30578 r30579  
    5555    /** Magic value (RTSEMEVENTMULTI_MAGIC). */
    5656    uint32_t volatile   u32Magic;
    57     /** The number of waiting threads. */
    58     uint32_t            cWaiters;
     57    /** The number of references. */
     58    int32_t volatile    cRefs;
    5959    /** Set if the event object is signaled. */
    60     uint8_t             fSignaled;
    61     /** The number of threads in the process of waking up, doubles up as a ref counter. */
    62     uint32_t            cWaking;
     60    bool                fSignaled;
    6361    /** Object generation.
    6462     * This is incremented every time the object is signalled and used to
     
    9088    if (pThis)
    9189    {
    92         pThis->u32Magic   = RTSEMEVENTMULTI_MAGIC;
    93         pThis->cWaiters   = 0;
    94         pThis->cWaking    = 0;
    95         pThis->fSignaled  = 0;
    96         pThis->uSignalGen = 0;
     90        pThis->u32Magic     = RTSEMEVENTMULTI_MAGIC;
     91        pThis->cRefs        = 1;
     92        pThis->fSignaled    = false;
     93        pThis->uSignalGen   = 0;
    9794        mutex_init(&pThis->Mtx, "IPRT Multiple Release Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
    9895        cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL);
     
    10299    }
    103100    return VERR_NO_MEMORY;
     101}
     102
     103
     104/**
     105 * Destructor that is called when cRefs == 0.
     106 * @param   pThis               The instance to destroy.
     107 */
     108static void rtSemEventMultiDtor(PRTSEMEVENTMULTIINTERNAL pThis)
     109{
     110    cv_destroy(&pThis->Cnd);
     111    mutex_destroy(&pThis->Mtx);
     112    RTMemFree(pThis);
    104113}
    105114
     
    112121    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    113122    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
     123    AssertMsgReturn(pThis->cRefs > 0, ("pThis=%p cRefs=%d\n", pThis, pThis->cRefs), VERR_INVALID_HANDLE);
    114124    RT_ASSERT_INTS_ON();
    115125
    116126    mutex_enter(&pThis->Mtx);
    117127
     128    /* Invalidate the handle and wake up all threads that might be waiting on the semaphore. */
    118129    Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
    119130    pThis->u32Magic = RTSEMEVENTMULTI_MAGIC_DEAD;
    120     if (pThis->cWaiters > 0)
    121     {
    122         /* abort waiting thread, last man cleans up. */
    123         pThis->cWaking += pThis->cWaiters;
    124         pThis->cWaiters = 0;
    125         cv_broadcast(&pThis->Cnd);
    126 
    127         mutex_exit(&pThis->Mtx);
    128     }
    129     else if (pThis->cWaking)
    130         /* the last waking thread is gonna do the cleanup */
     131    cv_broadcast(&pThis->Cnd);
     132
     133    /* Drop the reference from RTSemEventMultiCreateEx. */
     134    if (ASMAtomicDecS32(&pThis->cRefs))
    131135        mutex_exit(&pThis->Mtx);
    132136    else
    133     {
    134         mutex_exit(&pThis->Mtx);
    135 
    136         cv_destroy(&pThis->Cnd);
    137         mutex_destroy(&pThis->Mtx);
    138         RTMemFree(pThis);
    139     }
    140 
     137        rtSemEventMultiDtor(pThis);
    141138    return VINF_SUCCESS;
    142 }
    143 
    144 
    145 RTDECL(int)  RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
     139
     140}
     141
     142
     143RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
    146144{
    147145    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
     
    172170        mutex_enter(&pThis->Mtx);
    173171    }
    174 
     172    Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
     173
     174    /*
     175     * Do the job.
     176     */
    175177    pThis->fSignaled = true;
    176178    pThis->uSignalGen++;
    177     if (pThis->cWaiters > 0)
    178     {
    179         pThis->cWaking += pThis->cWaiters;
    180         pThis->cWaiters = 0;
    181         cv_broadcast(&pThis->Cnd);
    182     }
     179    cv_broadcast(&pThis->Cnd);
    183180
    184181    mutex_exit(&pThis->Mtx);
     
    189186
    190187
    191 RTDECL(int)  RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
     188RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
    192189{
    193190    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
     
    218215        mutex_enter(&pThis->Mtx);
    219216    }
    220 
     217    Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
     218
     219    /*
     220     * Do the job.
     221     */
    221222    pThis->fSignaled = false;
     223
    222224    mutex_exit(&pThis->Mtx);
    223225
     
    273275
    274276    mutex_enter(&pThis->Mtx);
     277    Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
     278    ASMAtomicIncS32(&pThis->cRefs);
    275279
    276280    if (pThis->fSignaled)
     
    280284    else
    281285    {
    282         pThis->cWaiters++;
    283286
    284287        /* This loop is only for continuing after a spurious wake-up. */
     
    294297                        continue; /* Spurious wake-up, go back to waiting. */
    295298
    296                     /* Retured due to call to cv_signal() or cv_broadcast() */
    297                     pThis->cWaking--;
     299                    /* Retured due to call to cv_signal() or cv_broadcast(). */
    298300                    rc = VINF_SUCCESS;
    299301                }
    300302                else
    301                 {
    302                     /* We're being destroyed */
     303                    /* We're being destroyed. */
    303304                    rc = VERR_SEM_DESTROYED;
    304                     if (!--pThis->cWaiters)
    305                     {
    306                         mutex_exit(&pThis->Mtx);
    307                         cv_destroy(&pThis->Cnd);
    308                         mutex_destroy(&pThis->Mtx);
    309                         RTMemFree(pThis);
    310                         return rc;
    311                     }
    312                 }
    313305            }
    314306            else if (rc == -1)
    315             {
    316                 /* Returned due to timeout being reached */
    317                 if (pThis->cWaiters > 0)
    318                     pThis->cWaiters--;
     307                /* Returned due to timeout being reached. */
    319308                rc = VERR_TIMEOUT;
    320             }
    321309            else
    322             {
    323                 /* Returned due to pending signal */
    324                 if (pThis->cWaiters > 0)
    325                     pThis->cWaiters--;
    326310                rc = VERR_INTERRUPTED;
    327             }
     311                /* Returned due to pending signal. */
    328312            break;
    329313        }
    330314    }
    331315
    332     mutex_exit(&pThis->Mtx);
     316    if (RT_LIKELY(ASMAtomicDecS32(&pThis->cRefs)))
     317        mutex_exit(&pThis->Mtx);
     318    else
     319        rtSemEventMultiDtor(pThis);
    333320    return rc;
    334321}
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