Changeset 33144 in vbox
- Timestamp:
- Oct 14, 2010 10:11:36 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 66676
- Location:
- trunk/src/VBox
- Files:
-
- 1 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/solaris/mod.sh
r28800 r33144 67 67 $SUDO cp $DIR/vboxdrv $VBOXDRV_DIR/vboxdrv 68 68 $SUDO cp $script_dir/src/VBox/HostDrivers/Support/solaris/vboxdrv.conf $VBOXDRV_CONF_DIR/vboxdrv.conf 69 old_id=`/usr/sbin/modinfo | /usr/xpg4/bin/grep vbox | cut -f 1 -d ' ' | sort -n -r `69 old_id=`/usr/sbin/modinfo | /usr/xpg4/bin/grep vbox | grep -v vboxguest | grep -v vboxfs | cut -f 1 -d ' ' | sort -n -r ` 70 70 if test -n "$old_id"; then 71 71 echo "* unloading $old_id..." -
trunk/src/VBox/Runtime/Makefile.kmk
r33092 r33144 1640 1640 generic/RTAssertShouldPanic-generic.cpp \ 1641 1641 generic/RTLogWriteStdOut-stub-generic.cpp \ 1642 generic/RTSemEventWait-2-ex-generic.cpp \ 1643 generic/RTSemEventWaitNoResume-2-ex-generic.cpp \ 1642 1644 generic/RTSemEventMultiWait-2-ex-generic.cpp \ 1643 1645 generic/RTSemEventMultiWaitNoResume-2-ex-generic.cpp \ -
trunk/src/VBox/Runtime/r0drv/solaris/semevent-r0drv-solaris.c
r30935 r33144 39 39 #endif 40 40 #include <iprt/err.h> 41 #include <iprt/list.h> 42 #include <iprt/lockvalidator.h> 41 43 #include <iprt/mem.h> 42 44 #include <iprt/mp.h> 43 45 #include <iprt/thread.h> 44 46 #include "internal/magics.h" 47 #include "semeventwait-r0drv-solaris.h" 45 48 46 49 … … 48 51 * Structures and Typedefs * 49 52 *******************************************************************************/ 53 /** 54 * Waiter entry. Lives on the stack. 55 * 56 * @remarks Unfortunately, we cannot easily use cv_signal because we cannot 57 * distinguish between it and the spurious wakeups we get after fork. 58 * So, we keep an unprioritized FIFO with the sleeping threads. 59 */ 60 typedef struct RTSEMEVENTSOLENTRY 61 { 62 /** The list node. */ 63 RTLISTNODE Node; 64 /** The thread. */ 65 kthread_t *pThread; 66 /** Flag set when waking up the thread by signal or destroy. */ 67 bool volatile fWokenUp; 68 } RTSEMEVENTSOLENTRY; 69 /** Pointer to waiter entry. */ 70 typedef RTSEMEVENTSOLENTRY *PRTSEMEVENTSOLENTRY; 71 72 50 73 /** 51 74 * Solaris event semaphore. … … 59 82 /** Set if the object is signalled when there are no waiters. */ 60 83 bool fSignaled; 61 /** Object generation. 62 * This is incremented every time the object is signalled and used to 63 * check for spurious wake-ups. */ 64 uint32_t uSignalGen; 65 /** The number of waiting threads. */ 66 uint32_t cWaiters; 67 /** The number of signalled threads. */ 68 uint32_t cWakeUp; 84 /** List of waiting and woken up threads. */ 85 RTLISTNODE WaitList; 69 86 /** The Solaris mutex protecting this structure and pairing up the with the cv. */ 70 87 kmutex_t Mtx; … … 95 112 pThis->cRefs = 1; 96 113 pThis->fSignaled = false; 97 pThis->uSignalGen = 0; 98 pThis->cWaiters = 0; 99 pThis->cWakeUp = 0; 114 RTListInit(&pThis->WaitList); 100 115 mutex_init(&pThis->Mtx, "IPRT Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL)); 101 116 cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL); … … 106 121 107 122 123 /** 124 * Retain a reference to the semaphore. 125 * 126 * @param pThis The semaphore. 127 */ 128 DECLINLINE(void) rtR0SemEventSolRetain(PRTSEMEVENTINTERNAL pThis) 129 { 130 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs); 131 Assert(cRefs && cRefs < 100000); 132 } 133 134 135 /** 136 * The destruct. 137 * 138 * @param pThis The semaphore. 139 */ 140 static void rtR0SemEventSolDtor(PRTSEMEVENTINTERNAL pThis) 141 { 142 Assert(pThis->u32Magic != RTSEMEVENT_MAGIC); 143 cv_destroy(&pThis->Cnd); 144 mutex_destroy(&pThis->Mtx); 145 RTMemFree(pThis); 146 } 147 148 149 /** 150 * Release a reference, destroy the thing if necessary. 151 * 152 * @param pThis The semaphore. 153 */ 154 DECLINLINE(void) rtR0SemEventSolRelease(PRTSEMEVENTINTERNAL pThis) 155 { 156 if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0)) 157 rtR0SemEventSolDtor(pThis); 158 } 159 160 108 161 RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem) 109 162 { 163 /* 164 * Validate input. 165 */ 110 166 PRTSEMEVENTINTERNAL pThis = hEventSem; 111 167 if (pThis == NIL_RTSEMEVENT) … … 113 169 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 114 170 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE); 171 Assert(pThis->cRefs > 0); 115 172 RT_ASSERT_INTS_ON(); 116 173 117 174 mutex_enter(&pThis->Mtx); 118 175 119 ASMAtomicDecU32(&pThis->cRefs); 120 121 pThis->u32Magic = ~RTSEMEVENT_MAGIC; /* make the handle invalid */ 122 if (pThis->cWaiters > 0) 176 /* 177 * Invalidate the semaphore. 178 */ 179 ASMAtomicWriteU32(&pThis->u32Magic, ~RTSEMEVENT_MAGIC); 180 ASMAtomicWriteBool(&pThis->fSignaled, false); 181 182 /* 183 * Abort and wake up all threads. 184 */ 185 PRTSEMEVENTSOLENTRY pWaiter; 186 RTListForEach(&pThis->WaitList, pWaiter, RTSEMEVENTSOLENTRY, Node) 123 187 { 124 /* 125 * Signal all threads to destroy. 126 */ 127 cv_broadcast(&pThis->Cnd); 128 mutex_exit(&pThis->Mtx); 188 pWaiter->fWokenUp = true; 129 189 } 130 else if (pThis->cRefs == 0) 131 { 132 /* 133 * We're the last thread referencing this object, destroy it. 134 */ 135 mutex_exit(&pThis->Mtx); 136 cv_destroy(&pThis->Cnd); 137 mutex_destroy(&pThis->Mtx); 138 RTMemFree(pThis); 139 } 140 else 141 { 142 /* 143 * There are other threads still referencing this object, last one cleans up. 144 */ 145 mutex_exit(&pThis->Mtx); 146 } 190 cv_broadcast(&pThis->Cnd); 191 192 /* 193 * Release the reference from RTSemEventCreateEx. 194 */ 195 mutex_exit(&pThis->Mtx); 196 rtR0SemEventSolRelease(pThis); 147 197 148 198 return VINF_SUCCESS; … … 150 200 151 201 152 RTDECL(int) 202 RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem) 153 203 { 154 204 PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem; … … 158 208 RT_ASSERT_INTS_ON(); 159 209 160 /* 161 * If we're in interrupt context we need to unpin the underlying current 162 * thread as this could lead to a deadlock (see #4259 for the full explanation) 163 * 164 * Note! This assumes nobody is using the RTThreadPreemptDisable in an 165 * interrupt context and expects it to work right. The swtch will 166 * result in a voluntary preemption. To fix this, we would have to 167 * do our own counting in RTThreadPreemptDisable/Restore like we do 168 * on systems which doesn't do preemption (OS/2, linux, ...) and 169 * check whether preemption was disabled via RTThreadPreemptDisable 170 * or not and only call swtch if RTThreadPreemptDisable wasn't called. 171 */ 172 int fAcquired = mutex_tryenter(&pThis->Mtx); 173 if (!fAcquired) 210 rtR0SemEventSolRetain(pThis); 211 rtR0SemSolWaitEnterMutexWithUnpinningHack(&pThis->Mtx); 212 213 /* 214 * Wake up one thread. 215 */ 216 ASMAtomicWriteBool(&pThis->fSignaled, true); 217 218 PRTSEMEVENTSOLENTRY pWaiter; 219 RTListForEach(&pThis->WaitList, pWaiter, RTSEMEVENTSOLENTRY, Node) 174 220 { 175 if ( curthread->t_intr && getpil() < DISP_LEVEL)221 if (!pWaiter->fWokenUp) 176 222 { 177 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;178 RTThreadPreemptDisable(&PreemptState);179 preempt();180 RTThreadPreemptRestore(&PreemptState);223 pWaiter->fWokenUp = true; 224 setrun(pWaiter->pThread); 225 ASMAtomicWriteBool(&pThis->fSignaled, false); 226 break; 181 227 } 182 mutex_enter(&pThis->Mtx);183 228 } 184 229 185 /*186 * If there are more waiting threads, wake them up. Otherwise leave the187 * semaphore in the signalled state.188 */189 pThis->cWakeUp++;190 if (pThis->cWakeUp <= pThis->cWaiters) /** @todo r=bird: see cWakeup = 0 below. */191 {192 cv_signal(&pThis->Cnd);193 pThis->uSignalGen++;194 }195 else196 pThis->fSignaled = true;197 198 230 mutex_exit(&pThis->Mtx); 231 rtR0SemEventSolRelease(pThis); 199 232 200 233 RT_ASSERT_PREEMPT_CPUID(); … … 203 236 204 237 205 static int rtSemEventWaitWorker(PRTSEMEVENTINTERNAL pThis, RTMSINTERVAL cMillies, bool fInterruptible) 206 { 207 /* 208 * Translate milliseconds into ticks and go to sleep. 209 */ 210 int rc = 0; 211 if (cMillies != RT_INDEFINITE_WAIT) 212 { 213 clock_t cTicks = drv_usectohz((clock_t)(cMillies * 1000L)); 214 clock_t cTimeout = ddi_get_lbolt(); 215 cTimeout += cTicks; 216 if (fInterruptible) 217 rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, cTimeout); 218 else 219 rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, cTimeout); 220 } 238 /** 239 * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug. 240 * 241 * @returns VBox status code. 242 * @param pThis The event semaphore. 243 * @param fFlags See RTSemEventWaitEx. 244 * @param uTimeout See RTSemEventWaitEx. 245 * @param pSrcPos The source code position of the wait. 246 */ 247 static int rtR0SemEventSolWait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout, 248 PCRTLOCKVALSRCPOS pSrcPos) 249 { 250 /* 251 * Validate the input. 252 */ 253 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); 254 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER); 255 AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER); 256 257 rtR0SemEventSolRetain(pThis); 258 mutex_enter(&pThis->Mtx); 259 260 /* 261 * In the signaled state? 262 */ 263 int rc; 264 if (ASMAtomicCmpXchgBool(&pThis->fSignaled, false, true)) 265 rc = VINF_SUCCESS; 221 266 else 222 267 { 223 if (fInterruptible) 224 rc = cv_wait_sig(&pThis->Cnd, &pThis->Mtx); 225 else 268 /* 269 * We have to wait. 270 */ 271 RTR0SEMSOLWAIT Wait; 272 rc = rtR0SemSolWaitInit(&Wait, fFlags, uTimeout); 273 if (RT_SUCCESS(rc)) 226 274 { 227 cv_wait(&pThis->Cnd, &pThis->Mtx); 228 rc = 1; 275 RTSEMEVENTSOLENTRY Waiter; 276 Waiter.pThread = curthread; 277 Waiter.fWokenUp = false; 278 RTListAppend(&pThis->WaitList, &Waiter.Node); 279 280 for (;;) 281 { 282 /* The destruction test. */ 283 if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC)) 284 rc = VERR_SEM_DESTROYED; 285 else 286 { 287 /* Check the exit conditions. */ 288 if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC)) 289 rc = VERR_SEM_DESTROYED; 290 else if (Waiter.fWokenUp) 291 rc = VINF_SUCCESS; 292 else if (rtR0SemSolWaitHasTimedOut(&Wait)) 293 rc = VERR_TIMEOUT; 294 else if (rtR0SemSolWaitWasInterrupted(&Wait)) 295 rc = VERR_INTERRUPTED; 296 else 297 { 298 /* Do the wait and then recheck the conditions. */ 299 rtR0SemSolWaitDoIt(&Wait, &pThis->Cnd, &pThis->Mtx); 300 continue; 301 } 302 } 303 break; 304 } 305 306 rtR0SemSolWaitDelete(&Wait); 307 RTListNodeRemove(&Waiter.Node); 229 308 } 230 309 } 231 310 311 mutex_exit(&pThis->Mtx); 312 rtR0SemEventSolRelease(pThis); 232 313 return rc; 233 314 } 234 315 235 316 236 static int rtSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies, bool fInterruptible) 237 { 238 int rc; 239 PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem; 240 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 241 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE); 242 if (cMillies) 243 RT_ASSERT_PREEMPTIBLE(); 244 245 mutex_enter(&pThis->Mtx); 246 247 ASMAtomicIncU32(&pThis->cRefs); 248 249 if (pThis->fSignaled) 250 { 251 /* 252 * The last signal occurred without any waiters and now we're the first thread 253 * waiting for the event signal. So no real need to wait for one. 254 */ 255 Assert(!pThis->cWaiters); 256 pThis->fSignaled = false; 257 /** @todo r=bird: This will get out of whack if someone is in the 258 * process of waking up (waiting to be scheduled). Further 259 * more, a race between a cv_signal and a 260 * timeout/interruption may cause wakeups to go unconsumed. 261 * Not sure how we could easily deal with this rigth now... */ 262 pThis->cWakeUp = 0; 263 rc = VINF_SUCCESS; 264 } 265 else if (!cMillies) 266 rc = VERR_TIMEOUT; 267 else 268 { 269 pThis->cWaiters++; 270 /* This loop is only for continuing after a spurious wake-up. */ 271 for (;;) 272 { 273 uint32_t const uSignalGenBeforeWait = pThis->uSignalGen; 274 rc = rtSemEventWaitWorker(pThis, cMillies, fInterruptible); 275 if (rc > 0) 276 { 277 if (pThis->u32Magic == RTSEMEVENT_MAGIC) 278 { 279 if (pThis->uSignalGen != uSignalGenBeforeWait) 280 { 281 /* We've been signaled by cv_signal(), consume the wake up. */ 282 --pThis->cWakeUp; /** @todo r=bird: May cause underflow, see above. */ 283 rc = VINF_SUCCESS; 284 } 285 else 286 /* Spurious wakeup due to some signal, go back to waiting. */ 287 continue; 288 } 289 else 290 /* We're being destroyed. */ 291 rc = VERR_SEM_DESTROYED; 292 } 293 else if (rc == -1) 294 /* Timeout reached. */ 295 rc = VERR_TIMEOUT; 296 else 297 /* Returned due to pending signal */ 298 rc = VERR_INTERRUPTED; 299 300 break; 301 } 302 --pThis->cWaiters; 303 } 304 305 if (!ASMAtomicDecU32(&pThis->cRefs)) 306 { 307 Assert(RT_FAILURE_NP(rc)); 308 mutex_exit(&pThis->Mtx); 309 cv_destroy(&pThis->Cnd); 310 mutex_destroy(&pThis->Mtx); 311 RTMemFree(pThis); 312 return rc; 313 } 314 315 mutex_exit(&pThis->Mtx); 316 return rc; 317 } 318 319 320 RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies) 321 { 322 return rtSemEventWait(hEventSem, cMillies, false /* not interruptible */); 323 } 324 325 326 RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies) 327 { 328 return rtSemEventWait(hEventSem, cMillies, true /* interruptible */); 329 } 330 317 #undef RTSemEventWaitEx 318 RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout) 319 { 320 #ifndef RTSEMEVENT_STRICT 321 return rtR0SemEventSolWait(hEventSem, fFlags, uTimeout, NULL); 322 #else 323 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API(); 324 return rtR0SemEventSolWait(hEventSem, fFlags, uTimeout, &SrcPos); 325 #endif 326 } 327 328 329 RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout, 330 RTHCUINTPTR uId, RT_SRC_POS_DECL) 331 { 332 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API(); 333 return rtR0SemEventSolWait(hEventSem, fFlags, uTimeout, &SrcPos); 334 } 335 -
trunk/src/VBox/Runtime/r0drv/solaris/semeventmulti-r0drv-solaris.c
r33092 r33144 45 45 #include <iprt/time.h> 46 46 #include "internal/magics.h" 47 #include "semeventwait-r0drv-solaris.h" 47 48 48 49 … … 195 196 RT_ASSERT_INTS_ON(); 196 197 rtR0SemEventMultiSolRetain(pThis); 197 198 /* 199 * If we're in interrupt context we need to unpin the underlying current 200 * thread as this could lead to a deadlock (see #4259 for the full explanation) 201 * 202 * Note! See remarks about preemption in RTSemEventSignal. 203 */ 204 int fAcquired = mutex_tryenter(&pThis->Mtx); 205 if (!fAcquired) 206 { 207 if (curthread->t_intr && getpil() < DISP_LEVEL) 208 { 209 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; 210 RTThreadPreemptDisable(&PreemptState); 211 preempt(); 212 RTThreadPreemptRestore(&PreemptState); 213 } 214 mutex_enter(&pThis->Mtx); 215 } 198 rtR0SemSolWaitEnterMutexWithUnpinningHack(&pThis->Mtx); 216 199 Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC); 217 200 … … 244 227 VERR_INVALID_HANDLE); 245 228 RT_ASSERT_INTS_ON(); 229 246 230 rtR0SemEventMultiSolRetain(pThis); 247 248 /* 249 * If we're in interrupt context we need to unpin the underlying current 250 * thread as this could lead to a deadlock (see #4259 for the full explanation) 251 * 252 * Note! See remarks about preemption in RTSemEventSignal. 253 */ 254 int fAcquired = mutex_tryenter(&pThis->Mtx); 255 if (!fAcquired) 256 { 257 if (curthread->t_intr && getpil() < DISP_LEVEL) 258 { 259 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; 260 RTThreadPreemptDisable(&PreemptState); 261 preempt(); 262 RTThreadPreemptRestore(&PreemptState); 263 } 264 mutex_enter(&pThis->Mtx); 265 } 231 rtR0SemSolWaitEnterMutexWithUnpinningHack(&pThis->Mtx); 266 232 Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC); 267 233 … … 272 238 273 239 mutex_exit(&pThis->Mtx); 274 275 240 rtR0SemEventMultiSolRelease(pThis); 241 276 242 RT_ASSERT_PREEMPT_CPUID(); 277 243 return VINF_SUCCESS; 278 244 } 279 280 /* -------- Move to header ---------- */281 282 typedef struct RTR0SEMSOLWAIT283 {284 /** The absolute timeout given as nano seconds since the start of the285 * monotonic clock. */286 uint64_t uNsAbsTimeout;287 /** The timeout in nano seconds relative to the start of the wait. */288 uint64_t cNsRelTimeout;289 /** The native timeout value. */290 union291 {292 /** The timeout (abs lbolt) when fHighRes is false. */293 clock_t lTimeout;294 } u;295 /** Set if we use high resolution timeouts. */296 bool fHighRes;297 /** Set if it's an indefinite wait. */298 bool fIndefinite;299 /** Set if we've already timed out.300 * Set by rtR0SemSolWaitDoIt or rtR0SemSolWaitHighResTimeout, read by301 * rtR0SemSolWaitHasTimedOut. */302 bool volatile fTimedOut;303 /** Whether the wait was interrupted. */304 bool fInterrupted;305 /** Interruptible or uninterruptible wait. */306 bool fInterruptible;307 /** The thread to wake up. */308 kthread_t *pThread;309 /** Cylic timer ID (used by the timeout callback). */310 cyclic_id_t idCy;311 } RTR0SEMSOLWAIT;312 /** Pointer to a solaris semaphore wait structure. */313 typedef RTR0SEMSOLWAIT *PRTR0SEMSOLWAIT;314 315 316 /**317 * Initializes a wait.318 *319 * The caller MUST check the wait condition BEFORE calling this function or the320 * timeout logic will be flawed.321 *322 * @returns VINF_SUCCESS or VERR_TIMEOUT.323 * @param pWait The wait structure.324 * @param fFlags The wait flags.325 * @param uTimeout The timeout.326 * @param pWaitQueue The wait queue head.327 */328 DECLINLINE(int) rtR0SemSolWaitInit(PRTR0SEMSOLWAIT pWait, uint32_t fFlags, uint64_t uTimeout)329 {330 /*331 * Process the flags and timeout.332 */333 if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))334 {335 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS)336 uTimeout = uTimeout < UINT64_MAX / UINT32_C(1000000) * UINT32_C(1000000)337 ? uTimeout * UINT32_C(1000000)338 : UINT64_MAX;339 if (uTimeout == UINT64_MAX)340 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;341 else342 {343 uint64_t u64Now;344 if (fFlags & RTSEMWAIT_FLAGS_RELATIVE)345 {346 if (uTimeout == 0)347 return VERR_TIMEOUT;348 349 u64Now = RTTimeSystemNanoTS();350 pWait->cNsRelTimeout = uTimeout;351 pWait->uNsAbsTimeout = u64Now + uTimeout;352 if (pWait->uNsAbsTimeout < u64Now) /* overflow */353 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;354 }355 else356 {357 u64Now = RTTimeSystemNanoTS();358 if (u64Now >= uTimeout)359 return VERR_TIMEOUT;360 361 pWait->cNsRelTimeout = uTimeout - u64Now;362 pWait->uNsAbsTimeout = uTimeout;363 }364 }365 }366 367 if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))368 {369 pWait->fIndefinite = false;370 if ( (fFlags & (RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE))371 || pWait->cNsRelTimeout < UINT32_C(1000000000) / 100 /*Hz*/ * 4)372 pWait->fHighRes = true;373 else374 {375 #if 1376 uint64_t cTicks = NSEC_TO_TICK_ROUNDUP(uTimeout);377 #else378 uint64_t cTicks = drv_usectohz((clock_t)(uTimeout / 1000));379 #endif380 if (cTicks >= LONG_MAX)381 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;382 else383 {384 pWait->u.lTimeout = ddi_get_lbolt() + cTicks;385 pWait->fHighRes = false;386 }387 }388 }389 390 if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)391 {392 pWait->fIndefinite = true;393 pWait->fHighRes = false;394 pWait->uNsAbsTimeout = UINT64_MAX;395 pWait->cNsRelTimeout = UINT64_MAX;396 pWait->u.lTimeout = LONG_MAX;397 }398 399 pWait->fTimedOut = false;400 pWait->fInterrupted = false;401 pWait->fInterruptible = !!(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE);402 pWait->pThread = curthread;403 pWait->idCy = CYCLIC_NONE;404 405 return VINF_SUCCESS;406 }407 408 409 /**410 * Cyclic timeout callback that sets the timeout indicator and wakes up the411 * waiting thread.412 *413 * @param pvUser The wait structure.414 */415 static void rtR0SemSolWaitHighResTimeout(void *pvUser)416 {417 PRTR0SEMSOLWAIT pWait = (PRTR0SEMSOLWAIT)pvUser;418 kthread_t *pThread = pWait->pThread;419 if (VALID_PTR(pThread)) /* paranoia */420 {421 /* Note: Trying to take the cpu_lock here doesn't work. */422 if (mutex_owner(&cpu_lock) == curthread)423 {424 cyclic_remove(pWait->idCy);425 pWait->idCy = CYCLIC_NONE;426 }427 ASMAtomicWriteBool(&pWait->fTimedOut, true);428 setrun(pThread);429 }430 }431 432 433 /**434 * Do the actual wait.435 *436 * @param pWait The wait structure.437 * @param pCnd The condition variable to wait on.438 * @param pMtx The mutex related to the condition variable.439 * The caller has entered this.440 */441 DECLINLINE(void) rtR0SemSolWaitDoIt(PRTR0SEMSOLWAIT pWait, kcondvar_t *pCnd, kmutex_t *pMtx)442 {443 int rc = 1;444 if (pWait->fIndefinite)445 {446 /*447 * No timeout - easy.448 */449 if (pWait->fInterruptible)450 rc = cv_wait_sig(pCnd, pMtx);451 else452 cv_wait(pCnd, pMtx);453 }454 else if (pWait->fHighRes)455 {456 /*457 * High resolution timeout - arm a one-shot cyclic for waking up458 * the thread at the desired time.459 */460 cyc_handler_t Cyh;461 Cyh.cyh_arg = pWait;462 Cyh.cyh_func = rtR0SemSolWaitHighResTimeout;463 Cyh.cyh_level = CY_LOW_LEVEL; /// @todo try CY_LOCK_LEVEL and CY_HIGH_LEVEL?464 465 cyc_time_t Cyt;466 Cyt.cyt_when = pWait->uNsAbsTimeout;467 Cyt.cyt_interval = UINT64_C(1000000000) * 60;468 469 mutex_enter(&cpu_lock);470 pWait->idCy = cyclic_add(&Cyh, &Cyt);471 mutex_exit(&cpu_lock);472 473 if (pWait->fInterruptible)474 rc = cv_wait_sig(pCnd, pMtx);475 else476 cv_wait(pCnd, pMtx);477 478 mutex_enter(&cpu_lock);479 if (pWait->idCy != CYCLIC_NONE)480 {481 cyclic_remove(pWait->idCy);482 pWait->idCy = CYCLIC_NONE;483 }484 mutex_exit(&cpu_lock);485 }486 else487 {488 /*489 * Normal timeout.490 */491 if (pWait->fInterruptible)492 rc = cv_timedwait_sig(pCnd, pMtx, pWait->u.lTimeout);493 else494 rc = cv_timedwait(pCnd, pMtx, pWait->u.lTimeout);495 }496 497 /* Above zero means normal wake-up. */498 if (rc > 0)499 return;500 501 /* Timeout is signalled by -1. */502 if (rc == -1)503 pWait->fTimedOut = true;504 /* Interruption is signalled by 0. */505 else506 {507 AssertMsg(rc == 0, ("rc=%d\n", rc));508 pWait->fInterrupted = true;509 }510 }511 512 513 /**514 * Checks if a solaris wait was interrupted.515 *516 * @returns true / false517 * @param pWait The wait structure.518 * @remarks This shall be called before the first rtR0SemSolWaitDoIt().519 */520 DECLINLINE(bool) rtR0SemSolWaitWasInterrupted(PRTR0SEMSOLWAIT pWait)521 {522 return pWait->fInterrupted;523 }524 525 526 /**527 * Checks if a solaris wait has timed out.528 *529 * @returns true / false530 * @param pWait The wait structure.531 */532 DECLINLINE(bool) rtR0SemSolWaitHasTimedOut(PRTR0SEMSOLWAIT pWait)533 {534 return pWait->fTimedOut;535 }536 537 538 /**539 * Deletes a solaris wait.540 *541 * @param pWait The wait structure.542 */543 DECLINLINE(void) rtR0SemSolWaitDelete(PRTR0SEMSOLWAIT pWait)544 {545 pWait->pThread = NULL;546 }547 548 /* -------- End ---------- */549 245 550 246
Note:
See TracChangeset
for help on using the changeset viewer.