Changeset 30579 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Jul 2, 2010 2:45:28 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/solaris/semeventmulti-r0drv-solaris.c
r30578 r30579 55 55 /** Magic value (RTSEMEVENTMULTI_MAGIC). */ 56 56 uint32_t volatile u32Magic; 57 /** The number of waiting threads. */58 uint32_t cWaiters;57 /** The number of references. */ 58 int32_t volatile cRefs; 59 59 /** 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; 63 61 /** Object generation. 64 62 * This is incremented every time the object is signalled and used to … … 90 88 if (pThis) 91 89 { 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; 97 94 mutex_init(&pThis->Mtx, "IPRT Multiple Release Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL)); 98 95 cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL); … … 102 99 } 103 100 return VERR_NO_MEMORY; 101 } 102 103 104 /** 105 * Destructor that is called when cRefs == 0. 106 * @param pThis The instance to destroy. 107 */ 108 static void rtSemEventMultiDtor(PRTSEMEVENTMULTIINTERNAL pThis) 109 { 110 cv_destroy(&pThis->Cnd); 111 mutex_destroy(&pThis->Mtx); 112 RTMemFree(pThis); 104 113 } 105 114 … … 112 121 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 113 122 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); 114 124 RT_ASSERT_INTS_ON(); 115 125 116 126 mutex_enter(&pThis->Mtx); 117 127 128 /* Invalidate the handle and wake up all threads that might be waiting on the semaphore. */ 118 129 Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC); 119 130 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)) 131 135 mutex_exit(&pThis->Mtx); 132 136 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); 141 138 return VINF_SUCCESS; 142 } 143 144 145 RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem) 139 140 } 141 142 143 RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem) 146 144 { 147 145 PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem; … … 172 170 mutex_enter(&pThis->Mtx); 173 171 } 174 172 Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC); 173 174 /* 175 * Do the job. 176 */ 175 177 pThis->fSignaled = true; 176 178 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); 183 180 184 181 mutex_exit(&pThis->Mtx); … … 189 186 190 187 191 RTDECL(int) 188 RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem) 192 189 { 193 190 PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem; … … 218 215 mutex_enter(&pThis->Mtx); 219 216 } 220 217 Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC); 218 219 /* 220 * Do the job. 221 */ 221 222 pThis->fSignaled = false; 223 222 224 mutex_exit(&pThis->Mtx); 223 225 … … 273 275 274 276 mutex_enter(&pThis->Mtx); 277 Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC); 278 ASMAtomicIncS32(&pThis->cRefs); 275 279 276 280 if (pThis->fSignaled) … … 280 284 else 281 285 { 282 pThis->cWaiters++;283 286 284 287 /* This loop is only for continuing after a spurious wake-up. */ … … 294 297 continue; /* Spurious wake-up, go back to waiting. */ 295 298 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(). */ 298 300 rc = VINF_SUCCESS; 299 301 } 300 302 else 301 { 302 /* We're being destroyed */ 303 /* We're being destroyed. */ 303 304 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 }313 305 } 314 306 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. */ 319 308 rc = VERR_TIMEOUT; 320 }321 309 else 322 {323 /* Returned due to pending signal */324 if (pThis->cWaiters > 0)325 pThis->cWaiters--;326 310 rc = VERR_INTERRUPTED; 327 }311 /* Returned due to pending signal. */ 328 312 break; 329 313 } 330 314 } 331 315 332 mutex_exit(&pThis->Mtx); 316 if (RT_LIKELY(ASMAtomicDecS32(&pThis->cRefs))) 317 mutex_exit(&pThis->Mtx); 318 else 319 rtSemEventMultiDtor(pThis); 333 320 return rc; 334 321 }
Note:
See TracChangeset
for help on using the changeset viewer.