Changeset 36392 in vbox for trunk/src/VBox/Runtime/r0drv/solaris
- Timestamp:
- Mar 24, 2011 11:20:37 AM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 70745
- Location:
- trunk/src/VBox/Runtime/r0drv/solaris
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/solaris/semevent-r0drv-solaris.c
r36282 r36392 65 65 /** The thread. */ 66 66 kthread_t *pThread; 67 /** Flag setwhen waking up the thread by signal or destroy. */68 bool volatilefWokenUp;67 /** Set to @c true when waking up the thread by signal or destroy. */ 68 uint32_t volatile fWokenUp; 69 69 } RTSEMEVENTSOLENTRY; 70 70 /** Pointer to waiter entry. */ … … 300 300 { 301 301 /* Do the wait and then recheck the conditions. */ 302 rtR0SemSolWaitDoIt(&Wait, &pThis->Cnd, &pThis->Mtx );302 rtR0SemSolWaitDoIt(&Wait, &pThis->Cnd, &pThis->Mtx, &Waiter.fWokenUp, false); 303 303 continue; 304 304 } -
trunk/src/VBox/Runtime/r0drv/solaris/semeventmulti-r0drv-solaris.c
r36286 r36392 305 305 { 306 306 /* Do the wait and then recheck the conditions. */ 307 rtR0SemSolWaitDoIt(&Wait, &pThis->Cnd, &pThis->Mtx );307 rtR0SemSolWaitDoIt(&Wait, &pThis->Cnd, &pThis->Mtx, &pThis->fStateAndGen, fOrgStateAndGen); 308 308 continue; 309 309 } -
trunk/src/VBox/Runtime/r0drv/solaris/semeventwait-r0drv-solaris.h
r36287 r36392 5 5 6 6 /* 7 * Copyright (C) 2006-201 0Oracle Corporation7 * Copyright (C) 2006-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 39 39 #define RTR0SEMSOLWAIT_RESOLUTION 50000 40 40 41 /** Disables the cyclic fallback code for old S10 installs - see @bugref{5342}. 42 * @todo Fixed by @bugref{5595}, can be reenabled after checking out 43 * CY_HIGH_LEVEL. */ 44 #define RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK 41 45 42 46 /** … … 60 64 /** Set if it's an indefinite wait. */ 61 65 bool fIndefinite; 66 /** Set if the waiting thread is ready to be woken up. 67 * Avoids false setrun() calls due to temporary mutex exits. */ 68 bool volatile fWantWakeup; 62 69 /** Set if we've already timed out. 63 70 * Set by rtR0SemSolWaitDoIt or rtR0SemSolWaitHighResTimeout, read by … … 70 77 /** The thread to wake up. */ 71 78 kthread_t *pThread; 72 #if 0 /* @bugref{5342} */79 #ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK 73 80 /** Cylic timer ID (used by the timeout callback). */ 74 81 cyclic_id_t idCy; … … 137 144 if ( ( (fFlags & (RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE)) 138 145 || pWait->cNsRelTimeout < UINT32_C(1000000000) / 100 /*Hz*/ * 4) 139 && g_pfnrtR0Sol_timeout_generic != NULL /* See @bugref{5342} */) 146 #ifdef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK 147 && g_pfnrtR0Sol_timeout_generic != NULL 148 #endif 149 ) 140 150 pWait->fHighRes = true; 141 151 else … … 161 171 } 162 172 173 pWait->fWantWakeup = false; 163 174 pWait->fTimedOut = false; 164 175 pWait->fInterrupted = false; … … 166 177 pWait->pThread = curthread; 167 178 pWait->pvMtx = NULL; 168 #if 0 /* @bugref{5342} */179 #ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK 169 180 pWait->idCy = CYCLIC_NONE; 170 181 #endif … … 174 185 175 186 176 #if 0 /* @bugref{5342} */187 #ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK 177 188 /** 178 189 * Cyclic timeout callback that sets the timeout indicator and wakes up the … … 191 202 before we wake it up. 192 203 Note: Trying to take the cpu_lock here doesn't work. */ 193 /** @todo LOCK ORDER INVERSION (pMtx & cpu_lock when arming the timer, here it's inverted).194 * Possible fix: Use the thread lock for sleep/wakeup race prevention195 * instead of the mutex associated with the cv/event. */196 204 mutex_enter(pMtx); 197 205 if (mutex_owner(&cpu_lock) == curthread) … … 200 208 pWait->idCy = CYCLIC_NONE; 201 209 } 210 bool const fWantWakeup = pWait->fWantWakeup; 202 211 ASMAtomicWriteBool(&pWait->fTimedOut, true); 203 212 mutex_exit(pMtx); 204 setrun(pThread); 213 214 if (fWantWakeup) 215 setrun(pThread); 205 216 } 206 217 } … … 224 235 before we wake it up. */ 225 236 mutex_enter(pMtx); 237 bool const fWantWakeup = pWait->fWantWakeup; 226 238 ASMAtomicWriteBool(&pWait->fTimedOut, true); 227 239 mutex_exit(pMtx); 228 setrun(pThread); 240 241 if (fWantWakeup) 242 setrun(pThread); 229 243 } 230 244 } … … 238 252 * @param pMtx The mutex related to the condition variable. 239 253 * The caller has entered this. 254 * @param pfState The state variable to check if have changed 255 * after leaving the mutex (spinlock). 256 * @param fCurState The current value of @a pfState. We'll return 257 * without sleeping if @a pfState doesn't hold 258 * this value after reacquiring the mutex. 240 259 * 241 260 * @remarks This must be call with the object mutex (spinlock) held. 242 261 */ 243 DECLINLINE(void) rtR0SemSolWaitDoIt(PRTR0SEMSOLWAIT pWait, kcondvar_t *pCnd, kmutex_t *pMtx) 262 DECLINLINE(void) rtR0SemSolWaitDoIt(PRTR0SEMSOLWAIT pWait, kcondvar_t *pCnd, kmutex_t *pMtx, 263 uint32_t volatile *pfState, uint32_t const fCurState) 244 264 { 245 265 union … … 251 271 /* 252 272 * Arm the timeout callback. 273 * 274 * We will have to leave the mutex (spinlock) when doing this because S10 275 * (didn't check S11) will not correctly preserve PIL across calls to 276 * timeout_generic() - @bugref{5595}. We do it for all timeout methods to 277 * be on the safe side, the nice sideeffect of which is that it solves the 278 * lock inversion problem found in @bugref{5342}. 253 279 */ 254 bool const fHasTimeout = !pWait->fIndefinite; 280 bool const fHasTimeout = !pWait->fIndefinite; 281 bool fGoToSleep = !fHasTimeout; 255 282 if (fHasTimeout) 256 283 { 284 pWait->fWantWakeup = false; /* only want fTimedOut */ 257 285 ASMAtomicWritePtr(&pWait->pvMtx, pMtx); /* atomic is paranoia */ 286 mutex_exit(pMtx); 258 287 259 288 if (pWait->fHighRes) 260 289 { 261 #if 0 /* @bugref{5342} */290 #ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK 262 291 if (g_pfnrtR0Sol_timeout_generic != NULL) 263 292 #endif … … 266 295 * High resolution timeout - arm a high resolution timeout callback 267 296 * for waking up the thread at the desired time. 268 *269 * Release and reacquire the mutex across calls to timeout_generic(), @bugref{5595}.270 297 */ 271 mutex_exit(pMtx);272 298 u.idCo = g_pfnrtR0Sol_timeout_generic(CALLOUT_REALTIME, rtR0SemSolWaitTimeout, pWait, 273 299 pWait->uNsAbsTimeout, RTR0SEMSOLWAIT_RESOLUTION, 274 300 CALLOUT_FLAG_ABSOLUTE); 275 mutex_enter(pMtx); 276 } 277 #if 0 /* @bugref{5342} */ 301 } 302 #ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK 278 303 else 279 304 { … … 303 328 * We're better off with our own callback like on the timeout man page, 304 329 * than calling cv_timedwait[_sig](). 305 *306 * Release and reacquire the mutex across calls to realtime_timeout(), @bugref{5595}.307 330 */ 308 mutex_exit(pMtx);309 331 u.idTom = realtime_timeout(rtR0SemSolWaitTimeout, pWait, pWait->u.lTimeout); 310 mutex_enter(pMtx); 311 } 332 } 333 334 /* 335 * Reacquire the mutex and check if the sleep condition still holds and 336 * that we didn't already time out. 337 */ 338 mutex_enter(pMtx); 339 pWait->fWantWakeup = true; 340 fGoToSleep = !ASMAtomicUoReadBool(&pWait->fTimedOut) 341 && ASMAtomicReadU32(pfState) == fCurState; 312 342 } 313 343 314 344 /* 315 * Check if the timeout has already fired in the time when the mutex was released.316 * Required since we release/reacquire the mutex, @bugref{5595}.345 * Do the waiting if that's still desirable. 346 * (rc > 0 - normal wake-up; rc == 0 - interruption; rc == -1 - timeout) 317 347 */ 318 if (ASMAtomicReadBool(&pWait->fTimedOut) == false) 319 { 320 /* 321 * Do the waiting. 322 * (rc > 0 - normal wake-up; rc == 0 - interruption; rc == -1 - timeout) 323 */ 348 if (fGoToSleep) 349 { 324 350 if (pWait->fInterruptible) 325 351 { … … 339 365 /* 340 366 * Remove the timeout callback. Drop the lock while we're doing that 341 * to reduce lock contention / deadlocks. (Too bad we are stuck with the 342 * cv_* API here, it's doing a little bit too much.) 367 * to reduce lock contention / deadlocks. Before dropping the lock, 368 * indicate that the callback shouldn't do anything. 369 * 370 * (Too bad we are stuck with the cv_* API here, it's doing a little 371 * bit too much.) 343 372 */ 344 373 if (fHasTimeout) 345 374 { 346 /* 347 * Invalidate the mutex pointer here so that if the timer fires just after we 348 * exit the mutex or has already fired and the callback is waiting on the mutex, 349 * we can simply ignore it in the callback as we've completed waiting. 350 */ 375 pWait->fWantWakeup = false; 351 376 ASMAtomicWritePtr(&pWait->pvMtx, NULL); 352 377 mutex_exit(pMtx); … … 354 379 if (pWait->fHighRes) 355 380 { 356 #if 0 /* @bugref{5342} */381 #ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK 357 382 if (g_pfnrtR0Sol_timeout_generic != NULL) 358 383 #endif 359 384 g_pfnrtR0Sol_untimeout_generic(u.idCo, 0 /*nowait*/); 360 #if 0 /* @bugref{5342} */385 #ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK 361 386 else 362 387 {
Note:
See TracChangeset
for help on using the changeset viewer.