Changeset 6738 in vbox for trunk/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp
- Timestamp:
- Feb 1, 2008 9:45:27 PM (17 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp
r6734 r6738 1 1 /* $Id$ */ 2 2 /** @file 3 * innotek Portable Runtime - Semaphores, POSIX.3 * innotek Portable Runtime - Multiple Release Event Semaphore, POSIX. 4 4 */ 5 5 … … 39 39 #include <sys/time.h> 40 40 41 #ifdef RT_OS_DARWIN42 # define pthread_yield() pthread_yield_np()43 #endif44 45 #ifdef RT_OS_SOLARIS46 # include <sched.h>47 # define pthread_yield() sched_yield()48 #endif49 50 41 51 42 /******************************************************************************* 52 43 * Structures and Typedefs * 53 44 *******************************************************************************/ 54 55 /** Internal representation of the POSIX implementation of an Event semaphore. 45 /** Posix internal representation of a Mutex Multi semaphore. 56 46 * The POSIX implementation uses a mutex and a condition variable to implement 57 * the automatic reset event semaphore semantics. 58 * 59 * This must be identical to RTSEMEVENTMULTIINTERNAL! 60 */ 61 struct RTSEMEVENTINTERNAL 47 * the automatic reset event semaphore semantics. */ 48 struct RTSEMEVENTMULTIINTERNAL 62 49 { 63 50 /** pthread condition. */ … … 72 59 }; 73 60 74 /** Posix internal representation of a Mutex Multi semaphore. 75 * This must be identical to RTSEMEVENTINTERNAL! */ 76 struct RTSEMEVENTMULTIINTERNAL 77 { 78 /** pthread condition. */ 79 pthread_cond_t Cond; 80 /** pthread mutex which protects the condition and the event state. */ 81 pthread_mutex_t Mutex; 82 /** The state of the semaphore. 83 * This is operated while owning mutex and using atomic updating. */ 84 volatile uint32_t u32State; 85 /** Number of waiters. */ 86 volatile uint32_t cWaiters; 87 }; 88 89 /** The valus of the u32State variable in a RTSEMEVENTINTERNAL and RTSEMEVENTMULTIINTERNAL. 61 /** The valus of the u32State variable in RTSEMEVENTMULTIINTERNAL. 90 62 * @{ */ 91 63 /** The object isn't initialized. */ 92 #define EVENT _STATE_UNINITIALIZED 064 #define EVENTMULTI_STATE_UNINITIALIZED 0 93 65 /** The semaphore is is signaled. */ 94 #define EVENT _STATE_SIGNALED 0xff00ff0066 #define EVENTMULTI_STATE_SIGNALED 0xff00ff00 95 67 /** The semaphore is not signaled. */ 96 #define EVENT _STATE_NOT_SIGNALED 0x00ff00ff68 #define EVENTMULTI_STATE_NOT_SIGNALED 0x00ff00ff 97 69 /** @} */ 98 70 99 71 100 /** Posix internal representation of a Mutex semaphore. */101 struct RTSEMMUTEXINTERNAL102 {103 /** pthread mutex. */104 pthread_mutex_t Mutex;105 /** The owner of the mutex. */106 volatile pthread_t Owner;107 /** Nesting count. */108 volatile uint32_t cNesting;109 };110 111 /** Posix internal representation of a read-write semaphore. */112 struct RTSEMRWINTERNAL113 {114 /** pthread rwlock. */115 pthread_rwlock_t RWLock;116 /** Variable to check if initialized.117 * 0 is uninitialized, ~0 is inititialized. */118 volatile unsigned uCheck;119 /** The write owner of the lock. */120 volatile pthread_t WROwner;121 };122 123 72 124 73 /** 125 * Validate an Eventsemaphore handle passed to one of the interface.74 * Validate an event multi semaphore handle passed to one of the interface. 126 75 * 127 76 * @returns true if valid. 128 77 * @returns false if invalid. 129 * @param p IntEventSemPointer to the event semaphore to validate.78 * @param pThis Pointer to the event semaphore to validate. 130 79 */ 131 inline bool rtsemEvent Valid(struct RTSEMEVENTINTERNAL *pIntEventSem)132 { 133 if ((uintptr_t)p IntEventSem< 0x10000)80 inline bool rtsemEventMultiValid(struct RTSEMEVENTMULTIINTERNAL *pThis) 81 { 82 if ((uintptr_t)pThis < 0x10000) 134 83 return false; 135 84 136 uint32_t u32 = p IntEventSem->u32State; /* this is volatile, so a explicit read like this is needed. */137 if ( u32 != EVENT _STATE_NOT_SIGNALED138 && u32 != EVENT _STATE_SIGNALED)85 uint32_t u32 = pThis->u32State; /* this is volatile, so a explicit read like this is needed. */ 86 if ( u32 != EVENTMULTI_STATE_NOT_SIGNALED 87 && u32 != EVENTMULTI_STATE_SIGNALED) 139 88 return false; 140 89 … … 143 92 144 93 145 RTDECL(int) RTSemEvent Create(PRTSEMEVENT pEventSem)94 RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI pEventMultiSem) 146 95 { 147 96 int rc; … … 150 99 * Allocate semaphore handle. 151 100 */ 152 struct RTSEMEVENT INTERNAL *pIntEventSem = (struct RTSEMEVENTINTERNAL *)RTMemAlloc(sizeof(struct RTSEMEVENTINTERNAL));153 if (p IntEventSem)101 struct RTSEMEVENTMULTIINTERNAL *pThis = (struct RTSEMEVENTMULTIINTERNAL *)RTMemAlloc(sizeof(struct RTSEMEVENTMULTIINTERNAL)); 102 if (pThis) 154 103 { 155 104 /* … … 160 109 if (!rc) 161 110 { 162 rc = pthread_cond_init(&p IntEventSem->Cond, &CondAttr);111 rc = pthread_cond_init(&pThis->Cond, &CondAttr); 163 112 if (!rc) 164 113 { … … 170 119 if (!rc) 171 120 { 172 rc = pthread_mutex_init(&p IntEventSem->Mutex, &MutexAttr);121 rc = pthread_mutex_init(&pThis->Mutex, &MutexAttr); 173 122 if (!rc) 174 123 { … … 176 125 pthread_condattr_destroy(&CondAttr); 177 126 178 ASMAtomicXchgU32(&p IntEventSem->u32State, EVENT_STATE_NOT_SIGNALED);179 ASMAtomicXchgU32(&p IntEventSem->cWaiters, 0);180 181 *pEvent Sem = pIntEventSem;127 ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_NOT_SIGNALED); 128 ASMAtomicXchgU32(&pThis->cWaiters, 0); 129 130 *pEventMultiSem = pThis; 182 131 return VINF_SUCCESS; 183 132 } 133 184 134 pthread_mutexattr_destroy(&MutexAttr); 185 135 } 186 pthread_cond_destroy(&p IntEventSem->Cond);136 pthread_cond_destroy(&pThis->Cond); 187 137 } 188 138 pthread_condattr_destroy(&CondAttr); … … 190 140 191 141 rc = RTErrConvertFromErrno(rc); 192 RTMemFree(p IntEventSem);142 RTMemFree(pThis); 193 143 } 194 144 else … … 196 146 197 147 return rc; 198 } 199 200 201 RTDECL(int) RTSemEventDestroy(RTSEMEVENT EventSem) 148 149 } 150 151 152 RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI EventMultiSem) 202 153 { 203 154 /* 204 155 * Validate handle. 205 156 */ 206 if (!rtsemEvent Valid(EventSem))207 { 208 AssertMsgFailed(("Invalid handle %p!\n", Event Sem));157 if (!rtsemEventMultiValid(EventMultiSem)) 158 { 159 AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem)); 209 160 return VERR_INVALID_HANDLE; 210 161 } … … 212 163 /* 213 164 * Abort all waiters forcing them to return failure. 214 * 215 */ 216 struct RTSEMEVENTINTERNAL *pIntEventSem = EventSem; 165 */ 166 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem; 217 167 int rc; 218 168 for (int i = 30; i > 0; i--) 219 169 { 220 ASMAtomicXchgU32(&p IntEventSem->u32State, EVENT_STATE_UNINITIALIZED);221 rc = pthread_cond_destroy(&p IntEventSem->Cond);170 ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_UNINITIALIZED); 171 rc = pthread_cond_destroy(&pThis->Cond); 222 172 if (rc != EBUSY) 223 173 break; 224 pthread_cond_broadcast(&p IntEventSem->Cond);174 pthread_cond_broadcast(&pThis->Cond); 225 175 usleep(1000); 226 176 } while (rc == EBUSY); 227 177 if (rc) 228 178 { 229 AssertMsgFailed(("Failed to destroy event sem %p, rc=%d.\n", Event Sem, rc));179 AssertMsgFailed(("Failed to destroy event sem %p, rc=%d.\n", EventMultiSem, rc)); 230 180 return RTErrConvertFromErrno(rc); 231 181 } … … 237 187 for (int i = 30; i > 0; i--) 238 188 { 239 rc = pthread_mutex_destroy(&p IntEventSem->Mutex);189 rc = pthread_mutex_destroy(&pThis->Mutex); 240 190 if (rc != EBUSY) 241 191 break; … … 244 194 if (rc) 245 195 { 246 AssertMsgFailed(("Failed to destroy event sem %p, rc=%d. (mutex)\n", Event Sem, rc));196 AssertMsgFailed(("Failed to destroy event sem %p, rc=%d. (mutex)\n", EventMultiSem, rc)); 247 197 return RTErrConvertFromErrno(rc); 248 198 } … … 251 201 * Free the semaphore memory and be gone. 252 202 */ 253 RTMemFree(p IntEventSem);203 RTMemFree(pThis); 254 204 return VINF_SUCCESS; 255 205 } 256 206 257 207 258 RTDECL(int) RTSemEvent Signal(RTSEMEVENT EventSem)208 RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI EventMultiSem) 259 209 { 260 210 /* 261 211 * Validate input. 262 212 */ 263 if (!rtsemEvent Valid(EventSem))264 { 265 AssertMsgFailed(("Invalid handle %p!\n", Event Sem));213 if (!rtsemEventMultiValid(EventMultiSem)) 214 { 215 AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem)); 266 216 return VERR_INVALID_HANDLE; 267 217 } … … 270 220 * Lock the mutex semaphore. 271 221 */ 272 struct RTSEMEVENT INTERNAL *pIntEventSem = EventSem;273 int rc = pthread_mutex_lock(&p IntEventSem->Mutex);274 if (rc) 275 { 276 AssertMsgFailed(("Failed to lock event sem %p, rc=%d.\n", Event Sem, rc));222 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem; 223 int rc = pthread_mutex_lock(&pThis->Mutex); 224 if (rc) 225 { 226 AssertMsgFailed(("Failed to lock event sem %p, rc=%d.\n", EventMultiSem, rc)); 277 227 return RTErrConvertFromErrno(rc); 278 228 } … … 281 231 * Check the state. 282 232 */ 283 if (p IntEventSem->u32State == EVENT_STATE_NOT_SIGNALED)284 { 285 ASMAtomicXchgU32(&p IntEventSem->u32State, EVENT_STATE_SIGNALED);286 rc = pthread_cond_signal(&p IntEventSem->Cond);287 AssertMsg(!rc, ("Failed to signal event sem %p, rc=%d.\n", Event Sem, rc));288 } 289 else if (p IntEventSem->u32State == EVENT_STATE_SIGNALED)290 { 291 rc = pthread_cond_signal(&p IntEventSem->Cond); /* give'm another kick... */292 AssertMsg(!rc, ("Failed to signal event sem %p, rc=%d. (2)\n", Event Sem, rc));233 if (pThis->u32State == EVENTMULTI_STATE_NOT_SIGNALED) 234 { 235 ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_SIGNALED); 236 rc = pthread_cond_signal(&pThis->Cond); 237 AssertMsg(!rc, ("Failed to signal event sem %p, rc=%d.\n", EventMultiSem, rc)); 238 } 239 else if (pThis->u32State == EVENTMULTI_STATE_SIGNALED) 240 { 241 rc = pthread_cond_signal(&pThis->Cond); /* give'm another kick... */ 242 AssertMsg(!rc, ("Failed to signal event sem %p, rc=%d. (2)\n", EventMultiSem, rc)); 293 243 } 294 244 else … … 298 248 * Release the mutex and return. 299 249 */ 300 int rc2 = pthread_mutex_unlock(&p IntEventSem->Mutex);301 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc=%d.\n", Event Sem, rc));250 int rc2 = pthread_mutex_unlock(&pThis->Mutex); 251 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc=%d.\n", EventMultiSem, rc)); 302 252 if (rc) 303 253 return RTErrConvertFromErrno(rc); … … 309 259 310 260 311 static int rtSemEventWait(RTSEMEVENT EventSem, unsigned cMillies, bool fAutoResume)261 RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI EventMultiSem) 312 262 { 313 263 /* 314 264 * Validate input. 315 265 */ 316 if (!rtsemEvent Valid(EventSem))317 { 318 AssertMsgFailed(("Invalid handle %p!\n", Event Sem));266 if (!rtsemEventMultiValid(EventMultiSem)) 267 { 268 AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem)); 319 269 return VERR_INVALID_HANDLE; 320 270 } 321 271 322 272 /* 273 * Lock the mutex semaphore. 274 */ 275 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem; 276 int rc = pthread_mutex_lock(&pThis->Mutex); 277 if (rc) 278 { 279 AssertMsgFailed(("Failed to lock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); 280 return RTErrConvertFromErrno(rc); 281 } 282 283 /* 284 * Check the state. 285 */ 286 if (pThis->u32State == EVENTMULTI_STATE_SIGNALED) 287 ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_NOT_SIGNALED); 288 else if (pThis->u32State != EVENTMULTI_STATE_NOT_SIGNALED) 289 rc = VERR_SEM_DESTROYED; 290 291 /* 292 * Release the mutex and return. 293 */ 294 rc = pthread_mutex_unlock(&pThis->Mutex); 295 if (rc) 296 { 297 AssertMsgFailed(("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); 298 return RTErrConvertFromErrno(rc); 299 } 300 301 return VINF_SUCCESS; 302 303 } 304 305 306 static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies, bool fAutoResume) 307 { 308 /* 309 * Validate input. 310 */ 311 if (!rtsemEventMultiValid(EventMultiSem)) 312 { 313 AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem)); 314 return VERR_INVALID_HANDLE; 315 } 316 317 /* 323 318 * Timed or indefinite wait? 324 319 */ 325 struct RTSEMEVENT INTERNAL *pIntEventSem = EventSem;320 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem; 326 321 if (cMillies == RT_INDEFINITE_WAIT) 327 322 { 328 /* for fairness, yield before going to sleep. */ 329 if ( ASMAtomicIncU32(&pIntEventSem->cWaiters) > 1 330 && pIntEventSem->u32State == EVENT_STATE_SIGNALED) 331 pthread_yield(); 332 333 /* take mutex */ 334 int rc = pthread_mutex_lock(&pIntEventSem->Mutex); 323 /* take mutex */ 324 int rc = pthread_mutex_lock(&pThis->Mutex); 335 325 if (rc) 336 326 { 337 ASMAtomicDecU32(&pIntEventSem->cWaiters); 338 AssertMsgFailed(("Failed to lock event sem %p, rc=%d.\n", EventSem, rc)); 327 AssertMsgFailed(("Failed to lock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); 339 328 return RTErrConvertFromErrno(rc); 340 329 } 330 ASMAtomicIncU32(&pThis->cWaiters); 341 331 342 332 for (;;) 343 333 { 344 334 /* check state. */ 345 if (pIntEventSem->u32State == EVENT_STATE_SIGNALED) 346 { 347 ASMAtomicXchgU32(&pIntEventSem->u32State, EVENT_STATE_NOT_SIGNALED); 348 ASMAtomicDecU32(&pIntEventSem->cWaiters); 349 rc = pthread_mutex_unlock(&pIntEventSem->Mutex); 350 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", EventSem, rc)); NOREF(rc); 335 if (pThis->u32State == EVENTMULTI_STATE_SIGNALED) 336 { 337 ASMAtomicDecU32(&pThis->cWaiters); 338 rc = pthread_mutex_unlock(&pThis->Mutex); 339 AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); NOREF(rc); 351 340 return VINF_SUCCESS; 352 341 } 353 if (p IntEventSem->u32State == EVENT_STATE_UNINITIALIZED)354 { 355 rc = pthread_mutex_unlock(&p IntEventSem->Mutex);356 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", EventSem, rc)); NOREF(rc);342 if (pThis->u32State == EVENTMULTI_STATE_UNINITIALIZED) 343 { 344 rc = pthread_mutex_unlock(&pThis->Mutex); 345 AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); NOREF(rc); 357 346 return VERR_SEM_DESTROYED; 358 347 } 359 348 360 349 /* wait */ 361 rc = pthread_cond_wait(&p IntEventSem->Cond, &pIntEventSem->Mutex);350 rc = pthread_cond_wait(&pThis->Cond, &pThis->Mutex); 362 351 if (rc) 363 352 { 364 AssertMsgFailed(("Failed to wait on event sem %p, rc=%d.\n", EventSem, rc));365 ASMAtomicDecU32(&p IntEventSem->cWaiters);366 int rc2 = pthread_mutex_unlock(&p IntEventSem->Mutex);367 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc=%d.\n", EventSem, rc2)); NOREF(rc2);353 AssertMsgFailed(("Failed to wait on event multi sem %p, rc=%d.\n", EventMultiSem, rc)); 354 ASMAtomicDecU32(&pThis->cWaiters); 355 int rc2 = pthread_mutex_unlock(&pThis->Mutex); 356 AssertMsg(!rc2, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc2)); NOREF(rc2); 368 357 return RTErrConvertFromErrno(rc); 369 358 } … … 395 384 } 396 385 397 /* for fairness, yield before going to sleep. */398 if (ASMAtomicIncU32(&pIntEventSem->cWaiters) > 1)399 pthread_yield();400 401 386 /* take mutex */ 402 387 #ifdef RT_OS_DARWIN 403 int rc = pthread_mutex_lock(&p IntEventSem->Mutex);388 int rc = pthread_mutex_lock(&pThis->Mutex); 404 389 #else 405 int rc = pthread_mutex_timedlock(&p IntEventSem->Mutex, &ts);390 int rc = pthread_mutex_timedlock(&pThis->Mutex, &ts); 406 391 #endif 407 392 if (rc) 408 393 { 409 ASMAtomicDecU32(&pIntEventSem->cWaiters); 410 AssertMsg(rc == ETIMEDOUT, ("Failed to lock event sem %p, rc=%d.\n", EventSem, rc)); 394 AssertMsg(rc == ETIMEDOUT, ("Failed to lock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); 411 395 return RTErrConvertFromErrno(rc); 412 396 } 397 ASMAtomicIncU32(&pThis->cWaiters); 413 398 414 399 for (;;) 415 400 { 416 401 /* check state. */ 417 if (pIntEventSem->u32State == EVENT_STATE_SIGNALED) 418 { 419 ASMAtomicXchgU32(&pIntEventSem->u32State, EVENT_STATE_NOT_SIGNALED); 420 ASMAtomicDecU32(&pIntEventSem->cWaiters); 421 rc = pthread_mutex_unlock(&pIntEventSem->Mutex); 422 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", EventSem, rc)); NOREF(rc); 423 return VINF_SUCCESS; 424 } 425 if (pIntEventSem->u32State == EVENT_STATE_UNINITIALIZED) 426 { 427 rc = pthread_mutex_unlock(&pIntEventSem->Mutex); 428 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", EventSem, rc)); NOREF(rc); 429 return VERR_SEM_DESTROYED; 430 } 431 432 /* wait */ 433 rc = pthread_cond_timedwait(&pIntEventSem->Cond, &pIntEventSem->Mutex, &ts); 434 if (rc && (rc != EINTR || !fAutoResume)) /* according to SuS this function shall not return EINTR, but linux man page says differently. */ 435 { 436 AssertMsg(rc == ETIMEDOUT, ("Failed to wait on event sem %p, rc=%d.\n", EventSem, rc)); 437 ASMAtomicDecU32(&pIntEventSem->cWaiters); 438 int rc2 = pthread_mutex_unlock(&pIntEventSem->Mutex); 439 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc2=%d.\n", EventSem, rc2)); NOREF(rc2); 440 return RTErrConvertFromErrno(rc); 441 } 442 } /* for (;;) */ 443 } 444 } 445 446 447 RTDECL(int) RTSemEventWait(RTSEMEVENT EventSem, unsigned cMillies) 448 { 449 int rc = rtSemEventWait(EventSem, cMillies, true); 450 Assert(rc != VERR_INTERRUPTED); 451 return rc; 452 } 453 454 455 RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT EventSem, unsigned cMillies) 456 { 457 return rtSemEventWait(EventSem, cMillies, false); 458 } 459 460 461 462 463 464 465 /** 466 * Validate an event multi semaphore handle passed to one of the interface. 467 * 468 * @returns true if valid. 469 * @returns false if invalid. 470 * @param pIntEventMultiSem Pointer to the event semaphore to validate. 471 */ 472 inline bool rtsemEventMultiValid(struct RTSEMEVENTMULTIINTERNAL *pIntEventMultiSem) 473 { 474 if ((uintptr_t)pIntEventMultiSem < 0x10000) 475 return false; 476 477 uint32_t u32 = pIntEventMultiSem->u32State; /* this is volatile, so a explicit read like this is needed. */ 478 if ( u32 != EVENT_STATE_NOT_SIGNALED 479 && u32 != EVENT_STATE_SIGNALED) 480 return false; 481 482 return true; 483 } 484 485 486 RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI pEventMultiSem) 487 { 488 /* the code and the structure is identical with other type for this function. */ 489 return RTSemEventCreate((PRTSEMEVENT)pEventMultiSem); 490 } 491 492 493 RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI EventMultiSem) 494 { 495 /* the code and the structure is identical with other type for this function. */ 496 return RTSemEventDestroy((RTSEMEVENT)EventMultiSem); 497 } 498 499 500 RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI EventMultiSem) 501 { 502 /* the code and the structure is identical with other type for this function. */ 503 return RTSemEventSignal((RTSEMEVENT)EventMultiSem); 504 } 505 506 507 RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI EventMultiSem) 508 { 509 /* 510 * Validate input. 511 */ 512 if (!rtsemEventMultiValid(EventMultiSem)) 513 { 514 AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem)); 515 return VERR_INVALID_HANDLE; 516 } 517 518 /* 519 * Lock the mutex semaphore. 520 */ 521 struct RTSEMEVENTMULTIINTERNAL *pIntEventMultiSem = EventMultiSem; 522 int rc = pthread_mutex_lock(&pIntEventMultiSem->Mutex); 523 if (rc) 524 { 525 AssertMsgFailed(("Failed to lock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); 526 return RTErrConvertFromErrno(rc); 527 } 528 529 /* 530 * Check the state. 531 */ 532 if (pIntEventMultiSem->u32State == EVENT_STATE_SIGNALED) 533 ASMAtomicXchgU32(&pIntEventMultiSem->u32State, EVENT_STATE_NOT_SIGNALED); 534 else if (pIntEventMultiSem->u32State != EVENT_STATE_NOT_SIGNALED) 535 rc = VERR_SEM_DESTROYED; 536 537 /* 538 * Release the mutex and return. 539 */ 540 rc = pthread_mutex_unlock(&pIntEventMultiSem->Mutex); 541 if (rc) 542 { 543 AssertMsgFailed(("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); 544 return RTErrConvertFromErrno(rc); 545 } 546 547 return VINF_SUCCESS; 548 549 } 550 551 552 static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies, bool fAutoResume) 553 { 554 /* 555 * Validate input. 556 */ 557 if (!rtsemEventMultiValid(EventMultiSem)) 558 { 559 AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem)); 560 return VERR_INVALID_HANDLE; 561 } 562 563 /* 564 * Timed or indefinite wait? 565 */ 566 struct RTSEMEVENTMULTIINTERNAL *pIntEventMultiSem = EventMultiSem; 567 if (cMillies == RT_INDEFINITE_WAIT) 568 { 569 /* take mutex */ 570 int rc = pthread_mutex_lock(&pIntEventMultiSem->Mutex); 571 if (rc) 572 { 573 AssertMsgFailed(("Failed to lock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); 574 return RTErrConvertFromErrno(rc); 575 } 576 ASMAtomicIncU32(&pIntEventMultiSem->cWaiters); 577 578 for (;;) 579 { 580 /* check state. */ 581 if (pIntEventMultiSem->u32State == EVENT_STATE_SIGNALED) 582 { 583 ASMAtomicDecU32(&pIntEventMultiSem->cWaiters); 584 rc = pthread_mutex_unlock(&pIntEventMultiSem->Mutex); 402 if (pThis->u32State == EVENTMULTI_STATE_SIGNALED) 403 { 404 ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_NOT_SIGNALED); 405 ASMAtomicDecU32(&pThis->cWaiters); 406 rc = pthread_mutex_unlock(&pThis->Mutex); 585 407 AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); NOREF(rc); 586 408 return VINF_SUCCESS; 587 409 } 588 if (p IntEventMultiSem->u32State == EVENT_STATE_UNINITIALIZED)589 { 590 rc = pthread_mutex_unlock(&p IntEventMultiSem->Mutex);410 if (pThis->u32State == EVENTMULTI_STATE_UNINITIALIZED) 411 { 412 rc = pthread_mutex_unlock(&pThis->Mutex); 591 413 AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); NOREF(rc); 592 414 return VERR_SEM_DESTROYED; … … 594 416 595 417 /* wait */ 596 rc = pthread_cond_wait(&pIntEventMultiSem->Cond, &pIntEventMultiSem->Mutex); 597 if (rc) 598 { 599 AssertMsgFailed(("Failed to wait on event multi sem %p, rc=%d.\n", EventMultiSem, rc)); 600 ASMAtomicDecU32(&pIntEventMultiSem->cWaiters); 601 int rc2 = pthread_mutex_unlock(&pIntEventMultiSem->Mutex); 602 AssertMsg(!rc2, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc2)); NOREF(rc2); 603 return RTErrConvertFromErrno(rc); 604 } 605 } 606 } 607 else 608 { 609 /* 610 * Get current time and calc end of wait time. 611 */ 612 struct timespec ts = {0,0}; 613 #ifdef RT_OS_DARWIN 614 struct timeval tv = {0,0}; 615 gettimeofday(&tv, NULL); 616 ts.tv_sec = tv.tv_sec; 617 ts.tv_nsec = tv.tv_usec * 1000; 618 #else 619 clock_gettime(CLOCK_REALTIME, &ts); 620 #endif 621 if (cMillies != 0) 622 { 623 ts.tv_nsec += (cMillies % 1000) * 1000000; 624 ts.tv_sec += cMillies / 1000; 625 if (ts.tv_nsec >= 1000000000) 626 { 627 ts.tv_nsec -= 1000000000; 628 ts.tv_sec++; 629 } 630 } 631 632 /* take mutex */ 633 #ifdef RT_OS_DARWIN 634 int rc = pthread_mutex_lock(&pIntEventMultiSem->Mutex); 635 #else 636 int rc = pthread_mutex_timedlock(&pIntEventMultiSem->Mutex, &ts); 637 #endif 638 if (rc) 639 { 640 AssertMsg(rc == ETIMEDOUT, ("Failed to lock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); 641 return RTErrConvertFromErrno(rc); 642 } 643 ASMAtomicIncU32(&pIntEventMultiSem->cWaiters); 644 645 for (;;) 646 { 647 /* check state. */ 648 if (pIntEventMultiSem->u32State == EVENT_STATE_SIGNALED) 649 { 650 ASMAtomicXchgU32(&pIntEventMultiSem->u32State, EVENT_STATE_NOT_SIGNALED); 651 ASMAtomicDecU32(&pIntEventMultiSem->cWaiters); 652 rc = pthread_mutex_unlock(&pIntEventMultiSem->Mutex); 653 AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); NOREF(rc); 654 return VINF_SUCCESS; 655 } 656 if (pIntEventMultiSem->u32State == EVENT_STATE_UNINITIALIZED) 657 { 658 rc = pthread_mutex_unlock(&pIntEventMultiSem->Mutex); 659 AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); NOREF(rc); 660 return VERR_SEM_DESTROYED; 661 } 662 663 /* wait */ 664 rc = pthread_cond_timedwait(&pIntEventMultiSem->Cond, &pIntEventMultiSem->Mutex, &ts); 418 rc = pthread_cond_timedwait(&pThis->Cond, &pThis->Mutex, &ts); 665 419 if (rc && (rc != EINTR || !fAutoResume)) /* according to SuS this function shall not return EINTR, but linux man page says differently. */ 666 420 { 667 421 AssertMsg(rc == ETIMEDOUT, ("Failed to wait on event multi sem %p, rc=%d.\n", EventMultiSem, rc)); 668 ASMAtomicDecU32(&p IntEventMultiSem->cWaiters);669 int rc2 = pthread_mutex_unlock(&p IntEventMultiSem->Mutex);422 ASMAtomicDecU32(&pThis->cWaiters); 423 int rc2 = pthread_mutex_unlock(&pThis->Mutex); 670 424 AssertMsg(!rc2, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc2)); NOREF(rc2); 671 425 return RTErrConvertFromErrno(rc); … … 689 443 } 690 444 691 692 693 694 695 /**696 * Validate a Mutex semaphore handle passed to one of the interface.697 *698 * @returns true if valid.699 * @returns false if invalid.700 * @param pIntMutexSem Pointer to the mutex semaphore to validate.701 */702 inline bool rtsemMutexValid(struct RTSEMMUTEXINTERNAL *pIntMutexSem)703 {704 if ((uintptr_t)pIntMutexSem < 0x10000)705 return false;706 707 if (pIntMutexSem->cNesting == (uint32_t)~0)708 return false;709 710 return true;711 }712 713 714 RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem)715 {716 int rc;717 718 /*719 * Allocate semaphore handle.720 */721 struct RTSEMMUTEXINTERNAL *pIntMutexSem = (struct RTSEMMUTEXINTERNAL *)RTMemAlloc(sizeof(struct RTSEMMUTEXINTERNAL));722 if (pIntMutexSem)723 {724 /*725 * Create the semaphore.726 */727 pthread_mutexattr_t MutexAttr;728 rc = pthread_mutexattr_init(&MutexAttr);729 if (!rc)730 {731 rc = pthread_mutex_init(&pIntMutexSem->Mutex, &MutexAttr);732 if (!rc)733 {734 pthread_mutexattr_destroy(&MutexAttr);735 736 pIntMutexSem->Owner = (pthread_t)-1;737 pIntMutexSem->cNesting = 0;738 739 *pMutexSem = pIntMutexSem;740 return VINF_SUCCESS;741 }742 pthread_mutexattr_destroy(&MutexAttr);743 }744 RTMemFree(pIntMutexSem);745 }746 else747 rc = VERR_NO_MEMORY;748 749 return rc;750 }751 752 753 RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX MutexSem)754 {755 /*756 * Validate input.757 */758 if (!rtsemMutexValid(MutexSem))759 {760 AssertMsgFailed(("Invalid handle %p!\n", MutexSem));761 return VERR_INVALID_HANDLE;762 }763 764 /*765 * Try destroy it.766 */767 struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;768 int rc = pthread_mutex_destroy(&pIntMutexSem->Mutex);769 if (rc)770 {771 AssertMsgFailed(("Failed to destroy mutex sem %p, rc=%d.\n", MutexSem, rc));772 return RTErrConvertFromErrno(rc);773 }774 775 /*776 * Free the memory and be gone.777 */778 pIntMutexSem->Owner = (pthread_t)-1;779 pIntMutexSem->cNesting = ~0;780 RTMemTmpFree(pIntMutexSem);781 782 return VINF_SUCCESS;783 }784 785 786 RTDECL(int) RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)787 {788 /*789 * Validate input.790 */791 if (!rtsemMutexValid(MutexSem))792 {793 AssertMsgFailed(("Invalid handle %p!\n", MutexSem));794 return VERR_INVALID_HANDLE;795 }796 797 /*798 * Check if nested request.799 */800 pthread_t Self = pthread_self();801 struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;802 if ( pIntMutexSem->Owner == Self803 && pIntMutexSem->cNesting > 0)804 {805 pIntMutexSem->cNesting++;806 return VINF_SUCCESS;807 }808 809 /*810 * Lock it.811 */812 if (cMillies == RT_INDEFINITE_WAIT)813 {814 /* take mutex */815 int rc = pthread_mutex_lock(&pIntMutexSem->Mutex);816 if (rc)817 {818 AssertMsgFailed(("Failed to lock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);819 return RTErrConvertFromErrno(rc);820 }821 }822 else823 {824 #ifdef RT_OS_DARWIN825 AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));826 return VERR_NOT_IMPLEMENTED;827 #else /* !RT_OS_DARWIN */828 /*829 * Get current time and calc end of wait time.830 */831 struct timespec ts = {0,0};832 clock_gettime(CLOCK_REALTIME, &ts);833 if (cMillies != 0)834 {835 ts.tv_nsec += (cMillies % 1000) * 1000000;836 ts.tv_sec += cMillies / 1000;837 if (ts.tv_nsec >= 1000000000)838 {839 ts.tv_nsec -= 1000000000;840 ts.tv_sec++;841 }842 }843 844 /* take mutex */845 int rc = pthread_mutex_timedlock(&pIntMutexSem->Mutex, &ts);846 if (rc)847 {848 AssertMsg(rc == ETIMEDOUT, ("Failed to lock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);849 return RTErrConvertFromErrno(rc);850 }851 #endif /* !RT_OS_DARWIN */852 }853 854 /*855 * Set the owner and nesting.856 */857 pIntMutexSem->Owner = Self;858 ASMAtomicXchgU32(&pIntMutexSem->cNesting, 1);859 860 return VINF_SUCCESS;861 }862 863 864 RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies)865 {866 /* EINTR isn't returned by the wait functions we're using. */867 return RTSemMutexRequest(MutexSem, cMillies);868 }869 870 871 RTDECL(int) RTSemMutexRelease(RTSEMMUTEX MutexSem)872 {873 /*874 * Validate input.875 */876 if (!rtsemMutexValid(MutexSem))877 {878 AssertMsgFailed(("Invalid handle %p!\n", MutexSem));879 return VERR_INVALID_HANDLE;880 }881 882 /*883 * Check if nested.884 */885 pthread_t Self = pthread_self();886 struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;887 if ( pIntMutexSem->Owner != Self888 || pIntMutexSem->cNesting == (uint32_t)~0)889 {890 AssertMsgFailed(("Not owner of mutex %p!! Self=%08x Owner=%08x cNesting=%d\n",891 pIntMutexSem, Self, pIntMutexSem->Owner, pIntMutexSem->cNesting));892 return VERR_NOT_OWNER;893 }894 895 /*896 * If nested we'll just pop a nesting.897 */898 if (pIntMutexSem->cNesting > 1)899 {900 pIntMutexSem->cNesting--;901 return VINF_SUCCESS;902 }903 904 /*905 * Clear the state. (cNesting == 1)906 */907 pIntMutexSem->Owner = (pthread_t)-1;908 ASMAtomicXchgU32(&pIntMutexSem->cNesting, 0);909 910 /*911 * Unlock mutex semaphore.912 */913 int rc = pthread_mutex_unlock(&pIntMutexSem->Mutex);914 if (rc)915 {916 AssertMsgFailed(("Failed to unlock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);917 return RTErrConvertFromErrno(rc);918 }919 920 return VINF_SUCCESS;921 }922 923 924 925 926 927 /**928 * Validate a read-write semaphore handle passed to one of the interface.929 *930 * @returns true if valid.931 * @returns false if invalid.932 * @param pIntRWSem Pointer to the read-write semaphore to validate.933 */934 inline bool rtsemRWValid(struct RTSEMRWINTERNAL *pIntRWSem)935 {936 if ((uintptr_t)pIntRWSem < 0x10000)937 return false;938 939 if (pIntRWSem->uCheck != (unsigned)~0)940 return false;941 942 return true;943 }944 945 946 RTDECL(int) RTSemRWCreate(PRTSEMRW pRWSem)947 {948 int rc;949 950 /*951 * Allocate handle.952 */953 struct RTSEMRWINTERNAL *pIntRWSem = (struct RTSEMRWINTERNAL *)RTMemAlloc(sizeof(struct RTSEMRWINTERNAL));954 if (pIntRWSem)955 {956 /*957 * Create the rwlock.958 */959 pthread_rwlockattr_t Attr;960 rc = pthread_rwlockattr_init(&Attr);961 if (!rc)962 {963 rc = pthread_rwlock_init(&pIntRWSem->RWLock, &Attr);964 if (!rc)965 {966 pIntRWSem->uCheck = ~0;967 pIntRWSem->WROwner = (pthread_t)-1;968 *pRWSem = pIntRWSem;969 return VINF_SUCCESS;970 }971 }972 973 rc = RTErrConvertFromErrno(rc);974 RTMemFree(pIntRWSem);975 }976 else977 rc = VERR_NO_MEMORY;978 979 return rc;980 }981 982 983 RTDECL(int) RTSemRWDestroy(RTSEMRW RWSem)984 {985 /*986 * Validate input.987 */988 if (!rtsemRWValid(RWSem))989 {990 AssertMsgFailed(("Invalid handle %p!\n", RWSem));991 return VERR_INVALID_HANDLE;992 }993 994 /*995 * Try destroy it.996 */997 struct RTSEMRWINTERNAL *pIntRWSem = RWSem;998 int rc = pthread_rwlock_destroy(&pIntRWSem->RWLock);999 if (!rc)1000 {1001 pIntRWSem->uCheck = 0;1002 RTMemFree(pIntRWSem);1003 rc = VINF_SUCCESS;1004 }1005 else1006 {1007 AssertMsgFailed(("Failed to destroy read-write sem %p, rc=%d.\n", RWSem, rc));1008 rc = RTErrConvertFromErrno(rc);1009 }1010 1011 return rc;1012 }1013 1014 1015 RTDECL(int) RTSemRWRequestRead(RTSEMRW RWSem, unsigned cMillies)1016 {1017 /*1018 * Validate input.1019 */1020 if (!rtsemRWValid(RWSem))1021 {1022 AssertMsgFailed(("Invalid handle %p!\n", RWSem));1023 return VERR_INVALID_HANDLE;1024 }1025 1026 /*1027 * Try lock it.1028 */1029 struct RTSEMRWINTERNAL *pIntRWSem = RWSem;1030 if (cMillies == RT_INDEFINITE_WAIT)1031 {1032 /* take rwlock */1033 int rc = pthread_rwlock_rdlock(&pIntRWSem->RWLock);1034 if (rc)1035 {1036 AssertMsgFailed(("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));1037 return RTErrConvertFromErrno(rc);1038 }1039 }1040 else1041 {1042 #ifdef RT_OS_DARWIN1043 AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));1044 return VERR_NOT_IMPLEMENTED;1045 #else /* !RT_OS_DARWIN */1046 /*1047 * Get current time and calc end of wait time.1048 */1049 struct timespec ts = {0,0};1050 clock_gettime(CLOCK_REALTIME, &ts);1051 if (cMillies != 0)1052 {1053 ts.tv_nsec += (cMillies % 1000) * 1000000;1054 ts.tv_sec += cMillies / 1000;1055 if (ts.tv_nsec >= 1000000000)1056 {1057 ts.tv_nsec -= 1000000000;1058 ts.tv_sec++;1059 }1060 }1061 1062 /* take rwlock */1063 int rc = pthread_rwlock_timedrdlock(&pIntRWSem->RWLock, &ts);1064 if (rc)1065 {1066 AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));1067 return RTErrConvertFromErrno(rc);1068 }1069 #endif /* !RT_OS_DARWIN */1070 }1071 1072 return VINF_SUCCESS;1073 }1074 1075 1076 RTDECL(int) RTSemRWRequestReadNoResume(RTSEMRW RWSem, unsigned cMillies)1077 {1078 /* EINTR isn't returned by the wait functions we're using. */1079 return RTSemRWRequestRead(RWSem, cMillies);1080 }1081 1082 1083 RTDECL(int) RTSemRWReleaseRead(RTSEMRW RWSem)1084 {1085 /*1086 * Validate input.1087 */1088 if (!rtsemRWValid(RWSem))1089 {1090 AssertMsgFailed(("Invalid handle %p!\n", RWSem));1091 return VERR_INVALID_HANDLE;1092 }1093 1094 /*1095 * Try unlock it.1096 */1097 struct RTSEMRWINTERNAL *pIntRWSem = RWSem;1098 if (pIntRWSem->WROwner == pthread_self())1099 {1100 AssertMsgFailed(("Tried to read unlock when write owner - read-write sem %p.\n", RWSem));1101 return VERR_NOT_OWNER;1102 }1103 int rc = pthread_rwlock_unlock(&pIntRWSem->RWLock);1104 if (rc)1105 {1106 AssertMsgFailed(("Failed read unlock read-write sem %p, rc=%d.\n", RWSem, rc));1107 return RTErrConvertFromErrno(rc);1108 }1109 1110 return VINF_SUCCESS;1111 }1112 1113 1114 RTDECL(int) RTSemRWRequestWrite(RTSEMRW RWSem, unsigned cMillies)1115 {1116 /*1117 * Validate input.1118 */1119 if (!rtsemRWValid(RWSem))1120 {1121 AssertMsgFailed(("Invalid handle %p!\n", RWSem));1122 return VERR_INVALID_HANDLE;1123 }1124 1125 /*1126 * Try lock it.1127 */1128 struct RTSEMRWINTERNAL *pIntRWSem = RWSem;1129 if (cMillies == RT_INDEFINITE_WAIT)1130 {1131 /* take rwlock */1132 int rc = pthread_rwlock_wrlock(&pIntRWSem->RWLock);1133 if (rc)1134 {1135 AssertMsgFailed(("Failed write lock read-write sem %p, rc=%d.\n", RWSem, rc));1136 return RTErrConvertFromErrno(rc);1137 }1138 }1139 else1140 {1141 #ifdef RT_OS_DARWIN1142 AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));1143 return VERR_NOT_IMPLEMENTED;1144 #else /* !RT_OS_DARWIN */1145 /*1146 * Get current time and calc end of wait time.1147 */1148 struct timespec ts = {0,0};1149 clock_gettime(CLOCK_REALTIME, &ts);1150 if (cMillies != 0)1151 {1152 ts.tv_nsec += (cMillies % 1000) * 1000000;1153 ts.tv_sec += cMillies / 1000;1154 if (ts.tv_nsec >= 1000000000)1155 {1156 ts.tv_nsec -= 1000000000;1157 ts.tv_sec++;1158 }1159 }1160 1161 /* take rwlock */1162 int rc = pthread_rwlock_timedwrlock(&pIntRWSem->RWLock, &ts);1163 if (rc)1164 {1165 AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));1166 return RTErrConvertFromErrno(rc);1167 }1168 #endif /* !RT_OS_DARWIN */1169 }1170 1171 #ifdef RT_OS_SOLARIS1172 ASMAtomicXchgSize(&pIntRWSem->WROwner, pthread_self());1173 #else1174 ASMAtomicXchgPtr((void * volatile *)&pIntRWSem->WROwner, (void *)pthread_self());1175 #endif1176 1177 return VINF_SUCCESS;1178 }1179 1180 1181 RTDECL(int) RTSemRWRequestWriteNoResume(RTSEMRW RWSem, unsigned cMillies)1182 {1183 /* EINTR isn't returned by the wait functions we're using. */1184 return RTSemRWRequestWrite(RWSem, cMillies);1185 }1186 1187 1188 RTDECL(int) RTSemRWReleaseWrite(RTSEMRW RWSem)1189 {1190 /*1191 * Validate input.1192 */1193 if (!rtsemRWValid(RWSem))1194 {1195 AssertMsgFailed(("Invalid handle %p!\n", RWSem));1196 return VERR_INVALID_HANDLE;1197 }1198 1199 /*1200 * Try unlock it.1201 */1202 pthread_t Self = pthread_self();1203 struct RTSEMRWINTERNAL *pIntRWSem = RWSem;1204 if (pIntRWSem->WROwner != Self)1205 {1206 AssertMsgFailed(("Not Write owner!\n"));1207 return VERR_NOT_OWNER;1208 }1209 1210 /*1211 * Try unlock it.1212 */1213 #ifdef RT_OS_SOLARIS1214 ASMAtomicXchgSize(&pIntRWSem->WROwner, (pthread_t)-1);1215 #else1216 AssertMsg(sizeof(pthread_t) == sizeof(void *), ("pthread_t is not the size of a pointer but %d bytes\n", sizeof(pthread_t)));1217 ASMAtomicXchgPtr((void * volatile *)&pIntRWSem->WROwner, (void *)(pthread_t)-1);1218 #endif1219 int rc = pthread_rwlock_unlock(&pIntRWSem->RWLock);1220 if (rc)1221 {1222 AssertMsgFailed(("Failed write unlock read-write sem %p, rc=%d.\n", RWSem, rc));1223 return RTErrConvertFromErrno(rc);1224 }1225 1226 return VINF_SUCCESS;1227 }1228
Note:
See TracChangeset
for help on using the changeset viewer.