VirtualBox

Changeset 201 in vbox for trunk/src/VBox/Runtime/r0drv


Ignore:
Timestamp:
Jan 20, 2007 4:09:16 AM (18 years ago)
Author:
vboxsync
Message:

event sems

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/darwin/semaphore-r0drv-darwin.cpp

    r199 r201  
    3636*   Structures and Typedefs                                                    *
    3737*******************************************************************************/
    38 #if 0 /** @todo */
    3938/**
    4039 * Darwin event semaphore.
     
    4443    /** Magic value (RTSEMEVENT_MAGIC). */
    4544    uint32_t volatile   u32Magic;
    46     /** The NT Event object. */
    47     KEVENT              Event;
     45    /** The number of waiting threads. */
     46    uint32_t volatile   cWaiters;
     47    /** Set if the event object is signaled. */
     48    uint8_t volatile    fSignaled;
     49    /** The number of threads in the process of waking up. */
     50    uint32_t volatile   cWaking;
     51    /** The spinlock protecting us. */
     52    lck_spin_t         *pSpinlock;
    4853} RTSEMEVENTINTERNAL, *PRTSEMEVENTINTERNAL;
    4954
    5055/** Magic for the Darwin event semaphore structure. (Neil Gaiman) */
    5156#define RTSEMEVENT_MAGIC 0x19601110
    52 #endif
    5357
    5458#if 0 /** @todo */
     
    8488
    8589
    86 #if 0/** @todo */
    8790RTDECL(int)  RTSemEventCreate(PRTSEMEVENT pEventSem)
    8891{
    8992    Assert(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *));
     93    AssertPtrReturn(VALID_PTR(pEventSem), VERR_INVALID_POINTER);
     94
    9095    PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pEventInt));
    9196    if (pEventInt)
    9297    {
    9398        pEventInt->u32Magic = RTSEMEVENT_MAGIC;
    94         wait_queue_init
    95         KeInitializeEvent(&pEventInt->Event, SynchronizationEvent, FALSE);
    96         *pEventSem = pEventInt;
    97         return VINF_SUCCESS;
     99        pEventInt->cWaiters = 0;
     100        pEventInt->cWaking = 0;
     101        pEventInt->fSignaled = 0;
     102        Assert(g_pDarwinLockGroup);
     103        pEventInt->pSpinlock = lck_spin_alloc_init(g_pDarwinLockGroup, LCK_ATTR_NULL);
     104        if (pEventInt->pSpinlock)
     105        {
     106            *pEventSem = pEventInt;
     107            return VINF_SUCCESS;
     108        }
     109
     110        pEventInt->u32Magic = 0;
     111        RTMemFree(pEventInt);
    98112    }
    99113    return VERR_NO_MEMORY;
     
    103117RTDECL(int)  RTSemEventDestroy(RTSEMEVENT EventSem)
    104118{
    105     /*
    106      * Validate input.
    107      */
     119    if (EventSem == NIL_RTSEMEVENT)     /* don't bitch */
     120        return VERR_INVALID_HANDLE;
    108121    PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
    109     if (!pEventInt)
    110         return VERR_INVALID_PARAMETER;
    111     if (pEventInt->u32Magic != RTSEMEVENT_MAGIC)
    112     {
    113         AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p\n", pEventInt->u32Magic, pEventInt));
    114         return VERR_INVALID_PARAMETER;
    115     }
    116 
    117     /*
    118      * Invalidate it and signal the object just in case.
    119      */
    120     ASMAtomicIncU32(&pEventInt->u32Magic);
    121     KeSetEvent(&pEventInt->Event, 0xfff, FALSE);
    122     RTMemFree(pEventInt);
     122    AssertPtrReturn(pEventInt, VERR_INVALID_HANDLE);
     123    AssertMsgReturn(pEventInt->u32Magic == RTSEMEVENT_MAGIC,
     124                    ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic),
     125                    VERR_INVALID_HANDLE);
     126
     127    lck_spin_lock(pEventInt->pSpinlock);
     128    ASMAtomicIncU32(&pEventInt->u32Magic); /* make the handle invalid */
     129    if (pEventInt->cWaiters > 0)
     130    {
     131        /* abort waiting thread, last man cleans up. */
     132        ASMAtomicXchgU32(&pEventInt->cWaking, pEventInt->cWaking + pEventInt->cWaiters);
     133        thread_wakeup_prim((event_t)pEventInt, FALSE /* all threads */, THREAD_RESTART);
     134        lck_spin_unlock(pEventInt->pSpinlock);
     135    }
     136    else if (pEventInt->cWaking)
     137        /* the last waking thread is gonna do the cleanup */
     138        lck_spin_unlock(pEventInt->pSpinlock);
     139    else
     140    {
     141        lck_spin_unlock(pEventInt->pSpinlock);
     142        lck_spin_destroy(pEventInt->pSpinlock, g_pDarwinLockGroup);
     143        RTMemFree(pEventInt);
     144    }
     145
    123146    return VINF_SUCCESS;
    124147}
     
    127150RTDECL(int)  RTSemEventSignal(RTSEMEVENT EventSem)
    128151{
    129     /*
    130      * Validate input.
    131      */
    132152    PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
    133     if (!pEventInt)
    134         return VERR_INVALID_PARAMETER;
    135     if (    !pEventInt
    136         ||  pEventInt->u32Magic != RTSEMEVENT_MAGIC)
    137     {
    138         AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p\n", pEventInt ? pEventInt->u32Magic : 0, pEventInt));
    139         return VERR_INVALID_PARAMETER;
    140     }
    141 
    142     /*
    143      * Signal the event object.
    144      */
    145     KeSetEvent(&pEventInt->Event, 1, FALSE);
    146     return VINF_SUCCESS;
     153    AssertPtrReturn(pEventInt, VERR_INVALID_HANDLE);
     154    AssertMsgReturn(pEventInt->u32Magic == RTSEMEVENT_MAGIC,
     155                    ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic),
     156                    VERR_INVALID_HANDLE);
     157
     158    lck_spin_lock(pEventInt->pSpinlock);
     159
     160    if (pEventInt->cWaiters > 0)
     161    {
     162        ASMAtomicDecU32(&pEventInt->cWaiters);
     163        ASMAtomicIncU32(&pEventInt->cWaking);
     164        thread_wakeup_prim((event_t)pEventInt, TRUE /* one thread */, THREAD_AWAKENED);
     165    }
     166    else
     167        ASMAtomicXchgU8(&pEventInt->fSignaled, true);
     168
     169    lck_spin_unlock(pEventInt->pSpinlock);
     170    return VINF_SUCCESS;
     171}
     172
     173
     174static int rtSemEventWait(RTSEMEVENT EventSem, unsigned cMillies, wait_interrupt_t fInterruptible)
     175{
     176    PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
     177    AssertPtrReturn(pEventInt, VERR_INVALID_HANDLE);
     178    AssertMsgReturn(pEventInt->u32Magic == RTSEMEVENT_MAGIC,
     179                    ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic),
     180                    VERR_INVALID_HANDLE);
     181
     182    lck_spin_lock(pEventInt->pSpinlock);
     183
     184    int rc;
     185    if (pEventInt->fSignaled)
     186    {
     187        Assert(!pEventInt->cWaiters);
     188        ASMAtomicXchgU8(&pEventInt->fSignaled, false);
     189        rc = 0;
     190    }
     191    else
     192    {
     193        ASMAtomicIncU32(&pEventInt->cWaiters);
     194
     195        wait_result_t rcWait;
     196        if (cMillies == RT_INDEFINITE_WAIT)
     197            rcWait = lck_spin_sleep(pEventInt->pSpinlock, LCK_SLEEP_DEFAULT, (event_t)pEventInt, fInterruptible);
     198        else
     199        {
     200            uint64_t u64AbsTime;
     201            nanoseconds_to_absolutetime(cMillies * UINT64_C(1000000), &u64AbsTime);
     202            u64AbsTime += mach_absolute_time();
     203
     204            rcWait = lck_spin_sleep_deadline(pEventInt->pSpinlock, LCK_SLEEP_DEFAULT,
     205                                             (event_t)pEventInt, fInterruptible, u64AbsTime);
     206        }
     207        switch (rcWait)
     208        {
     209            case THREAD_AWAKENED:
     210                Assert(pEventInt->cWaking > 0);
     211                if (    !ASMAtomicDecU32(&pEventInt->cWaking)
     212                    &&  pEventInt->u32Magic != RTSEMEVENT_MAGIC)
     213                {
     214                    /* the event was destroyed after we woke up, as the last thread do the cleanup. */
     215                    lck_spin_unlock(pEventInt->pSpinlock);
     216                    Assert(g_pDarwinLockGroup);
     217                    lck_spin_destroy(pEventInt->pSpinlock, g_pDarwinLockGroup);
     218                    RTMemFree(pEventInt);
     219                    return VINF_SUCCESS;
     220                }
     221                rc = VINF_SUCCESS;
     222                break;
     223
     224            case THREAD_TIMED_OUT:
     225                Assert(cMillies != RT_INDEFINITE_WAIT);
     226                ASMAtomicDecU32(&pEventInt->cWaiters);
     227                rc = VERR_TIMEOUT;
     228                break;
     229
     230            case THREAD_INTERRUPTED:
     231                Assert(fInterruptible);
     232                ASMAtomicDecU32(&pEventInt->cWaiters);
     233                rc = VERR_INTERRUPTED;
     234                break;
     235
     236            case THREAD_RESTART:
     237                /* Last one out does the cleanup. */
     238                if (!ASMAtomicDecU32(&pEventInt->cWaking))
     239                {
     240                    lck_spin_unlock(pEventInt->pSpinlock);
     241                    Assert(g_pDarwinLockGroup);
     242                    lck_spin_destroy(pEventInt->pSpinlock, g_pDarwinLockGroup);
     243                    RTMemFree(pEventInt);
     244                    return VERR_SEM_DESTROYED;
     245                }
     246
     247                rc = VERR_SEM_DESTROYED;
     248                break;
     249
     250            default:
     251                AssertMsgFailed(("rcWait=%d\n", rcWait));
     252                rc = VERR_GENERAL_FAILURE;
     253                break;
     254        }
     255    }
     256
     257    lck_spin_unlock(pEventInt->pSpinlock);
     258    return rc;
    147259}
    148260
     
    150262RTDECL(int)  RTSemEventWait(RTSEMEVENT EventSem, unsigned cMillies)
    151263{
    152     /*
    153      * Validate input.
    154      */
    155     PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
    156     if (!pEventInt)
    157         return VERR_INVALID_PARAMETER;
    158     if (    !pEventInt
    159         ||  pEventInt->u32Magic != RTSEMEVENT_MAGIC)
    160     {
    161         AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p\n", pEventInt ? pEventInt->u32Magic : 0, pEventInt));
    162         return VERR_INVALID_PARAMETER;
    163     }
    164 
    165     /*
    166      * Wait for it.
    167      */
    168     NTSTATUS rcNt;
    169     if (cMillies == RT_INDEFINITE_WAIT)
    170         rcNt = KeWaitForSingleObject(&pEventInt->Event, Executive, KernelMode, TRUE, NULL);
    171     else
    172     {
    173         LARGE_INTEGER Timeout;
    174         Timeout.QuadPart = -(int64_t)cMillies * 10000;
    175         rcNt = KeWaitForSingleObject(&pEventInt->Event, Executive, KernelMode, TRUE, &Timeout);
    176     }
    177     switch (rcNt)
    178     {
    179         case STATUS_SUCCESS:
    180             if (pEventInt->u32Magic == RTSEMEVENT_MAGIC)
    181                 return VINF_SUCCESS;
    182             return VERR_SEM_DESTROYED;
    183         case STATUS_ALERTED:
    184             return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
    185         case STATUS_USER_APC:
    186             return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
    187         case STATUS_TIMEOUT:
    188             return VERR_TIMEOUT;
    189         default:
    190             AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p: wait returned %lx!\n",
    191                              pEventInt->u32Magic, pEventInt, (long)rcNt));
    192             return VERR_INTERNAL_ERROR;
    193     }
    194 }
    195 #endif /* todo */
     264    return rtSemEventWait(EventSem, cMillies, FALSE /* not interruptable */);
     265}
     266
     267
     268RTDECL(int)  RTSemEventWaitNoResume(RTSEMEVENT EventSem, unsigned cMillies)
     269{
     270    return rtSemEventWait(EventSem, cMillies, TRUE /* interruptable */);
     271}
     272
    196273
    197274
     
    354431        return VERR_INVALID_PARAMETER;
    355432    PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
    356     AssertPtrReturn(VALID_PTR(pFastInt), VERR_INVALID_POINTER);
     433    AssertPtrReturn(pFastInt, VERR_INVALID_PARAMETER);
    357434    AssertMsgReturn(pFastInt->u32Magic == RTSEMFASTMUTEX_MAGIC,
    358435                    ("pFastInt->u32Magic=%RX32 pFastInt=%p\n", pFastInt->u32Magic, pFastInt),
     
    372449{
    373450    PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
    374     AssertMsgReturn(VALID_PTR(pFastInt) && pFastInt->u32Magic == RTSEMFASTMUTEX_MAGIC,
    375                     ("pFastInt->u32Magic=%RX32 pFastInt=%p\n", VALID_PTR(pFastInt) ? pFastInt->u32Magic : 0, pFastInt),
     451    AssertPtrReturn(pFastInt, VERR_INVALID_PARAMETER);
     452    AssertMsgReturn(pFastInt->u32Magic == RTSEMFASTMUTEX_MAGIC,
     453                    ("pFastInt->u32Magic=%RX32 pFastInt=%p\n", pFastInt->u32Magic, pFastInt),
    376454                    VERR_INVALID_PARAMETER);
    377455    lck_mtx_lock(pFastInt->pMtx);
     
    383461{
    384462    PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
    385     AssertMsgReturn(VALID_PTR(pFastInt) && pFastInt->u32Magic == RTSEMFASTMUTEX_MAGIC,
    386                     ("pFastInt->u32Magic=%RX32 pFastInt=%p\n", VALID_PTR(pFastInt) ? pFastInt->u32Magic : 0, pFastInt),
     463    AssertPtrReturn(pFastInt, VERR_INVALID_PARAMETER);
     464    AssertMsgReturn(pFastInt->u32Magic == RTSEMFASTMUTEX_MAGIC,
     465                    ("pFastInt->u32Magic=%RX32 pFastInt=%p\n", pFastInt->u32Magic, pFastInt),
    387466                    VERR_INVALID_PARAMETER);
    388467    lck_mtx_unlock(pFastInt->pMtx);
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