Changeset 30472 in vbox
- Timestamp:
- Jun 28, 2010 2:15:54 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/solaris/semevent-r0drv-solaris.c
r29284 r30472 57 57 /** The number of waiting threads. */ 58 58 uint32_t volatile cWaiters; 59 /** Set if the next waiter is to be signaled. */ 60 uint8_t volatile fPendingSignal; 61 /** Set if the event object is signaled. */ 62 uint8_t volatile fSignaled; 59 /** The number of signalled threads. */ 60 uint32_t volatile cWakeUp; 63 61 /** The number of threads referencing this object. */ 64 62 uint32_t volatile cRefs; … … 90 88 pThis->u32Magic = RTSEMEVENT_MAGIC; 91 89 pThis->cWaiters = 0; 90 pThis->cWakeUp = 0; 92 91 pThis->cRefs = 1; 93 pThis->fSignaled = 0;94 pThis->fPendingSignal = 0;95 92 mutex_init(&pThis->Mtx, "IPRT Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL)); 96 93 cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL); … … 178 175 } 179 176 180 if (pThis->cWaiters > 0) 177 ASMAtomicIncU32(&pThis->cWakeUp); 178 if (pThis->cWakeUp <= pThis->cWaiters) 181 179 { 182 180 /* … … 185 183 * 0 even when there are threads actually waiting. 186 184 */ 187 ASMAtomicDecU32(&pThis->cWaiters);188 ASMAtomicXchgU8(&pThis->fSignaled, true);189 185 cv_signal(&pThis->Cnd); 190 186 } 191 else192 ASMAtomicXchgU8(&pThis->fPendingSignal, true);193 187 194 188 mutex_exit(&pThis->Mtx); … … 196 190 RT_ASSERT_PREEMPT_CPUID(); 197 191 return VINF_SUCCESS; 192 } 193 194 195 static int rtSemEventWaitWorker(PRTSEMEVENTINTERNAL pThis, RTMSINTERVAL cMillies, bool fInterruptible) 196 { 197 /* 198 * Translate milliseconds into ticks and go to sleep. 199 */ 200 int rc = 0; 201 if (cMillies != RT_INDEFINITE_WAIT) 202 { 203 clock_t cTicks = drv_usectohz((clock_t)(cMillies * 1000L)); 204 clock_t cTimeout = ddi_get_lbolt(); 205 cTimeout += cTicks; 206 if (fInterruptible) 207 rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, cTimeout); 208 else 209 rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, cTimeout); 210 } 211 else 212 { 213 if (fInterruptible) 214 rc = cv_wait_sig(&pThis->Cnd, &pThis->Mtx); 215 else 216 { 217 cv_wait(&pThis->Cnd, &pThis->Mtx); 218 rc = 1; 219 } 220 } 221 222 return rc; 198 223 } 199 224 … … 212 237 ASMAtomicIncU32(&pThis->cRefs); 213 238 214 if (pThis-> fPendingSignal)239 if (pThis->cWakeUp > 0) 215 240 { 216 241 /* … … 219 244 */ 220 245 Assert(!pThis->cWaiters); 221 ASMAtomic XchgU8(&pThis->fPendingSignal, false);246 ASMAtomicWriteU32((uint32_t volatile *)&pThis->cWakeUp, 0); 222 247 rc = VINF_SUCCESS; 223 248 } … … 226 251 else 227 252 { 253 uint32_t cWakeUp = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->cWakeUp); 228 254 ASMAtomicIncU32(&pThis->cWaiters); 229 230 /* 231 * Translate milliseconds into ticks and go to sleep. 232 */ 233 if (cMillies != RT_INDEFINITE_WAIT) 255 for (;;) 234 256 { 235 clock_t cTicks = drv_usectohz((clock_t)(cMillies * 1000L)); 236 clock_t cTimeout = ddi_get_lbolt(); 237 cTimeout += cTicks; 238 if (fInterruptible) 239 rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, cTimeout); 240 else 241 rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, cTimeout); 242 } 243 else 244 { 245 if (fInterruptible) 246 rc = cv_wait_sig(&pThis->Cnd, &pThis->Mtx); 247 else 257 rc = rtSemEventWaitWorker(pThis, cMillies, fInterruptible); 258 if (rc > 0) 248 259 { 249 cv_wait(&pThis->Cnd, &pThis->Mtx); 250 rc = 1; 260 if (pThis->u32Magic != RTSEMEVENT_MAGIC) 261 { 262 /* 263 * We're being destroyed. 264 */ 265 ASMAtomicDecU32(&pThis->cWaiters); 266 rc = VERR_SEM_DESTROYED; 267 break; 268 } 269 else 270 { 271 uint32_t cWakeUpNow = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->cWakeUp); 272 if (cWakeUpNow > cWakeUp) 273 { 274 /* 275 * We've been signaled by RTSemEventSignal(), consume the wake up. 276 */ 277 ASMAtomicDecU32(&pThis->cWaiters); 278 ASMAtomicDecU32(&pThis->cWakeUp); 279 rc = VINF_SUCCESS; 280 break; 281 } 282 else 283 { 284 /* 285 * Premature wakeup due to some signal, go back to waiting. 286 */ 287 continue; 288 } 289 } 251 290 } 252 } 253 254 if (rc > 0) 255 { 256 if (pThis->u32Magic != RTSEMEVENT_MAGIC) 291 else if (rc == -1) 257 292 { 258 293 /* 259 * We're being destroyed.294 * Timeout reached. 260 295 */ 261 rc = VERR_SEM_DESTROYED;262 296 ASMAtomicDecU32(&pThis->cWaiters); 297 rc = VERR_TIMEOUT; 298 break; 263 299 } 264 300 else 265 301 { 266 if (pThis->fSignaled) 267 { 268 /* 269 * We've been signaled by RTSemEventSignal(). 270 */ 271 ASMAtomicXchgU8(&pThis->fSignaled, false); 272 rc = VINF_SUCCESS; 273 } 274 else 275 { 276 /* 277 * Premature wakeup due to some signal. 278 */ 279 rc = VERR_INTERRUPTED; 280 ASMAtomicDecU32(&pThis->cWaiters); 281 } 302 /* Returned due to pending signal */ 303 ASMAtomicDecU32(&pThis->cWaiters); 304 rc = VERR_INTERRUPTED; 305 break; 282 306 } 283 }284 else if (rc == -1)285 {286 /*287 * Timeout reached.288 */289 rc = VERR_TIMEOUT;290 ASMAtomicDecU32(&pThis->cWaiters);291 }292 else293 {294 /* Returned due to pending signal */295 rc = VERR_INTERRUPTED;296 ASMAtomicDecU32(&pThis->cWaiters);297 307 } 298 308 }
Note:
See TracChangeset
for help on using the changeset viewer.