VirtualBox

Ignore:
Timestamp:
Jan 11, 2010 1:24:09 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
56457
Message:

iprt: Added RTSemEventCreateEx and did some cleanups of the RTSemEventDestroy behavior wrt NIL handles.

File:
1 edited

Legend:

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

    r22819 r25717  
    6565
    6666
    67 RTDECL(int)  RTSemEventCreate(PRTSEMEVENT pEventSem)
    68 {
    69     Assert(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *));
    70     AssertPtrReturn(pEventSem, VERR_INVALID_POINTER);
    71 
    72     PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)RTMemAllocZ(sizeof(*pEventInt));
    73     if (pEventInt)
    74     {
    75         pEventInt->u32Magic = RTSEMEVENT_MAGIC;
    76         pEventInt->cWaiters = 0;
    77         pEventInt->cWaking = 0;
    78         pEventInt->fSignaled = 0;
    79         int rc = RTSpinlockCreate(&pEventInt->hSpinLock);
    80         if (RT_SUCCESS(rc))
    81         {
    82             *pEventSem = pEventInt;
    83             return VINF_SUCCESS;
    84         }
    85 
    86         RTMemFree(pEventInt);
    87         return rc;
    88     }
    89     return VERR_NO_MEMORY;
    90 }
    91 
    92 
    93 RTDECL(int)  RTSemEventDestroy(RTSEMEVENT EventSem)
    94 {
    95     if (EventSem == NIL_RTSEMEVENT)     /* don't bitch */
    96         return VERR_INVALID_HANDLE;
    97     PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
    98     RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
    99 
    100     AssertPtrReturn(pEventInt, VERR_INVALID_HANDLE);
    101     AssertMsgReturn(pEventInt->u32Magic == RTSEMEVENT_MAGIC,
    102                     ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic),
     67RTDECL(int)  RTSemEventCreate(PRTSEMEVENT phEventSem)
     68{
     69    return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
     70}
     71
     72
     73RTDECL(int)  RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
     74{
     75    AssertCompile(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *));
     76    AssertReturn(!(fFlags & ~RTSEMEVENT_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
     77    AssertPtrReturn(phEventSem, VERR_INVALID_POINTER);
     78
     79    PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)RTMemAllocZ(sizeof(*pThis));
     80    if (!pThis)
     81        return VERR_NO_MEMORY;
     82
     83    pThis->u32Magic  = RTSEMEVENT_MAGIC;
     84    pThis->cWaiters  = 0;
     85    pThis->cWaking   = 0;
     86    pThis->fSignaled = 0;
     87    int rc = RTSpinlockCreate(&pThis->hSpinLock);
     88    if (RT_SUCCESS(rc))
     89    {
     90        *phEventSem = pThis;
     91        return VINF_SUCCESS;
     92    }
     93
     94    RTMemFree(pThis);
     95    return rc;
     96}
     97
     98
     99RTDECL(int)  RTSemEventDestroy(RTSEMEVENT hEventSem)
     100{
     101    PRTSEMEVENTINTERNAL pThis = hEventSem;
     102    RTSPINLOCKTMP       Tmp   = RTSPINLOCKTMP_INITIALIZER;
     103
     104    if (pThis == NIL_RTSEMEVENT)
     105        return VINF_SUCCESS;
     106    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     107    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
     108
     109    RTSpinlockAcquire(pThis->hSpinLock, &Tmp);
     110
     111    ASMAtomicIncU32(&pThis->u32Magic); /* make the handle invalid */
     112    if (pThis->cWaiters > 0)
     113    {
     114        /* abort waiting thread, last man cleans up. */
     115        ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
     116        sleepq_lock(pThis);
     117        sleepq_broadcast(pThis, SLEEPQ_CONDVAR, 0, 0);
     118        sleepq_release(pThis);
     119        RTSpinlockRelease(pThis->hSpinLock, &Tmp);
     120    }
     121    else if (pThis->cWaking)
     122        /* the last waking thread is gonna do the cleanup */
     123        RTSpinlockRelease(pThis->hSpinLock, &Tmp);
     124    else
     125    {
     126        RTSpinlockRelease(pThis->hSpinLock, &Tmp);
     127        RTSpinlockDestroy(pThis->hSpinLock);
     128        RTMemFree(pThis);
     129    }
     130
     131    return VINF_SUCCESS;
     132}
     133
     134
     135RTDECL(int)  RTSemEventSignal(RTSEMEVENT hEventSem)
     136{
     137    RTSPINLOCKTMP       Tmp = RTSPINLOCKTMP_INITIALIZER;
     138    PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
     139    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     140    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC,
     141                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
    103142                    VERR_INVALID_HANDLE);
    104143
    105     RTSpinlockAcquire(pEventInt->hSpinLock, &Tmp);
    106 
    107     ASMAtomicIncU32(&pEventInt->u32Magic); /* make the handle invalid */
    108     if (pEventInt->cWaiters > 0)
    109     {
    110         /* abort waiting thread, last man cleans up. */
    111         ASMAtomicXchgU32(&pEventInt->cWaking, pEventInt->cWaking + pEventInt->cWaiters);
    112         sleepq_lock(pEventInt);
    113         sleepq_broadcast(pEventInt, SLEEPQ_CONDVAR, 0, 0);
    114         sleepq_release(pEventInt);
    115         RTSpinlockRelease(pEventInt->hSpinLock, &Tmp);
    116     }
    117     else if (pEventInt->cWaking)
    118         /* the last waking thread is gonna do the cleanup */
    119         RTSpinlockRelease(pEventInt->hSpinLock, &Tmp);
    120     else
    121     {
    122         RTSpinlockRelease(pEventInt->hSpinLock, &Tmp);
    123         RTSpinlockDestroy(pEventInt->hSpinLock);
    124         RTMemFree(pEventInt);
    125     }
    126 
    127     return VINF_SUCCESS;
    128 }
    129 
    130 
    131 RTDECL(int)  RTSemEventSignal(RTSEMEVENT EventSem)
    132 {
    133     RTSPINLOCKTMP       Tmp = RTSPINLOCKTMP_INITIALIZER;
    134     PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
    135     AssertPtrReturn(pEventInt, VERR_INVALID_HANDLE);
    136     AssertMsgReturn(pEventInt->u32Magic == RTSEMEVENT_MAGIC,
    137                     ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic),
    138                     VERR_INVALID_HANDLE);
    139 
    140     RTSpinlockAcquire(pEventInt->hSpinLock, &Tmp);
    141 
    142     if (pEventInt->cWaiters > 0)
    143     {
    144         ASMAtomicDecU32(&pEventInt->cWaiters);
    145         ASMAtomicIncU32(&pEventInt->cWaking);
    146         sleepq_lock(pEventInt);
    147         int fWakeupSwapProc = sleepq_signal(pEventInt, SLEEPQ_CONDVAR, 0, 0);
    148         sleepq_release(pEventInt);
     144    RTSpinlockAcquire(pThis->hSpinLock, &Tmp);
     145
     146    if (pThis->cWaiters > 0)
     147    {
     148        ASMAtomicDecU32(&pThis->cWaiters);
     149        ASMAtomicIncU32(&pThis->cWaking);
     150        sleepq_lock(pThis);
     151        int fWakeupSwapProc = sleepq_signal(pThis, SLEEPQ_CONDVAR, 0, 0);
     152        sleepq_release(pThis);
    149153        if (fWakeupSwapProc)
    150154            kick_proc0();
    151155    }
    152156    else
    153         ASMAtomicXchgU8(&pEventInt->fSignaled, true);
    154 
    155     RTSpinlockRelease(pEventInt->hSpinLock, &Tmp);
     157        ASMAtomicXchgU8(&pThis->fSignaled, true);
     158
     159    RTSpinlockRelease(pThis->hSpinLock, &Tmp);
    156160    return VINF_SUCCESS;
    157161}
    158162
    159163
    160 static int rtSemEventWait(RTSEMEVENT EventSem, unsigned cMillies, bool fInterruptible)
     164static int rtSemEventWait(RTSEMEVENT hEventSem, unsigned cMillies, bool fInterruptible)
    161165{
    162166    int rc;
    163167    RTSPINLOCKTMP       Tmp = RTSPINLOCKTMP_INITIALIZER;
    164     PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
    165     AssertPtrReturn(pEventInt, VERR_INVALID_HANDLE);
    166     AssertMsgReturn(pEventInt->u32Magic == RTSEMEVENT_MAGIC,
    167                     ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic),
     168    PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
     169    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     170    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC,
     171                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
    168172                    VERR_INVALID_HANDLE);
    169173
    170     RTSpinlockAcquire(pEventInt->hSpinLock, &Tmp);
    171 
    172     if (pEventInt->fSignaled)
    173     {
    174         Assert(!pEventInt->cWaiters);
    175         ASMAtomicXchgU8(&pEventInt->fSignaled, false);
     174    RTSpinlockAcquire(pThis->hSpinLock, &Tmp);
     175
     176    if (pThis->fSignaled)
     177    {
     178        Assert(!pThis->cWaiters);
     179        ASMAtomicXchgU8(&pThis->fSignaled, false);
    176180        rc = VINF_SUCCESS;
    177181    }
     
    182186        else
    183187        {
    184             ASMAtomicIncU32(&pEventInt->cWaiters);
     188            ASMAtomicIncU32(&pThis->cWaiters);
    185189
    186190            int fFlags = SLEEPQ_CONDVAR;
     
    189193                fFlags |= SLEEPQ_INTERRUPTIBLE;
    190194
    191             sleepq_lock(pEventInt);
    192             sleepq_add(pEventInt, NULL, "IPRT Event Semaphore", fFlags, 0);
     195            sleepq_lock(pThis);
     196            sleepq_add(pThis, NULL, "IPRT Event Semaphore", fFlags, 0);
    193197
    194198            if (cMillies != RT_INDEFINITE_WAIT)
     
    202206                tv.tv_usec = (cMillies % 1000) * 1000;
    203207
    204                 sleepq_set_timeout(pEventInt, tvtohz(&tv));
    205 
    206                 RTSpinlockRelease(pEventInt->hSpinLock, &Tmp);
     208                sleepq_set_timeout(pThis, tvtohz(&tv));
     209
     210                RTSpinlockRelease(pThis->hSpinLock, &Tmp);
    207211
    208212                if (fInterruptible)
    209                     rc = SLEEPQ_TIMEDWAIT_SIG(pEventInt);
     213                    rc = SLEEPQ_TIMEDWAIT_SIG(pThis);
    210214                else
    211                     rc = SLEEPQ_TIMEDWAIT(pEventInt);
     215                    rc = SLEEPQ_TIMEDWAIT(pThis);
    212216            }
    213217            else
    214218            {
    215                 RTSpinlockRelease(pEventInt->hSpinLock, &Tmp);
     219                RTSpinlockRelease(pThis->hSpinLock, &Tmp);
    216220
    217221                if (fInterruptible)
    218                     rc = SLEEPQ_WAIT_SIG(pEventInt);
     222                    rc = SLEEPQ_WAIT_SIG(pThis);
    219223                else
    220224                {
    221225                    rc = 0;
    222                     SLEEPQ_WAIT(pEventInt);
     226                    SLEEPQ_WAIT(pThis);
    223227                }
    224228            }
    225229
    226             RTSpinlockAcquire(pEventInt->hSpinLock, &Tmp);
     230            RTSpinlockAcquire(pThis->hSpinLock, &Tmp);
    227231
    228232            switch (rc)
    229233            {
    230234                case 0:
    231                     if (pEventInt->u32Magic == RTSEMEVENT_MAGIC)
     235                    if (pThis->u32Magic == RTSEMEVENT_MAGIC)
    232236                    {
    233                         ASMAtomicDecU32(&pEventInt->cWaking);
     237                        ASMAtomicDecU32(&pThis->cWaking);
    234238                        rc = VINF_SUCCESS;
    235239                    }
     
    238242                        rc = VERR_SEM_DESTROYED; /** @todo this isn't necessarily correct, we've
    239243                                                  * could've woken up just before destruction... */
    240                         if (!ASMAtomicDecU32(&pEventInt->cWaking))
     244                        if (!ASMAtomicDecU32(&pThis->cWaking))
    241245                        {
    242246                            /* The event was destroyed, as the last thread do the cleanup.
    243247                               we don't actually know whether */
    244                             RTSpinlockRelease(pEventInt->hSpinLock, &Tmp);
    245                             RTSpinlockDestroy(pEventInt->hSpinLock);
    246                             RTMemFree(pEventInt);
     248                            RTSpinlockRelease(pThis->hSpinLock, &Tmp);
     249                            RTSpinlockDestroy(pThis->hSpinLock);
     250                            RTMemFree(pThis);
    247251                            return rc;
    248252                        }
     
    252256                case EWOULDBLOCK:
    253257                    Assert(cMillies != RT_INDEFINITE_WAIT);
    254                     if (pEventInt->cWaiters > 0)
    255                         ASMAtomicDecU32(&pEventInt->cWaiters);
     258                    if (pThis->cWaiters > 0)
     259                        ASMAtomicDecU32(&pThis->cWaiters);
    256260                    rc = VERR_TIMEOUT;
    257261                    break;
     
    260264                case ERESTART:
    261265                    Assert(fInterruptible);
    262                     if (pEventInt->cWaiters > 0)
    263                         ASMAtomicDecU32(&pEventInt->cWaiters);
     266                    if (pThis->cWaiters > 0)
     267                        ASMAtomicDecU32(&pThis->cWaiters);
    264268                    rc = VERR_INTERRUPTED;
    265269                    break;
     
    273277    }
    274278
    275     RTSpinlockRelease(pEventInt->hSpinLock, &Tmp);
     279    RTSpinlockRelease(pThis->hSpinLock, &Tmp);
    276280
    277281    return rc;
     
    279283
    280284
    281 RTDECL(int)  RTSemEventWait(RTSEMEVENT EventSem, unsigned cMillies)
    282 {
    283     return rtSemEventWait(EventSem, cMillies, false /* not interruptible */);
    284 }
    285 
    286 
    287 RTDECL(int)  RTSemEventWaitNoResume(RTSEMEVENT EventSem, unsigned cMillies)
    288 {
    289     return rtSemEventWait(EventSem, cMillies, true /* interruptible */);
    290 }
    291 
     285RTDECL(int)  RTSemEventWait(RTSEMEVENT hEventSem, unsigned cMillies)
     286{
     287    return rtSemEventWait(hEventSem, cMillies, false /* not interruptible */);
     288}
     289
     290
     291RTDECL(int)  RTSemEventWaitNoResume(RTSEMEVENT hEventSem, unsigned cMillies)
     292{
     293    return rtSemEventWait(hEventSem, cMillies, true /* interruptible */);
     294}
     295
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette