Changeset 30578 in vbox for trunk/src/VBox/Runtime/r0drv/solaris
- Timestamp:
- Jul 2, 2010 1:25:25 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/solaris/semeventmulti-r0drv-solaris.c
r30576 r30578 49 49 *******************************************************************************/ 50 50 /** 51 * FreeBSDmultiple release event semaphore.51 * Solaris multiple release event semaphore. 52 52 */ 53 53 typedef struct RTSEMEVENTMULTIINTERNAL … … 56 56 uint32_t volatile u32Magic; 57 57 /** The number of waiting threads. */ 58 uint32_t volatilecWaiters;58 uint32_t cWaiters; 59 59 /** Set if the event object is signaled. */ 60 uint8_t volatilefSignaled;60 uint8_t fSignaled; 61 61 /** The number of threads in the process of waking up, doubles up as a ref counter. */ 62 uint32_t volatile cWaking; 63 /** Object version that is incremented every time the object is signaled. */ 64 uint32_t volatile u32Version; 62 uint32_t cWaking; 63 /** Object generation. 64 * This is incremented every time the object is signalled and used to 65 * check for spurious wake-ups. */ 66 uint32_t uSignalGen; 65 67 /** The Solaris mutex protecting this structure and pairing up the with the cv. */ 66 68 kmutex_t Mtx; … … 88 90 if (pThis) 89 91 { 90 pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;91 pThis->cWaiters = 0;92 pThis->cWaking = 0;93 pThis->fSignaled = 0;94 pThis->u 32Version = 0;92 pThis->u32Magic = RTSEMEVENTMULTI_MAGIC; 93 pThis->cWaiters = 0; 94 pThis->cWaking = 0; 95 pThis->fSignaled = 0; 96 pThis->uSignalGen = 0; 95 97 mutex_init(&pThis->Mtx, "IPRT Multiple Release Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL)); 96 98 cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL); … … 113 115 114 116 mutex_enter(&pThis->Mtx); 115 ASMAtomicIncU32(&pThis->u32Magic); /* make the handle invalid */ 117 118 Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC); 119 pThis->u32Magic = RTSEMEVENTMULTI_MAGIC_DEAD; 116 120 if (pThis->cWaiters > 0) 117 121 { 118 122 /* abort waiting thread, last man cleans up. */ 119 ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters); 123 pThis->cWaking += pThis->cWaiters; 124 pThis->cWaiters = 0; 120 125 cv_broadcast(&pThis->Cnd); 126 121 127 mutex_exit(&pThis->Mtx); 122 128 } … … 127 133 { 128 134 mutex_exit(&pThis->Mtx); 135 129 136 cv_destroy(&pThis->Cnd); 130 137 mutex_destroy(&pThis->Mtx); … … 166 173 } 167 174 168 ASMAtomicXchgU8(&pThis->fSignaled, true); 175 pThis->fSignaled = true; 176 pThis->uSignalGen++; 169 177 if (pThis->cWaiters > 0) 170 178 { 171 ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters); 172 ASMAtomicXchgU32(&pThis->cWaiters, 0); 173 ASMAtomicIncU32(&pThis->u32Version); 179 pThis->cWaking += pThis->cWaiters; 180 pThis->cWaiters = 0; 174 181 cv_broadcast(&pThis->Cnd); 175 182 } … … 212 219 } 213 220 214 ASMAtomicXchgU8(&pThis->fSignaled, false);221 pThis->fSignaled = false; 215 222 mutex_exit(&pThis->Mtx); 216 223 … … 220 227 221 228 229 /** 230 * Translate milliseconds into ticks and go to sleep using the right method. 231 * 232 * @retval >0 on normal or spurious wake-up. 233 * @retval -1 on timeout. 234 * @retval 0 on signal. 235 */ 222 236 static int rtSemEventMultiWaitWorker(PRTSEMEVENTMULTIINTERNAL pThis, RTMSINTERVAL cMillies, bool fInterruptible) 223 237 { 224 /* 225 * Translate milliseconds into ticks and go to sleep. 226 */ 227 int rc = 0; 238 int rc; 228 239 if (cMillies != RT_INDEFINITE_WAIT) 229 240 { … … 269 280 else 270 281 { 271 ASMAtomicIncU32(&pThis->cWaiters); 282 pThis->cWaiters++; 283 284 /* This loop is only for continuing after a spurious wake-up. */ 272 285 for (;;) 273 286 { 274 uint32_t u32VersionBeforeWait = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->u32Version);287 uint32_t const uSignalGenBeforeWait = pThis->uSignalGen; 275 288 rc = rtSemEventMultiWaitWorker(pThis, cMillies, fInterruptible); 276 uint32_t u32Version = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->u32Version);277 289 if (rc > 0) 278 290 { 279 291 if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC)) 280 292 { 293 if (pThis->uSignalGen == uSignalGenBeforeWait) 294 continue; /* Spurious wake-up, go back to waiting. */ 295 281 296 /* Retured due to call to cv_signal() or cv_broadcast() */ 282 if (u32Version != u32VersionBeforeWait) 283 { 284 rc = VINF_SUCCESS; 285 ASMAtomicDecU32(&pThis->cWaking); 286 break; 287 } 288 else 289 { 290 /* Spurious wakeup, go back to waiting */ 291 continue; 292 } 297 pThis->cWaking--; 298 rc = VINF_SUCCESS; 293 299 } 294 300 else … … 296 302 /* We're being destroyed */ 297 303 rc = VERR_SEM_DESTROYED; 298 if (! ASMAtomicDecU32(&pThis->cWaking))304 if (!--pThis->cWaiters) 299 305 { 300 306 mutex_exit(&pThis->Mtx); … … 304 310 return rc; 305 311 } 306 break;307 312 } 308 313 } … … 311 316 /* Returned due to timeout being reached */ 312 317 if (pThis->cWaiters > 0) 313 ASMAtomicDecU32(&pThis->cWaiters);318 pThis->cWaiters--; 314 319 rc = VERR_TIMEOUT; 315 break;316 320 } 317 321 else … … 319 323 /* Returned due to pending signal */ 320 324 if (pThis->cWaiters > 0) 321 ASMAtomicDecU32(&pThis->cWaiters);325 pThis->cWaiters--; 322 326 rc = VERR_INTERRUPTED; 323 break;324 327 } 328 break; 325 329 } 326 330 }
Note:
See TracChangeset
for help on using the changeset viewer.