Changeset 28566 in vbox
- Timestamp:
- Apr 21, 2010 2:46:09 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/solaris/semevent-r0drv-solaris.c
r25724 r28566 58 58 /** The number of waiting threads. */ 59 59 uint32_t volatile cWaiters; 60 /** Set if the next waiter is to be signaled. */ 61 uint8_t volatile fPendingSignal; 60 62 /** Set if the event object is signaled. */ 61 63 uint8_t volatile fSignaled; 62 /** The number of threads in the process of waking up. */63 uint32_t volatile c Waking;64 /** The number of threads referencing this object. */ 65 uint32_t volatile cRefs; 64 66 /** The Solaris mutex protecting this structure and pairing up the with the cv. */ 65 67 kmutex_t Mtx; … … 87 89 return VERR_NO_MEMORY; 88 90 89 pThis->u32Magic = RTSEMEVENT_MAGIC; 90 pThis->cWaiters = 0; 91 pThis->cWaking = 0; 92 pThis->fSignaled = 0; 91 pThis->u32Magic = RTSEMEVENT_MAGIC; 92 pThis->cWaiters = 0; 93 pThis->cRefs = 1; 94 pThis->fSignaled = 0; 95 pThis->fPendingSignal = 0; 93 96 mutex_init(&pThis->Mtx, "IPRT Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL)); 94 97 cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL); … … 112 115 if (pThis->cWaiters > 0) 113 116 { 114 /* abort waiting thread, last man cleans up. */ 115 ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters); 117 /* 118 * Signal all threads to destroy. 119 */ 116 120 cv_broadcast(&pThis->Cnd); 117 121 mutex_exit(&pThis->Mtx); 118 122 } 119 else if (pThis->cWaking) 120 { 121 /* the last waking thread is gonna do the cleanup */ 122 mutex_exit(&pThis->Mtx); 123 } 124 else 125 { 123 else if (pThis->cRefs == 0) 124 { 125 /* 126 * We're the last thread referencing this object, destroy it. 127 */ 126 128 mutex_exit(&pThis->Mtx); 127 129 cv_destroy(&pThis->Cnd); 128 130 mutex_destroy(&pThis->Mtx); 129 131 RTMemFree(pThis); 132 } 133 else 134 { 135 /* 136 * There are other threads still referencing this object, last one cleans up. 137 */ 138 mutex_exit(&pThis->Mtx); 130 139 } 131 140 … … 169 178 if (pThis->cWaiters > 0) 170 179 { 180 /* 181 * We decrement waiters here so that we don't keep signalling threads that 182 * have already been signalled but not yet scheduled. So cWaiters might be 183 * 0 even when there are threads actually waiting. 184 */ 171 185 ASMAtomicDecU32(&pThis->cWaiters); 172 ASMAtomic IncU32(&pThis->cWaking);186 ASMAtomicXchgU8(&pThis->fSignaled, true); 173 187 cv_signal(&pThis->Cnd); 174 188 } 175 189 else 176 ASMAtomicXchgU8(&pThis->f Signaled, true);190 ASMAtomicXchgU8(&pThis->fPendingSignal, true); 177 191 178 192 mutex_exit(&pThis->Mtx); … … 194 208 mutex_enter(&pThis->Mtx); 195 209 196 if (pThis->fSignaled) 197 { 210 if (pThis->fPendingSignal) 211 { 212 /* 213 * The last signal occurred without any waiters and now we're the first thread 214 * waiting for the event signal. So no real need to wait for one. 215 */ 198 216 Assert(!pThis->cWaiters); 199 ASMAtomicXchgU8(&pThis->f Signaled, false);217 ASMAtomicXchgU8(&pThis->fPendingSignal, false); 200 218 rc = VINF_SUCCESS; 201 219 } … … 232 250 if (rc > 0) 233 251 { 234 /* Retured due to call to cv_signal() or cv_broadcast() */235 252 if (pThis->u32Magic != RTSEMEVENT_MAGIC) 236 253 { 254 /* 255 * We're being destroyed. 256 */ 237 257 rc = VERR_SEM_DESTROYED; 238 if (!ASMAtomicDecU32(&pThis->c Waking))258 if (!ASMAtomicDecU32(&pThis->cRefs)) 239 259 { 240 260 mutex_exit(&pThis->Mtx); … … 244 264 return rc; 245 265 } 266 ASMAtomicDecU32(&pThis->cWaiters); 246 267 } 247 248 ASMAtomicDecU32(&pThis->cWaking); 249 rc = VINF_SUCCESS; 268 else 269 { 270 if (pThis->fSignaled) 271 { 272 /* 273 * We've been signaled by RTSemEventSignal(). 274 */ 275 ASMAtomicXchgU8(&pThis->fSignaled, false); 276 rc = VINF_SUCCESS; 277 } 278 else 279 { 280 /* 281 * Premature wakeup due to some signal. 282 */ 283 rc = VERR_INTERRUPTED; 284 ASMAtomicDecU32(&pThis->cWaiters); 285 } 286 } 250 287 } 251 288 else if (rc == -1) 252 289 { 253 /* Returned due to timeout being reached */254 if (pThis->cWaiters > 0)255 ASMAtomicDecU32(&pThis->cWaiters);290 /* 291 * Timeout reached. 292 */ 256 293 rc = VERR_TIMEOUT; 294 ASMAtomicDecU32(&pThis->cWaiters); 257 295 } 258 296 else 259 297 { 260 298 /* Returned due to pending signal */ 261 if (pThis->cWaiters > 0)262 ASMAtomicDecU32(&pThis->cWaiters);263 299 rc = VERR_INTERRUPTED; 300 ASMAtomicDecU32(&pThis->cWaiters); 264 301 } 265 302 } … … 280 317 return rtSemEventWait(hEventSem, cMillies, true /* interruptible */); 281 318 } 319
Note:
See TracChangeset
for help on using the changeset viewer.