Changeset 92779 in vbox for trunk/src/VBox
- Timestamp:
- Dec 7, 2021 9:45:53 AM (3 years ago)
- Location:
- trunk/src/VBox/Runtime/r3/linux
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/linux/semevent-linux.cpp
r92777 r92779 65 65 #include <sys/time.h> 66 66 #include <sys/syscall.h> 67 #if 0 /* With 2.6.17 futex.h has become C++ unfriendly. */ 68 # include <linux/futex.h> 69 #else 70 # define FUTEX_WAIT 0 71 # define FUTEX_WAKE 1 72 # define FUTEX_WAIT_BITSET 9 /**< @since 2.6.25 - uses absolute timeout. */ 73 #endif 67 68 #include "semwait-linux.h" 74 69 75 70 … … 104 99 * Global Variables * 105 100 *********************************************************************************************************************************/ 101 /** Whether we can use FUTEX_WAIT_BITSET. */ 106 102 static int volatile g_fCanUseWaitBitSet = -1; 107 103 108 109 /**110 * Wrapper for the futex syscall.111 */112 static long sys_futex(uint32_t volatile *uaddr, int op, int val, struct timespec *utime, int32_t *uaddr2, int val3)113 {114 errno = 0;115 long rc = syscall(__NR_futex, uaddr, op, val, utime, uaddr2, val3);116 if (rc < 0)117 {118 Assert(rc == -1);119 rc = -errno;120 }121 return rc;122 }123 124 125 DECLINLINE(void) rtSemLinuxCheckForFutexWaitBitSetSlow(int volatile *pfCanUseWaitBitSet)126 {127 uint32_t uTestVar = UINT32_MAX;128 long rc = sys_futex(&uTestVar, FUTEX_WAIT_BITSET, UINT32_C(0xf0f0f0f0), NULL, NULL, UINT32_MAX);129 *pfCanUseWaitBitSet = rc == -EAGAIN;130 AssertMsg(rc == -ENOSYS || rc == -EAGAIN, ("%d\n", rc));131 }132 133 134 DECLINLINE(void) rtSemLinuxCheckForFutexWaitBitSet(int volatile *pfCanUseWaitBitSet)135 {136 if (*pfCanUseWaitBitSet != -1)137 { /* likely */ }138 else139 rtSemLinuxCheckForFutexWaitBitSetSlow(pfCanUseWaitBitSet);140 }141 104 142 105 -
trunk/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp
r90789 r92779 67 67 #include <sys/time.h> 68 68 #include <sys/syscall.h> 69 #if 0 /* With 2.6.17 futex.h has become C++ unfriendly. */ 70 # include <linux/futex.h> 71 #else 72 # define FUTEX_WAIT 0 73 # define FUTEX_WAKE 1 74 #endif 69 70 #include "semwait-linux.h" 75 71 76 72 … … 85 81 /** Magic value. */ 86 82 uint32_t volatile u32Magic; 87 /** The futex state variable .88 * -1 means signaled.89 * 0 means not signaled, no waiters. 90 * 1 means not signaled and that someone is waiting.91 */92 int32_t volatile iState; 83 /** The futex state variable, see RTSEMEVENTMULTI_LNX_XXX. */ 84 uint32_t volatile uState; 85 #ifdef RT_STRICT 86 /** Increased on every signalling call. */ 87 uint32_t volatile uSignalSerialNo; 88 #endif 93 89 #ifdef RTSEMEVENTMULTI_STRICT 94 90 /** Signallers. */ … … 100 96 101 97 102 /** 103 * Wrapper for the futex syscall. 104 */ 105 static long sys_futex(int32_t volatile *uaddr, int op, int val, struct timespec *utime, int32_t *uaddr2, int val3) 106 { 107 errno = 0; 108 long rc = syscall(__NR_futex, uaddr, op, val, utime, uaddr2, val3); 109 if (rc < 0) 110 { 111 Assert(rc == -1); 112 rc = -errno; 113 } 114 return rc; 115 } 98 /********************************************************************************************************************************* 99 * Defined Constants And Macros * 100 *********************************************************************************************************************************/ 101 /** @name RTSEMEVENTMULTI_LNX_XXX - state 102 * @{ */ 103 #define RTSEMEVENTMULTI_LNX_NOT_SIGNALED UINT32_C(0x00000000) 104 #define RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS UINT32_C(0x00000001) 105 #define RTSEMEVENTMULTI_LNX_SIGNALED UINT32_C(0x00000003) 106 /** @} */ 107 108 #define ASSERT_VALID_STATE(a_uState) \ 109 AssertMsg( (a_uState) == RTSEMEVENTMULTI_LNX_NOT_SIGNALED \ 110 || (a_uState) == RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS \ 111 || (a_uState) == RTSEMEVENTMULTI_LNX_SIGNALED, \ 112 (#a_uState "=%s\n", a_uState)) 113 114 115 /********************************************************************************************************************************* 116 * Global Variables * 117 *********************************************************************************************************************************/ 118 /** Whether we can use FUTEX_WAIT_BITSET. */ 119 static int volatile g_fCanUseWaitBitSet = -1; 116 120 117 121 … … 128 132 129 133 /* 134 * Make sure we know whether FUTEX_WAIT_BITSET works. 135 */ 136 rtSemLinuxCheckForFutexWaitBitSet(&g_fCanUseWaitBitSet); 137 #if defined(DEBUG_bird) && !defined(IN_GUEST) 138 Assert(g_fCanUseWaitBitSet == true); 139 #endif 140 141 /* 130 142 * Allocate semaphore handle. 131 143 */ … … 133 145 if (pThis) 134 146 { 135 pThis->u32Magic = RTSEMEVENTMULTI_MAGIC; 136 pThis->iState = 0; 147 pThis->u32Magic = RTSEMEVENTMULTI_MAGIC; 148 pThis->uState = RTSEMEVENTMULTI_LNX_NOT_SIGNALED; 149 #ifdef RT_STRICT 150 pThis->uSignalSerialNo = 0; 151 #endif 137 152 #ifdef RTSEMEVENTMULTI_STRICT 138 153 if (!pszNameFmt) … … 179 194 */ 180 195 ASMAtomicWriteU32(&pThis->u32Magic, RTSEMEVENTMULTI_MAGIC + 1); 181 if (ASMAtomicXchg S32(&pThis->iState, -1) == 1)182 { 183 sys_futex(&pThis-> iState, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);196 if (ASMAtomicXchgU32(&pThis->uState, RTSEMEVENTMULTI_LNX_SIGNALED) == RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS) 197 { 198 sys_futex(&pThis->uState, FUTEX_WAKE, INT_MAX, NULL, NULL, 0); 184 199 usleep(1000); 185 200 } … … 214 229 #endif 215 230 216 217 231 /* 218 232 * Signal it. 219 233 */ 220 int32_t iOld = ASMAtomicXchgS32(&pThis->iState, -1); 221 if (iOld > 0) 234 #ifdef RT_STRICT 235 ASMAtomicIncU32(&pThis->uSignalSerialNo); 236 #endif 237 uint32_t uOld = ASMAtomicXchgU32(&pThis->uState, RTSEMEVENTMULTI_LNX_SIGNALED); 238 if (uOld == RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS) 222 239 { 223 240 /* wake up sleeping threads. */ 224 long cWoken = sys_futex(&pThis-> iState, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);241 long cWoken = sys_futex(&pThis->uState, FUTEX_WAKE, INT_MAX, NULL, NULL, 0); 225 242 AssertMsg(cWoken >= 0, ("%ld\n", cWoken)); NOREF(cWoken); 226 243 } 227 A ssert(iOld == 0 || iOld == -1 || iOld == 1);244 ASSERT_VALID_STATE(uOld); 228 245 return VINF_SUCCESS; 229 246 } … … 239 256 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE); 240 257 #ifdef RT_STRICT 241 int32_t i = pThis->iState;242 A ssert(i == 0 || i == -1 || i == 1);258 uint32_t const uState = pThis->uState; 259 ASSERT_VALID_STATE(uState); 243 260 #endif 244 261 … … 246 263 * Reset it. 247 264 */ 248 ASMAtomicCmpXchg S32(&pThis->iState, 0, -1);265 ASMAtomicCmpXchgU32(&pThis->uState, RTSEMEVENTMULTI_LNX_NOT_SIGNALED, RTSEMEVENTMULTI_LNX_SIGNALED); 249 266 return VINF_SUCCESS; 250 267 } … … 267 284 * Quickly check whether it's signaled. 268 285 */ 269 int32_t iCur = ASMAtomicUoReadS32(&pThis->iState); 270 Assert(iCur == 0 || iCur == -1 || iCur == 1); 271 if (iCur == -1) 286 uint32_t uState = ASMAtomicUoReadU32(&pThis->uState); 287 if (uState == RTSEMEVENTMULTI_LNX_SIGNALED) 272 288 return VINF_SUCCESS; 289 ASSERT_VALID_STATE(uState); 273 290 274 291 /* … … 325 342 * threads waiting on the semaphore to keep things simple. 326 343 */ 327 iCur = ASMAtomicUoReadS32(&pThis->iState); 328 Assert(iCur == 0 || iCur == -1 || iCur == 1); 329 if ( iCur == 1 330 || ASMAtomicCmpXchgS32(&pThis->iState, 1, 0)) 344 uState = ASMAtomicUoReadU32(&pThis->uState); 345 if ( uState == RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS 346 || ( uState == RTSEMEVENTMULTI_LNX_NOT_SIGNALED 347 && ASMAtomicCmpXchgU32(&pThis->uState, RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS, 348 RTSEMEVENTMULTI_LNX_NOT_SIGNALED))) 331 349 { 332 350 /* adjust the relative timeout */ … … 348 366 } 349 367 #endif 368 #ifdef RT_STRICT 369 uint32_t const uPrevSignalSerialNo = ASMAtomicReadU32(&pThis->uSignalSerialNo); 370 #endif 350 371 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true); 351 long rc = sys_futex(&pThis-> iState, FUTEX_WAIT, 1, pTimeout, NULL, 0);372 long rc = sys_futex(&pThis->uState, FUTEX_WAIT, 1, pTimeout, NULL, 0); 352 373 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI); 353 374 if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC)) 354 375 return VERR_SEM_DESTROYED; 355 376 if (rc == 0) 377 { 378 Assert(uPrevSignalSerialNo != ASMAtomicReadU32(&pThis->uSignalSerialNo)); 356 379 return VINF_SUCCESS; 380 } 357 381 358 382 /* … … 381 405 } 382 406 } 383 else if ( iCur == -1)407 else if (uState == RTSEMEVENTMULTI_LNX_SIGNALED) 384 408 return VINF_SUCCESS; 409 else 410 ASSERT_VALID_STATE(uState); 385 411 } 386 412 }
Note:
See TracChangeset
for help on using the changeset viewer.