Changeset 33038 in vbox for trunk/src/VBox/Runtime/r0drv/nt
- Timestamp:
- Oct 11, 2010 11:55:01 AM (14 years ago)
- Location:
- trunk/src/VBox/Runtime/r0drv/nt
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/nt/semevent-r0drv-nt.cpp
r28800 r33038 5 5 6 6 /* 7 * Copyright (C) 2006-20 07Oracle Corporation7 * Copyright (C) 2006-2010 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 26 26 27 27 28 29 28 /******************************************************************************* 30 29 * Header Files * … … 32 31 #include "the-nt-kernel.h" 33 32 #include <iprt/semaphore.h> 34 #include <iprt/alloc.h> 33 34 #include <iprt/asm.h> 35 35 #include <iprt/assert.h> 36 #include <iprt/asm.h>37 36 #include <iprt/err.h> 37 #include <iprt/lockvalidator.h> 38 #include <iprt/mem.h> 39 #include <iprt/time.h> 38 40 39 41 #include "internal/magics.h" … … 50 52 /** Magic value (RTSEMEVENT_MAGIC). */ 51 53 uint32_t volatile u32Magic; 54 /** Reference counter. */ 55 uint32_t volatile cRefs; 52 56 /** The NT Event object. */ 53 57 KEVENT Event; … … 67 71 68 72 PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pThis)); 69 if (!pThis) 70 return VERR_NO_MEMORY; 71 72 pThis->u32Magic = RTSEMEVENT_MAGIC; 73 KeInitializeEvent(&pThis->Event, SynchronizationEvent, FALSE); 74 75 *phEventSem = pThis; 76 return VINF_SUCCESS; 73 if (pThis) 74 { 75 pThis->u32Magic = RTSEMEVENT_MAGIC; 76 pThis->cRefs = 1; 77 KeInitializeEvent(&pThis->Event, SynchronizationEvent, FALSE); 78 79 *phEventSem = pThis; 80 return VINF_SUCCESS; 81 } 82 return VERR_NO_MEMORY; 83 } 84 85 86 /** 87 * Retains a reference to the semaphore. 88 * 89 * @param pThis The semaphore to retain. 90 */ 91 DECLINLINE(void) rtR0SemEventNtRetain(PRTSEMEVENTINTERNAL pThis) 92 { 93 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs); 94 Assert(cRefs < 100000); NOREF(cRefs); 95 } 96 97 98 /** 99 * Releases a reference to the semaphore. 100 * 101 * @param pThis The semaphore to release 102 */ 103 DECLINLINE(void) rtR0SemEventNtRelease(PRTSEMEVENTINTERNAL pThis) 104 { 105 if (ASMAtomicDecU32(&pThis->cRefs) == 0) 106 RTMemFree(pThis); 77 107 } 78 108 … … 94 124 ASMAtomicIncU32(&pThis->u32Magic); 95 125 KeSetEvent(&pThis->Event, 0xfff, FALSE); 96 RTMemFree(pThis);126 rtR0SemEventNtRelease(pThis); 97 127 return VINF_SUCCESS; 98 128 } 99 129 100 130 101 RTDECL(int) 131 RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem) 102 132 { 103 133 /* … … 107 137 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 108 138 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE); 139 rtR0SemEventNtRetain(pThis); 109 140 110 141 /* … … 112 143 */ 113 144 KeSetEvent(&pThis->Event, 1, FALSE); 145 146 rtR0SemEventNtRelease(pThis); 114 147 return VINF_SUCCESS; 115 148 } 116 149 117 150 118 static int rtSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies, bool fInterruptible) 151 152 /** 153 * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug. 154 * 155 * @returns VBox status code. 156 * @param pThis The event semaphore. 157 * @param fFlags See RTSemEventWaitEx. 158 * @param uTimeout See RTSemEventWaitEx. 159 * @param pSrcPos The source code position of the wait. 160 */ 161 DECLINLINE(int) rtR0SemEventNtWait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout, 162 PCRTLOCKVALSRCPOS pSrcPos) 119 163 { 120 164 /* 121 165 * Validate input. 122 166 */ 123 PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem; 124 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 125 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE); 167 if (!pThis) 168 return VERR_INVALID_PARAMETER; 169 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); 170 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER); 171 rtR0SemEventNtRetain(pThis); 172 173 /* 174 * Convert the timeout to a relative one because KeWaitForSingleObject 175 * takes system time instead of interrupt time as input for absolute 176 * timeout specifications. So, we're best of by giving it relative time. 177 * 178 * Lazy bird converts uTimeout to relative nanoseconds and then to Nt time. 179 */ 180 if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE)) 181 { 182 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS) 183 uTimeout = uTimeout < UINT64_MAX / UINT32_C(1000000) * UINT32_C(1000000) 184 ? uTimeout * UINT32_C(1000000) 185 : UINT64_MAX; 186 if (uTimeout == UINT64_MAX) 187 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE; 188 else 189 { 190 if (fFlags & RTSEMWAIT_FLAGS_ABSOLUTE) 191 { 192 uint64_t u64Now = RTTimeSystemNanoTS(); 193 uTimeout = u64Now < uTimeout 194 ? uTimeout - u64Now 195 : 0; 196 } 197 } 198 } 199 126 200 127 201 /* … … 130 204 */ 131 205 NTSTATUS rcNt; 206 BOOLEAN fInterruptible = !!(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE); 132 207 KPROCESSOR_MODE WaitMode = fInterruptible ? UserMode : KernelMode; 133 if ( cMillies == RT_INDEFINITE_WAIT)208 if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE) 134 209 rcNt = KeWaitForSingleObject(&pThis->Event, Executive, WaitMode, fInterruptible, NULL); 135 210 else 136 211 { 137 212 LARGE_INTEGER Timeout; 138 Timeout.QuadPart = -(int64_t) cMillies * 10000;213 Timeout.QuadPart = -(int64_t)(uTimeout / 100); 139 214 rcNt = KeWaitForSingleObject(&pThis->Event, Executive, WaitMode, fInterruptible, &Timeout); 140 215 } 141 switch (rcNt) 142 { 143 case STATUS_SUCCESS: 144 if (pThis->u32Magic == RTSEMEVENT_MAGIC) 145 return VINF_SUCCESS; 146 return VERR_SEM_DESTROYED; 147 case STATUS_ALERTED: 148 return VERR_INTERRUPTED; 149 case STATUS_USER_APC: 150 return VERR_INTERRUPTED; 151 case STATUS_TIMEOUT: 152 return VERR_TIMEOUT; 153 default: 154 AssertMsgFailed(("pThis->u32Magic=%RX32 pThis=%p: wait returned %lx!\n", 155 pThis->u32Magic, pThis, (long)rcNt)); 156 return VERR_INTERNAL_ERROR; 157 } 158 } 159 160 161 RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies) 162 { 163 return rtSemEventWait(hEventSem, cMillies, false /* fInterruptible */); 164 } 165 166 167 RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies) 168 { 169 return rtSemEventWait(hEventSem, cMillies, true /* fInterruptible */); 170 } 171 216 int rc; 217 if (pThis->u32Magic == RTSEMEVENT_MAGIC) 218 { 219 switch (rcNt) 220 { 221 case STATUS_SUCCESS: 222 rc = VINF_SUCCESS; 223 break; 224 case STATUS_ALERTED: 225 rc = VERR_INTERRUPTED; 226 break; 227 case STATUS_USER_APC: 228 rc = VERR_INTERRUPTED; 229 break; 230 case STATUS_TIMEOUT: 231 rc = VERR_TIMEOUT; 232 break; 233 default: 234 AssertMsgFailed(("pThis->u32Magic=%RX32 pThis=%p: wait returned %lx!\n", 235 pThis->u32Magic, pThis, (long)rcNt)); 236 rc = VERR_INTERNAL_ERROR_4; 237 break; 238 } 239 } 240 else 241 rc = VERR_SEM_DESTROYED; 242 243 rtR0SemEventNtRelease(pThis); 244 return rc; 245 } 246 247 248 #undef RTSemEventWaitEx 249 RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout) 250 { 251 #ifndef RTSEMEVENT_STRICT 252 return rtR0SemEventNtWait(hEventSem, fFlags, uTimeout, NULL); 253 #else 254 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API(); 255 return rtR0SemEventNtWait(hEventSem, fFlags, uTimeout, &SrcPos); 256 #endif 257 } 258 259 260 RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout, 261 RTHCUINTPTR uId, RT_SRC_POS_DECL) 262 { 263 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API(); 264 return rtR0SemEventNtWait(hEventSem, fFlags, uTimeout, &SrcPos); 265 } 266 -
trunk/src/VBox/Runtime/r0drv/nt/semeventmulti-r0drv-nt.cpp
r28800 r33038 5 5 6 6 /* 7 * Copyright (C) 2006-20 07Oracle Corporation7 * Copyright (C) 2006-2010 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 31 31 #include "the-nt-kernel.h" 32 32 #include <iprt/semaphore.h> 33 #include <iprt/alloc.h> 33 34 #include <iprt/asm.h> 34 35 #include <iprt/assert.h> 35 #include <iprt/asm.h>36 36 #include <iprt/err.h> 37 #include <iprt/lockvalidator.h> 38 #include <iprt/mem.h> 39 #include <iprt/time.h> 37 40 38 41 #include "internal/magics.h" … … 49 52 /** Magic value (RTSEMEVENTMULTI_MAGIC). */ 50 53 uint32_t volatile u32Magic; 54 /** Reference counter. */ 55 uint32_t volatile cRefs; 51 56 /** The NT Event object. */ 52 57 KEVENT Event; … … 70 75 { 71 76 pThis->u32Magic = RTSEMEVENTMULTI_MAGIC; 77 pThis->cRefs = 1; 72 78 KeInitializeEvent(&pThis->Event, NotificationEvent, FALSE /* not signalled */); 73 79 … … 76 82 } 77 83 return VERR_NO_MEMORY; 84 } 85 86 87 /** 88 * Retains a reference to the semaphore. 89 * 90 * @param pThis The semaphore to retain. 91 */ 92 DECLINLINE(void) rtR0SemEventMultiNtRetain(PRTSEMEVENTMULTIINTERNAL pThis) 93 { 94 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs); 95 Assert(cRefs < 100000); NOREF(cRefs); 96 } 97 98 99 /** 100 * Releases a reference to the semaphore. 101 * 102 * @param pThis The semaphore to release 103 */ 104 DECLINLINE(void) rtR0SemEventMultiNtRelease(PRTSEMEVENTMULTIINTERNAL pThis) 105 { 106 if (ASMAtomicDecU32(&pThis->cRefs) == 0) 107 RTMemFree(pThis); 78 108 } 79 109 … … 95 125 ASMAtomicIncU32(&pThis->u32Magic); 96 126 KeSetEvent(&pThis->Event, 0xfff, FALSE); 97 RTMemFree(pThis);127 rtR0SemEventMultiNtRelease(pThis); 98 128 return VINF_SUCCESS; 99 129 } … … 110 140 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); 111 141 AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER); 142 rtR0SemEventMultiNtRetain(pThis); 112 143 113 144 /* … … 115 146 */ 116 147 KeSetEvent(&pThis->Event, 1, FALSE); 148 149 rtR0SemEventMultiNtRelease(pThis); 117 150 return VINF_SUCCESS; 118 151 } … … 129 162 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); 130 163 AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER); 164 rtR0SemEventMultiNtRetain(pThis); 131 165 132 166 /* … … 134 168 */ 135 169 KeResetEvent(&pThis->Event); 170 171 rtR0SemEventMultiNtRelease(pThis); 136 172 return VINF_SUCCESS; 137 173 } 138 174 139 175 140 static int rtSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies, bool fInterruptible) 141 { 142 /* 143 * Validate input. 144 */ 145 PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem; 176 /** 177 * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug. 178 * 179 * @returns VBox status code. 180 * @param pThis The event semaphore. 181 * @param fFlags See RTSemEventMultiWaitEx. 182 * @param uTimeout See RTSemEventMultiWaitEx. 183 * @param pSrcPos The source code position of the wait. 184 */ 185 DECLINLINE(int) rtR0SemEventMultiNtWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout, 186 PCRTLOCKVALSRCPOS pSrcPos) 187 { 188 /* 189 * Validate input. 190 */ 146 191 if (!pThis) 147 192 return VERR_INVALID_PARAMETER; 148 193 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); 149 194 AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER); 195 rtR0SemEventMultiNtRetain(pThis); 196 197 /* 198 * Convert the timeout to a relative one because KeWaitForSingleObject 199 * takes system time instead of interrupt time as input for absolute 200 * timeout specifications. So, we're best of by giving it relative time. 201 * 202 * Lazy bird converts uTimeout to relative nanoseconds and then to Nt time. 203 */ 204 if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE)) 205 { 206 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS) 207 uTimeout = uTimeout < UINT64_MAX / UINT32_C(1000000) * UINT32_C(1000000) 208 ? uTimeout * UINT32_C(1000000) 209 : UINT64_MAX; 210 if (uTimeout == UINT64_MAX) 211 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE; 212 else 213 { 214 if (fFlags & RTSEMWAIT_FLAGS_ABSOLUTE) 215 { 216 uint64_t u64Now = RTTimeSystemNanoTS(); 217 uTimeout = u64Now < uTimeout 218 ? uTimeout - u64Now 219 : 0; 220 } 221 } 222 } 223 150 224 151 225 /* … … 154 228 */ 155 229 NTSTATUS rcNt; 230 BOOLEAN fInterruptible = !!(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE); 156 231 KPROCESSOR_MODE WaitMode = fInterruptible ? UserMode : KernelMode; 157 if ( cMillies == RT_INDEFINITE_WAIT)232 if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE) 158 233 rcNt = KeWaitForSingleObject(&pThis->Event, Executive, WaitMode, fInterruptible, NULL); 159 234 else 160 235 { 161 236 LARGE_INTEGER Timeout; 162 Timeout.QuadPart = -(int64_t) cMillies * 10000;237 Timeout.QuadPart = -(int64_t)(uTimeout / 100); 163 238 rcNt = KeWaitForSingleObject(&pThis->Event, Executive, WaitMode, fInterruptible, &Timeout); 164 239 } 165 switch (rcNt) 166 { 167 case STATUS_SUCCESS: 168 if (pThis->u32Magic == RTSEMEVENTMULTI_MAGIC) 169 return VINF_SUCCESS; 170 return VERR_SEM_DESTROYED; 171 case STATUS_ALERTED: 172 return VERR_INTERRUPTED; 173 case STATUS_USER_APC: 174 return VERR_INTERRUPTED; 175 case STATUS_TIMEOUT: 176 return VERR_TIMEOUT; 177 default: 178 AssertMsgFailed(("pThis->u32Magic=%RX32 pThis=%p: wait returned %lx!\n", 179 pThis->u32Magic, pThis, (long)rcNt)); 180 return VERR_INTERNAL_ERROR; 181 } 182 } 183 184 185 RTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies) 186 { 187 return rtSemEventMultiWait(hEventMultiSem, cMillies, false /* fInterruptible */); 188 } 189 190 191 RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies) 192 { 193 return rtSemEventMultiWait(hEventMultiSem, cMillies, true /* fInterruptible */); 194 } 195 240 int rc; 241 if (pThis->u32Magic == RTSEMEVENTMULTI_MAGIC) 242 { 243 switch (rcNt) 244 { 245 case STATUS_SUCCESS: 246 rc = VINF_SUCCESS; 247 break; 248 case STATUS_ALERTED: 249 rc = VERR_INTERRUPTED; 250 break; 251 case STATUS_USER_APC: 252 rc = VERR_INTERRUPTED; 253 break; 254 case STATUS_TIMEOUT: 255 rc = VERR_TIMEOUT; 256 break; 257 default: 258 AssertMsgFailed(("pThis->u32Magic=%RX32 pThis=%p: wait returned %lx!\n", 259 pThis->u32Magic, pThis, (long)rcNt)); 260 rc = VERR_INTERNAL_ERROR_4; 261 break; 262 } 263 } 264 else 265 rc = VERR_SEM_DESTROYED; 266 267 rtR0SemEventMultiNtRelease(pThis); 268 return rc; 269 } 270 271 272 #undef RTSemEventMultiWaitEx 273 RTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout) 274 { 275 #ifndef RTSEMEVENT_STRICT 276 return rtR0SemEventMultiNtWait(hEventMultiSem, fFlags, uTimeout, NULL); 277 #else 278 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API(); 279 return rtR0SemEventMultiNtWait(hEventMultiSem, fFlags, uTimeout, &SrcPos); 280 #endif 281 } 282 283 284 RTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout, 285 RTHCUINTPTR uId, RT_SRC_POS_DECL) 286 { 287 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API(); 288 return rtR0SemEventMultiNtWait(hEventMultiSem, fFlags, uTimeout, &SrcPos); 289 } 290
Note:
See TracChangeset
for help on using the changeset viewer.