Changeset 33033 in vbox for trunk/src/VBox/Runtime/r0drv/linux/semevent-r0drv-linux.c
- Timestamp:
- Oct 11, 2010 9:55:12 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/linux/semevent-r0drv-linux.c
r29661 r33033 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 … … 32 32 #include "internal/iprt.h" 33 33 #include <iprt/semaphore.h> 34 #include <iprt/alloc.h> 34 35 #include <iprt/asm.h> 35 36 #include <iprt/assert.h> 36 #include <iprt/asm.h>37 37 #include <iprt/err.h> 38 38 #include <iprt/lockvalidator.h> 39 #include <iprt/mem.h> 40 41 #include "waitqueue-r0drv-linux.h" 39 42 #include "internal/magics.h" 40 43 … … 52 55 /** The object status - !0 when signaled and 0 when reset. */ 53 56 uint32_t volatile fState; 57 /** Reference counter. */ 58 uint32_t volatile cRefs; 54 59 /** The wait queue. */ 55 60 wait_queue_head_t Head; … … 75 80 pThis->u32Magic = RTSEMEVENT_MAGIC; 76 81 pThis->fState = 0; 82 pThis->cRefs = 1; 77 83 init_waitqueue_head(&pThis->Head); 78 84 … … 81 87 } 82 88 RT_EXPORT_SYMBOL(RTSemEventCreate); 89 90 91 /** 92 * Retains a reference to the event semaphore. 93 * 94 * @param pThis The event semaphore. 95 */ 96 DECLINLINE(void) rtR0SemEventLnxRetain(PRTSEMEVENTINTERNAL pThis) 97 { 98 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs); 99 Assert(cRefs < 100000); NOREF(cRefs); 100 } 101 102 103 /** 104 * Releases a reference to the event semaphore. 105 * 106 * @param pThis The event semaphore. 107 */ 108 DECLINLINE(void) rtR0SemEventLnxRelease(PRTSEMEVENTINTERNAL pThis) 109 { 110 if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0)) 111 RTMemFree(pThis); 112 } 83 113 84 114 … … 92 122 return VINF_SUCCESS; 93 123 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE); 124 Assert(pThis->cRefs > 0); 94 125 95 126 /* … … 100 131 Assert(!waitqueue_active(&pThis->Head)); 101 132 wake_up_all(&pThis->Head); 102 RTMemFree(pThis);133 rtR0SemEventLnxRelease(pThis); 103 134 return VINF_SUCCESS; 104 135 } … … 114 145 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 115 146 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE); 147 rtR0SemEventLnxRetain(pThis); 116 148 117 149 /* … … 121 153 wake_up(&pThis->Head); 122 154 155 rtR0SemEventLnxRelease(pThis); 123 156 return VINF_SUCCESS; 124 157 } … … 127 160 128 161 /** 129 * Worker for RTSemEvent and RTSemEventNoResume.162 * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug. 130 163 * 131 164 * @returns VBox status code. 132 165 * @param pThis The event semaphore. 133 * @param cMillies The number of milliseconds to wait. 134 * @param fInterruptible Whether it's an interruptible wait or not. 135 */ 136 static int rtSemEventWait(PRTSEMEVENTINTERNAL pThis, RTMSINTERVAL cMillies, bool fInterruptible) 137 { 138 /* 139 * Ok wait for it. 140 */ 141 DEFINE_WAIT(Wait); 142 int rc = VINF_SUCCESS; 143 long lTimeout = cMillies == RT_INDEFINITE_WAIT ? MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(cMillies); 144 IPRT_DEBUG_SEMS_STATE(pThis, 'e'); 145 for (;;) 166 * @param fFlags See RTSemEventWaitEx. 167 * @param uTimeout See RTSemEventWaitEx. 168 * @param pSrcPos The source code position of the wait. 169 */ 170 static int rtR0SemEventLnxWait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout, 171 PCRTLOCKVALSRCPOS pSrcPos) 172 { 173 int rc; 174 175 /* 176 * Validate the input. 177 */ 178 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); 179 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER); 180 rtR0SemEventLnxRetain(pThis); 181 182 /* 183 * Try grab the event without setting up the wait. 184 */ 185 if ( 1 /** @todo check if there are someone waiting already - waitqueue_active, but then what do we do below? */ 186 && ASMAtomicCmpXchgU32(&pThis->fState, 0, 1)) 187 rc = VINF_SUCCESS; 188 else 146 189 { 147 /* make everything thru schedule_timeout() atomic scheduling wise. */ 148 prepare_to_wait(&pThis->Head, &Wait, fInterruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); 149 150 /* check the condition. */ 151 if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1)) 152 break; 153 154 /* check for pending signals. */ 155 if (fInterruptible && signal_pending(current)) 190 /* 191 * We have to wait. 192 */ 193 RTR0SEMLNXWAIT Wait; 194 rc = rtR0SemLnxWaitInit(&Wait, fFlags, uTimeout, &pThis->Head); 195 if (RT_SUCCESS(rc)) 156 196 { 157 rc = VERR_INTERRUPTED; 158 break; 159 } 160 161 /* wait */ 162 lTimeout = schedule_timeout(lTimeout); 163 164 after_wait(&Wait); 165 166 /* Check if someone destroyed the semaphore while we were waiting. */ 167 if (pThis->u32Magic != RTSEMEVENT_MAGIC) 168 { 169 rc = VERR_SEM_DESTROYED; 170 break; 171 } 172 173 /* check for timeout. */ 174 if (!lTimeout) 175 { 176 rc = VERR_TIMEOUT; 177 break; 197 IPRT_DEBUG_SEMS_STATE(pThis, 'E'); 198 for (;;) 199 { 200 /* The destruction test. */ 201 if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC)) 202 rc = VERR_SEM_DESTROYED; 203 else 204 { 205 rtR0SemLnxWaitPrepare(&Wait); 206 207 /* Check the exit conditions. */ 208 if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC)) 209 rc = VERR_SEM_DESTROYED; 210 else if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1)) 211 rc = VINF_SUCCESS; 212 else if (rtR0SemLnxWaitHasTimedOut(&Wait)) 213 rc = VERR_TIMEOUT; 214 else if (rtR0SemLnxWaitWasInterrupted(&Wait)) 215 rc = VERR_INTERRUPTED; 216 else 217 { 218 /* Do the wait and then recheck the conditions. */ 219 rtR0SemLnxWaitDoIt(&Wait); 220 continue; 221 } 222 } 223 break; 224 } 225 226 rtR0SemLnxWaitDelete(&Wait); 227 IPRT_DEBUG_SEMS_STATE_RC(pThis, 'E', rc); 178 228 } 179 229 } 180 230 181 finish_wait(&pThis->Head, &Wait); 182 IPRT_DEBUG_SEMS_STATE_RC(pThis, 'e', rc); 231 rtR0SemEventLnxRelease(pThis); 183 232 return rc; 184 233 } 185 234 186 235 187 RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies) 188 { 189 PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem; 190 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 191 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE); 192 193 if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1)) 194 return VINF_SUCCESS; 195 return rtSemEventWait(pThis, cMillies, false /* fInterruptible */); 196 } 197 RT_EXPORT_SYMBOL(RTSemEventWait); 198 199 200 RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies) 201 { 202 PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem; 203 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 204 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE); 205 206 if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1)) 207 return VINF_SUCCESS; 208 return rtSemEventWait(pThis, cMillies, true /* fInterruptible */); 209 } 210 RT_EXPORT_SYMBOL(RTSemEventWaitNoResume); 211 236 #undef RTSemEventWaitEx 237 RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout) 238 { 239 #ifndef RTSEMEVENT_STRICT 240 return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, NULL); 241 #else 242 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API(); 243 return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, &SrcPos); 244 #endif 245 } 246 RT_EXPORT_SYMBOL(RTSemEventWaitEx); 247 248 249 RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout, 250 RTHCUINTPTR uId, RT_SRC_POS_DECL) 251 { 252 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API(); 253 return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, &SrcPos); 254 } 255 RT_EXPORT_SYMBOL(RTSemEventWaitExDebug); 256
Note:
See TracChangeset
for help on using the changeset viewer.