Changeset 2299
- Timestamp:
- Aug 22, 2005, 3:56:25 AM (20 years ago)
- Location:
- trunk/src/emx
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/emx/ChangeLog.LIBC
-
Property cvs2svn:cvs-rev
changed from
1.123
to1.124
r2298 r2299 5 5 2005-08-21: knut st. osmundsen <bird-gccos2-spam@anduin.net> 6 6 - libc: 7 o Merged the signal semaphore handling into the safe sems and 8 made signals use them instead. 7 9 o Tried to workaround the race conditions in __libc_Back_safesemEvSleep/Wakeup. 8 10 These might affect SysV sems. -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/include/InnoTekLIBC/backend.h
-
Property cvs2svn:cvs-rev
changed from
1.31
to1.32
r2298 r2299 967 967 * @{ */ 968 968 969 /** 969 /** 970 970 * Safe Mutex Semaphore structure. 971 971 * 972 * For shared semaphores this structure must be in shared memory so all users 972 * For shared semaphores this structure must be in shared memory so all users 973 973 * actually use the very same structure. 974 974 */ … … 977 977 #ifdef __OS2__ 978 978 /** Mutex handle. */ 979 unsigned long hmtx; 980 #endif 979 unsigned long hmtx; 980 #endif 981 /** Set if the semaphore is shared. */ 982 unsigned fShared; 981 983 } __LIBC_SAFESEMMTX; 982 984 /** Pointer to a SAFESEM Mutex structure. */ … … 1030 1032 1031 1033 1032 /** 1034 /** 1033 1035 * Safe Event Semaphore structure. 1034 1036 * 1035 * For shared semaphores this structure must be in shared memory so all users 1037 * For shared semaphores this structure must be in shared memory so all users 1036 1038 * actually use the very same structure. 1037 1039 * 1038 * @remark The event semaphore business is difficult because the lack of 1039 * atomic mutex release + event wait apis in OS/2. We have to 1040 * @remark The event semaphore business is difficult because the lack of 1041 * atomic mutex release + event wait apis in OS/2. We have to 1040 1042 * jump around the place to get this working nearly safly... 1041 1043 */ … … 1045 1047 /** The event semaphore. */ 1046 1048 unsigned long hev; 1047 #endif 1049 #endif 1048 1050 /** Number of threads which are supposed to be blocking on the above event semaphore. */ 1049 1051 uint32_t volatile cWaiters; 1050 1052 /** The mutex semaphore used to protect the event semaphore. */ 1051 1053 __LIBC_PSAFESEMMTX pmtx; 1052 /** Set if the semaphore is shared. 1053 * If shared this structure is allocated from SPM, else it's from the heap. */ 1054 /** Set if the semaphore is shared. */ 1054 1055 unsigned fShared; 1055 1056 } __LIBC_SAFESEMEV; … … 1071 1072 * Opens a shared safe event sem. 1072 1073 * 1073 * The caller is responsible for opening the associated mutex 1074 * The caller is responsible for opening the associated mutex 1074 1075 * semaphore before calling this function. 1075 1076 * … … 1092 1093 * Sleep on a semaphore. 1093 1094 * 1094 * The caller must own the associated mutex semaphore. The mutex semaphore will 1095 * be released as we go to sleep and reclaimed when we wake up. 1096 * 1097 * The pfnComplete callback is used to correct state before signals are handled. 1095 * The caller must own the associated mutex semaphore. The mutex semaphore will 1096 * be released as we go to sleep and reclaimed when we wake up. 1097 * 1098 * The pfnComplete callback is used to correct state before signals are handled. 1098 1099 * It will always be called be for this function returns, and it'll either be under 1099 1100 * the protection of the signal mutex or the associated mutex (both safe sems). 1100 1101 * 1101 * This is the most difficult thing we're doing in this API. On OS/2 we have 1102 * This is the most difficult thing we're doing in this API. On OS/2 we have 1102 1103 * potential (at least theoretically) race conditions... 1103 1104 * -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/src/lib/sys/safesems.c
-
Property cvs2svn:cvs-rev
changed from
1.3
to1.4
r2298 r2299 81 81 LIBCLOG_ENTER("pmtx=%p fShared=%d\n", (void *)pmtx, fShared); 82 82 pmtx->hmtx = NULLHANDLE; 83 pmtx->fShared = fShared; 83 84 int rc = DosCreateMutexSemEx(NULL, &pmtx->hmtx, fShared ? DC_SEM_SHARED : 0, FALSE); 84 85 if (rc) … … 116 117 LIBCLOG_ENTER("pmtx=%p:{.hmtx=%#lx}\n", (void *)pmtx, pmtx->hmtx); 117 118 int rc = DosCloseMutexSemEx(pmtx->hmtx); 118 if ( !rc)119 if (rc) 119 120 rc = -__libc_native2errno(rc); 120 121 LIBCLOG_RETURN_INT(rc); … … 127 128 * result. 128 129 * 130 * @returns 0 on success. 131 * @returns -1 on failure. 129 132 * @internal 130 133 */ 131 static int stackChecker(void) 132 { 133 char volatile *pch = alloca(2048); 134 if (!pch) 135 return -1; 136 /* With any luck the compiler doesn't optimize this away. */ 137 pch[0] = pch[1024] = pch[2044] = 0x7f; 134 static int __libc_back_safesemStackChecker(void) 135 { 136 char volatile *pch; 137 unsigned u; 138 __asm__ __volatile__("movl %%esp, %0\n\t" 139 "movl -4(%0), %1\n\t" 140 "movl %1, -4(%0)\n\t" 141 "movl -1024(%0), %1\n\t" 142 "movl %1, -1024(%0)\n\t" 143 "movl -2048(%0), %1\n\t" 144 "movl %1, -2048(%0)\n\t" 145 : "=r" (pch), "=r" (u)); 138 146 return 0; 139 147 } … … 158 166 * Check stack. 159 167 */ 160 if ( stackChecker())168 if (__predict_false(__libc_back_safesemStackChecker() != 0)) 161 169 { 162 170 LIBC_ASSERTM_FAILED("Too little stack left!\n"); … … 166 174 /* 167 175 * Request semaphore and enter "must-complete section" to avoid signal trouble. 176 * 177 * We start by trying for 1ms inside a must-complete section. This will usually 178 * succeed and is the safest way of acquiring the mutex. While waiting from inside 179 * a must-complete section we're unkillable, so we can only do this for very short 180 * periods. 168 181 */ 169 182 FS_SAVE_LOAD(); 170 /* try for 2ms in a must-complete section. */171 183 DosEnterMustComplete(&ul); 172 rc = DosRequestMutexSem(hmtx, 2); 173 if (!rc) 174 { 175 FS_RESTORE(); 176 LIBCLOG_RETURN_INT(0); 177 } 178 179 /* retry outside the must-complete section. */ 180 DosExitMustComplete(&ul); 181 rc = DosRequestMutexSem(hmtx, 30*1000); 182 DosEnterMustComplete(&ul); 183 if (!rc) 184 { 185 FS_RESTORE(); 186 LIBCLOG_RETURN_INT(0); 187 } 188 189 /* failure out */ 190 DosExitMustComplete(&ul); 191 LIBC_ASSERTM_FAILED("DosRequestMutexSem(%lx) failed with rc=%d!\n", pmtx->hmtx, rc); 192 rc = -__libc_native2errno(rc); 184 rc = DosRequestMutexSem(hmtx, 1); 185 if (__predict_false(rc != NO_ERROR)) 186 { 187 /* 188 * Ok, do an interruptable wait then and handle all kind of errors that might occur. 189 */ 190 unsigned cOwnerDied = 30; 191 unsigned msStart = fibGetMsCount(); 192 unsigned msSleep = 30*1000; 193 for (;;) 194 { 195 DosExitMustComplete(&ul); 196 rc = DosRequestMutexSem(hmtx, msSleep); 197 DosEnterMustComplete(&ul); 198 if (!rc) 199 break; 200 201 if (rc == ERROR_INTERRUPT || rc == ERROR_SEM_TIMEOUT || rc == ERROR_TIMEOUT) 202 { 203 /* 204 * If the waiting was interrupted someone wants our attention, possibly because 205 * we're dying. If we timed out we've got a potential deadlock on our hands, 206 * this can also happen during termination. 207 * 208 * Check if the process is dying before retrying to get the semaphore. Being 209 * stubborn during process termination usually lead to bad deadlocks. 210 */ 211 if (fibIsInExit()) 212 { 213 DosExitMustComplete(&ul); /* we're terminating, don't give a shit about signals now, just hurry up and die! */ 214 FS_RESTORE(); 215 LIBCLOG_ERROR_RETURN_MSG(-EDEADLK, "ret -%d (we're dying)\n", EDEADLK); 216 } 217 /* Not dying, retry. */ 218 } 219 else if (rc == ERROR_SEM_OWNER_DIED && --cOwnerDied > 0) 220 { 221 /* 222 * Semaphore owner dies, try remedy the situation. 223 */ 224 HMTX hmtxNew; 225 LIBCLOG_MSG("Semaphore owner died. !SHIT!\n"); 226 rc = DosCreateMutexSemEx(NULL, &hmtxNew, pmtx->fShared ? DC_SEM_SHARED : 0, TRUE); 227 if (rc) 228 __libc_Back_panic(0, NULL, "safesem mutex owner died: create mutex failed, rc=%d. pmtx=%p:{.hmtx=%#lx .fShared=%d}\n", 229 rc, (void *)pmtx, pmtx->hmtx, pmtx->fShared); 230 /* we race here. */ 231 if (__atomic_cmpxchg32((uint32_t volatile *)&pmtx->hmtx, (uint32_t)hmtx, (uint32_t)hmtxNew)) 232 break; 233 234 /* beaten. */ 235 DosCloseMutexSem(hmtxNew); 236 msSleep = 2; /* force retry */ 237 hmtx = pmtx->hmtx; 238 } 239 else 240 __libc_Back_panic(0, NULL, "safesem mutex requested failed, rc=%d. pmtx=%p:{.hmtx=%#lx .fShared=%d}\n", 241 rc, (void *)pmtx, pmtx->hmtx, pmtx->fShared); 242 243 /* 244 * Calculate sleep time / check for timeout. 245 */ 246 if (msSleep <= 1) 247 __libc_Back_panic(0, NULL, "safesem mutex timeout, %u ms: pmtx=%p:{.hmtx=%#lx .fShared=%d}\n", 248 fibGetMsCount() - msStart, (void *)pmtx, pmtx->hmtx, pmtx->fShared); 249 msSleep = fibGetMsCount() - msStart; 250 if (msSleep < 30*1000) 251 msSleep = 30*1000 - msSleep; 252 else 253 msSleep = 1; /* one last try before we panic. */ 254 255 LIBCLOG_MSG("Interrupted, retry %d ms\n", msSleep); 256 } /* for (;;) */ 257 } 258 259 /* success */ 193 260 FS_RESTORE(); 194 LIBCLOG_RETURN_INT( rc);261 LIBCLOG_RETURN_INT(0); 195 262 } 196 263 … … 215 282 FS_SAVE_LOAD(); 216 283 rc = DosReleaseMutexSem(pmtx->hmtx); 217 if (rc) 218 { 219 FS_RESTORE(); 220 LIBC_ASSERTM_FAILED("DosReleaseMutexSem(%lx) -> %d\n", pmtx->hmtx, rc); 221 rc = -__libc_native2errno(rc); 222 LIBCLOG_RETURN_INT(rc); 223 } 284 if (__predict_false(rc != NO_ERROR)) 285 __libc_Back_panic(0, NULL, "safesem mutex release failed, rc=%d. pmtx=%p:{.hmtx=%#lx .fShared=%d}\n", 286 rc, (void *)pmtx, pmtx->hmtx, pmtx->fShared); 224 287 225 288 DosExitMustComplete(&ul); … … 315 378 pArgs->pfnComplete(pArgs->pvUser); 316 379 int rc = DosSetPriority(PRTYS_THREAD, pArgs->ulOldPri >> 8, pArgs->ulOldPri & 0xff, 0); 317 if ( rc)380 if (__predict_false(rc != NO_ERROR)) 318 381 __libc_Back_panic(0, NULL, "DosSetPriority(PRTYS_THREAD, %x, %x, 0) -> %d (3)\n", 319 382 (unsigned)pArgs->ulOldPri >> 8, (unsigned)pArgs->ulOldPri & 0xff, rc); … … 354 417 int rc; 355 418 __LIBC_PTHREAD pThrd = __libc_threadCurrentNoAuto(); 356 if ( pThrd)419 if (__predict_true(pThrd != NULL)) 357 420 { 358 421 FS_VAR_SAVE_LOAD(); … … 378 441 rc = DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 31, 0); 379 442 LIBC_ASSERTM(!rc, "DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 31, 0) -> %d\n", rc); 380 if ( rc && (Args.ulOldPri >> 8) != PRTYC_TIMECRITICAL)443 if (__predict_false(rc && (Args.ulOldPri >> 8) != PRTYC_TIMECRITICAL)) 381 444 { 382 445 rc = DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0); … … 389 452 __atomic_increment_u32(&pev->cWaiters); 390 453 rc = __libc_Back_safesemMtxUnlock(pev->pmtx); 391 if ( !rc)454 if (__predict_true(!rc)) 392 455 { 393 456 /* … … 395 458 */ 396 459 int rc2 = 0; 397 if ( !Args.fDone)460 if (__predict_true(!Args.fDone)) 398 461 rc2 = DosWaitEventSem(pev->hev, SEM_INDEFINITE_WAIT); 462 /** @todo check for fibIsInExit() in some way? */ 399 463 400 464 /* … … 411 475 */ 412 476 rc2 = DosSetPriority(PRTYS_THREAD, Args.ulOldPri >> 8, Args.ulOldPri & 0xff, 0); 413 if ( rc2)477 if (__predict_false(rc2 != NO_ERROR)) 414 478 __libc_Back_panic(0, NULL, "DosSetPriority(PRTYS_THREAD, %x, %x, 0) -> %d (1)\n", 415 479 (unsigned)Args.ulOldPri >> 8, (unsigned)Args.ulOldPri & 0xff, rc2); … … 444 508 * Check for interruption and do completion. 445 509 */ 446 if ( !Args.fDone)510 if (__predict_true(!Args.fDone)) 447 511 { 448 512 pfnComplete(pvUser); -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/src/lib/sys/signals.c
-
Property cvs2svn:cvs-rev
changed from
1.30
to1.31
r2298 r2299 227 227 * This mutex basically protects all the signal constructs in the process. A 228 228 * complete list of what this is should be provided later. 229 * 230 * An OS/2 semaphore is used here because speed is less important than 231 * reliability. Don't access the mutex directly but use the methods 232 * defined for such purposes. 233 */ 234 static HMTX ghmtxSignals; 229 */ 230 static __LIBC_SAFESEMMTX gmtxSignals; 235 231 236 232 /** Wait Event Semaphore. … … 588 584 LIBCLOG_ENTER("\n"); 589 585 int rc; 590 FS_VAR();591 586 592 587 /* 593 588 * Create the semaphore. 594 589 */ 595 FS_SAVE_LOAD(); 596 rc = DosCreateMutexSemEx(NULL, &ghmtxSignals, 0, FALSE); 590 rc = __libc_Back_safesemMtxCreate(&gmtxSignals, FALSE); 597 591 if (!rc) 598 592 { … … 622 616 } 623 617 624 FS_RESTORE();625 618 LIBCLOG_RETURN_INT(0); 626 619 } … … 628 621 LIBC_ASSERTM_FAILED("DosCreateEventSemEx failed with rc=%d\n", rc); 629 622 630 DosCloseMutexSemEx(ghmtxSignals);631 g hmtxSignals= NULLHANDLE;623 __libc_Back_safesemMtxClose(&gmtxSignals); 624 gmtxSignals.hmtx = NULLHANDLE; 632 625 } 633 626 else 634 LIBC_ASSERTM_FAILED("DosCreateMutexSemEx failed with rc=%d\n", rc); 635 636 FS_RESTORE(); 627 LIBC_ASSERTM_FAILED("__libc_Back_safesemMtxCreate failed with rc=%d\n", rc); 628 637 629 LIBCLOG_RETURN_INT(-1); 638 630 } … … 694 686 DosGetInfoBlocks(&pTib, &pPib); 695 687 696 rc = DosQueryMutexSem(g hmtxSignals, &pid, &tid, &cNesting);688 rc = DosQueryMutexSem(gmtxSignals.hmtx, &pid, &tid, &cNesting); 697 689 FS_RESTORE(); 698 LIBC_ASSERTM(!rc, "DosQueryMutexSem(%#lx,,,,) -> rc=%d\n", g hmtxSignals, rc);690 LIBC_ASSERTM(!rc, "DosQueryMutexSem(%#lx,,,,) -> rc=%d\n", gmtxSignals.hmtx, rc); 699 691 if (!rc && pTib->tib_ptib2->tib2_ultid == tid && pPib->pib_ulpid == pid) 700 692 return cNesting ? cNesting : 1; /* paranoia */ … … 712 704 { 713 705 LIBCLOG_ENTER("\n"); 714 int rc; 715 ULONG cNesting; 716 FS_VAR(); 717 718 FS_SAVE_LOAD(); 719 do 720 { 721 HMTX hmtx = ghmtxSignals; 722 rc = DosRequestMutexSem(hmtx, 3000); 723 if (!rc) 724 break; 725 if (rc == ERROR_INTERRUPT || rc == ERROR_SEM_TIMEOUT || rc == ERROR_TIMEOUT) 726 { 727 /* 728 * The waiting was interrupted, probably because someone 729 * signalling us. 730 * 731 * Check if the process is dying before retrying to get the 732 * semaphore. Being stubborn during process termination usually 733 * lead to bad deadlocks. 734 */ 735 if (fibIsInExit()) 736 { 737 /* we're terminating, don't give a shit about signals now, just hurry up and die! */ 738 FS_RESTORE(); 739 LIBCLOG_ERROR_RETURN_MSG(-1, "ret -1 (we're dying)\n"); 740 } 741 /* Not dying, retry. */ 742 } 743 else if (rc == ERROR_SEM_OWNER_DIED) 744 { 745 HMTX hmtxNew; 746 LIBCLOG_MSG("semaphore owner died. !SHIT!\n"); 747 /* we'll try fix this situation */ 748 rc = DosCreateMutexSem(NULL, &hmtxNew, 0, TRUE); 749 if (rc) 750 { 751 FS_RESTORE(); 752 LIBCLOG_ERROR_RETURN_MSG(-1, "ret -1 (create mutex failed, rc=%d)\n", rc); 753 } 754 /* we race here. */ 755 if (__atomic_cmpxchg32((uint32_t *)(void *)&ghmtxSignals, (uint32_t)hmtx, (uint32_t)hmtxNew)) 756 break; 757 758 /* beaten. */ 759 DosCloseMutexSem(hmtxNew); 760 } 761 else 762 { 763 FS_RESTORE(); 764 LIBC_ASSERTM_FAILED("DosRequestMutexSem retured odd rc=%d\n", rc); 765 LIBCLOG_ERROR_RETURN_MSG(-1, "ret -1 (unknown reason, rc=%d)\n", rc); 766 } 767 768 LIBCLOG_MSG("interrupted, retry\n"); 769 } while (1); 770 771 /* 772 * Got the semaphore, now enter must complete. 773 */ 774 rc = DosEnterMustComplete(&cNesting); 775 LIBC_ASSERTM(!rc, "DosEnterMustComplete failed with rc=%d\n", rc); 776 777 LIBCLOG_RETURN_MSG(0, "ret 0 (must complete nesting %lu)\n", cNesting); 706 int rc = __libc_Back_safesemMtxLock(&gmtxSignals); 707 LIBCLOG_RETURN_INT(rc); 778 708 } 779 709 … … 785 715 { 786 716 LIBCLOG_ENTER("\n"); 787 ULONG cNesting; 788 int rc; 789 FS_VAR(); 790 791 /* 792 * First the semphore. 793 */ 794 FS_SAVE_LOAD(); 795 rc = DosReleaseMutexSem(ghmtxSignals); 796 if (rc) 797 { 798 LIBC_ASSERTM_FAILED("DosReleaseMutexSem failed with rc=%d\n", rc); 799 FS_RESTORE(); 800 LIBCLOG_ERROR_RETURN_VOID(); 801 } 802 803 /* 804 * Now we can leave the must complete stuff. 805 */ 806 rc = DosExitMustComplete(&cNesting); 807 LIBC_ASSERTM(!rc, "DosExitMustComplete failed with rc=%d\n", rc); 808 809 FS_RESTORE(); 810 LIBCLOG_RETURN_MSG_VOID("ret 0 (must complete nesting %lu)\n", cNesting); 717 __libc_Back_safesemMtxUnlock(&gmtxSignals); 718 LIBCLOG_RETURN_VOID(); 811 719 } 812 720 -
Property cvs2svn:cvs-rev
changed from
Note:
See TracChangeset
for help on using the changeset viewer.