Changeset 2723
- Timestamp:
- Jul 17, 2006, 7:10:19 AM (19 years ago)
- Location:
- trunk/libc
- Files:
-
- 3 added
- 5 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/libc/Config.kmk
r2717 r2723 50 50 IN_INNOTEK_LIBC \ 51 51 __IN_INNOTEK_LIBC__ 52 DEFS.os2 = __OS2__ 53 DEFS.win32 = __NT__ 54 DEFS.win64 = __NT__ 55 52 56 53 57 # … … 73 77 TEMPLATE_libc_TOOL = GCC3 74 78 TEMPLATE_libc_INCS = $(PATH_LIBC_INC) $(dir $(LIBC-STD.H)) 79 TEMPLATE_libc_INCS.win32 = $(PATH_LIBC_SRC)/w32api/include 80 TEMPLATE_libc_INCS.win64 = $(TEMPLATE_libc_INCS.win32) 75 81 TEMPLATE_libc_DEPS = $(LIBC-STD.H) 76 82 TEMPLATE_libc_INST = usr/lib/ … … 80 86 TEMPLATE_libc.logstrict_TOOL = GCC3 81 87 TEMPLATE_libc.logstrict_INCS = $(TEMPLATE_libc_INCS) 88 TEMPLATE_libc.logstrict_INCS.win32 = $(TEMPLATE_libc_INCS.win32) 89 TEMPLATE_libc.logstrict_INCS.win64 = $(TEMPLATE_libc_INCS.win64) 82 90 TEMPLATE_libc.logstrict_DEFS = $(TEMPLATE_libc_DEFS) __LIBC_STRICT DEBUG_LOGGING 83 91 TEMPLATE_libc.logstrict_DEPS = $(TEMPLATE_libc_DEPS) … … 88 96 TEMPLATE_libc.profiled_TOOL = GCC3 89 97 TEMPLATE_libc.profiled_INCS = $(TEMPLATE_libc_INCS) 98 TEMPLATE_libc.profiled_INCS.win32 = $(TEMPLATE_libc_INCS.win32) 99 TEMPLATE_libc.profiled_INCS.win64 = $(TEMPLATE_libc_INCS.win64) 90 100 TEMPLATE_libc.profiled_DEFS = $(TEMPLATE_libc_DEFS) __LIBC_PROFILED 91 101 TEMPLATE_libc.profiled_DEPS = $(TEMPLATE_libc_DEPS) -
trunk/libc/include/386/builtin.h
r2049 r2723 428 428 429 429 430 /** 431 * Atomically compare and exchange a pointer. 432 * 433 * @returns 1 if changed, 0 if unchanged (i.e. boolean). 434 * @param ppv Pointer to the value to compare & exchange. 435 * @param pvNew The new value. 436 * @param pvCur The current value. Only update if *pu32 equals this one. 437 */ 438 static inline unsigned __atomic_cmpxchgptr(void * volatile *ppv, void *pvNew, void *pvOld) 439 { 440 __asm__ __volatile__("lock; cmpxchgl %2, %1\n\t" 441 "setz %%al\n\t" 442 "movzx %%al, %%eax\n\t" 443 : "=a" (pvOld), 444 "=m" (*ppv) 445 : "r" (pvNew), 446 "0" (pvOld)); 447 return (uintptr_t)pvOld; 448 } 449 430 450 #define __ROTATE_FUN(F,I,T) \ 431 451 static __inline__ T F (T value, int shift) \ -
trunk/libc/include/sys/fmutex.h
r2090 r2723 41 41 { 42 42 /** Handle to event semaphore. */ 43 #ifdef __OS2__ 43 44 unsigned long hev; 45 #else 46 void *hev; 47 #endif 44 48 /** Semaphore status. */ 45 49 volatile signed char fs; -
trunk/libc/src/libc/process/Makefile.kmk
r2719 r2723 121 121 $(PATH_LIBC_SRC)/libc/process/os2/fmutex-os2.c \ 122 122 123 libc_libc_process_SOURCES.win32 = \ 124 $(PATH_LIBC_SRC)/libc/process/nt/fmutex-nt.c \ 125 $(PATH_LIBC_SRC)/libc/process/nt/smutex-nt.c \ 126 127 libc_libc_process_SOURCES.win64 = $(libc_libc_process_SOURCES.win32) 123 128 124 129 # configure the variants. */ -
trunk/libc/src/libc/process/nt/fmutex-nt.c
r2719 r2723 2 2 3 3 #include "libc-alias.h" 4 #define INCL_DOSSEMAPHORES 5 #define INCL_DOSPROCESS 6 #define INCL_DOSERRORS 7 #define INCL_DOSEXCEPTIONS 8 #define INCL_FSMACROS 9 #define INCL_EXAPIS 10 #include <os2.h> 4 #include <klibc/nt/nt.h> 11 5 #include <stdlib.h> 12 6 #include <string.h> … … 14 8 #include <sys/fmutex.h> 15 9 #include <sys/smutex.h> 16 #include <InnoTekLIBC/FastInfoBlocks.h>17 10 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_MUTEX 18 11 #include <InnoTekLIBC/logstrict.h> … … 28 21 29 22 30 unsigned _fmutex_create(_fmutex * sem, unsigned flags)31 { 32 LIBCLOG_ENTER(" sem=%p flags=%#x\n", (void *)sem, flags);33 unsigned rc = _fmutex_create2( sem, flags, NULL);23 unsigned _fmutex_create(_fmutex *pSem, unsigned flags) 24 { 25 LIBCLOG_ENTER("pSem=%p flags=%#x\n", (void *)pSem, flags); 26 unsigned rc = _fmutex_create2(pSem, flags, NULL); 34 27 if (!rc) 35 28 LIBCLOG_RETURN_UINT(rc); … … 38 31 39 32 40 unsigned _fmutex_create2(_fmutex *sem, unsigned flags, const char *pszDesc) 41 { 42 LIBCLOG_ENTER("sem=%p flags=%#x pszDesc=%s\n", (void *)sem, flags, pszDesc); 43 unsigned rc; 44 45 sem->hev = 0; 46 sem->Owner = 0; 47 sem->fs = _FMS_AVAILABLE; 48 sem->flags = flags; 49 sem->padding[0] = 'f'; 50 sem->padding[1] = 'm'; 51 sem->pszDesc = pszDesc; 52 rc = DosCreateEventSemEx(NULL, (PHEV)&sem->hev, 53 (flags & _FMC_SHARED) ? DC_SEM_SHARED : 0, 54 FALSE); 55 if (!rc) 33 unsigned _fmutex_create2(_fmutex *pSem, unsigned flags, const char *pszDesc) 34 { 35 LIBCLOG_ENTER("pSem=%p flags=%#x pszDesc=%s\n", (void *)pSem, flags, pszDesc); 36 if (flags & _FMC_SHARED) 37 __libc_Back_panic(0, NULL, "_fmutex_create2: _FMC_SHARED isn't supported on NT. sorry.\n"); 38 39 pSem->hev = 0; 40 pSem->Owner = 0; 41 pSem->fs = _FMS_AVAILABLE; 42 pSem->flags = flags; 43 pSem->padding[0] = 'f'; 44 pSem->padding[1] = 'm'; 45 pSem->pszDesc = pszDesc; 46 NTSTATUS rc = NtCreateEvent(&pSem->hev, EVENT_ALL_ACCESS, NULL, FALSE, FALSE); 47 if (NT_SUCCESS(rc)) 56 48 LIBCLOG_RETURN_UINT(rc); 57 49 LIBCLOG_ERROR_RETURN_UINT(rc); … … 59 51 60 52 61 unsigned _fmutex_open(_fmutex *sem) 62 { 63 LIBCLOG_ENTER("sem=%p{.pszDesc=%s}\n", (void *)sem, sem->pszDesc); 64 unsigned rc = DosOpenEventSemEx(NULL, (PHEV)&sem->hev); 65 if (!rc) 53 unsigned _fmutex_open(_fmutex *pSem) 54 { 55 LIBCLOG_ENTER("pSem=%p{.pszDesc=%s}\n", (void *)pSem, pSem->pszDesc); 56 __libc_Back_panic(0, NULL, "_fmutex_open: _FMC_SHARED isn't supported on NT. sorry.\n"); 57 } 58 59 60 unsigned _fmutex_close(_fmutex *pSem) 61 { 62 LIBCLOG_ENTER("pSem=%p{.pszDesc=%s}\n", (void *)pSem, pSem->pszDesc); 63 NTSTATUS rc = NtClose(pSem->hev); 64 if (NT_SUCCESS(rc)) 66 65 LIBCLOG_RETURN_UINT(rc); 67 66 LIBCLOG_ERROR_RETURN_UINT(rc); … … 69 68 70 69 71 unsigned _fmutex_close(_fmutex *sem) 72 { 73 LIBCLOG_ENTER("sem=%p{.pszDesc=%s}\n", (void *)sem, sem->pszDesc); 74 unsigned rc = DosCloseEventSemEx(sem->hev); 75 if (!rc) 76 LIBCLOG_RETURN_UINT(rc); 77 LIBCLOG_ERROR_RETURN_UINT(rc); 78 } 79 80 81 unsigned __fmutex_request_internal(_fmutex *sem, unsigned flags, signed char fs) 82 { 83 LIBCLOG_ENTER("sem=%p{.pszDesc=%s} flags=%#x fs=%#x\n", (void *)sem, sem->pszDesc, flags, (int)fs); 70 unsigned __fmutex_request_internal(_fmutex *pSem, unsigned flags, signed char fs) 71 { 72 LIBCLOG_ENTER("pSem=%p{.pszDesc=%s} flags=%#x fs=%#x\n", (void *)pSem, pSem->pszDesc, flags, (int)fs); 84 73 int rc; 85 74 … … 90 79 } 91 80 92 if (fs == _FMS_AUTO_INITIALIZE || !sem->hev) 93 { 94 HEV hev; 95 rc = DosCreateEventSemEx(NULL, &hev, sem->flags & _FMC_SHARED ? DC_SEM_SHARED : 0, FALSE); 96 if (rc) 97 { 98 LIBC_ASSERTM_FAILED("Failed to create event semaphore for fmutex '%s', rc=%d. flags=%#x\n", sem->pszDesc, rc, sem->flags); 99 LIBCLOG_RETURN_UINT(ERROR_INVALID_HANDLE); 100 } 101 if (__atomic_cmpxchg32((volatile uint32_t *)&sem->hev, hev, 0)) 102 { 103 LIBCLOG_MSG("auto initialized fmutex %p '%s'\n", (void *)sem, sem->pszDesc); 104 __atomic_xchg(&sem->Owner, fibGetTidPid()); 81 if (fs == _FMS_AUTO_INITIALIZE || !pSem->hev) 82 { 83 if (pSem->flags & _FMC_SHARED) 84 __libc_Back_panic(0, NULL, "_fmutex_request_internal: _FMC_SHARED isn't supported on NT. sorry.\n"); 85 86 HANDLE hev; 87 NTSTATUS rc = NtCreateEvent(&hev, EVENT_ALL_ACCESS, NULL, FALSE, FALSE); 88 if (!NT_SUCCESS(rc)) 89 { 90 LIBC_ASSERTM_FAILED("Failed to create event semaphore for fmutex '%s', rc=%d. flags=%#x\n", pSem->pszDesc, rc, pSem->flags); 91 LIBCLOG_RETURN_UINT(rc); 92 } 93 if (__atomic_cmpxchgptr(&pSem->hev, hev, 0)) 94 { 95 LIBCLOG_MSG("auto initialized fmutex %p '%s'\n", (void *)pSem, pSem->pszDesc); 96 __atomic_xchg(&pSem->Owner, fibGetTidPid()); 105 97 LIBCLOG_RETURN_UINT(NO_ERROR); 106 98 } 107 LIBCLOG_MSG("lost auto initialization race for fmutex %p '%s'\n", (void *) sem, sem->pszDesc);108 DosCloseEventSemEx(hev);99 LIBCLOG_MSG("lost auto initialization race for fmutex %p '%s'\n", (void *)pSem, pSem->pszDesc); 100 NtClose(hev); 109 101 fs = _FMS_OWNED_HARD; 110 102 } … … 114 106 if (fs == _FMS_OWNED_HARD) 115 107 { 116 if (__cxchg(& sem->fs, _FMS_OWNED_HARD) == _FMS_AVAILABLE)108 if (__cxchg(&pSem->fs, _FMS_OWNED_HARD) == _FMS_AVAILABLE) 117 109 { 118 __atomic_xchg(& sem->Owner, fibGetTidPid());110 __atomic_xchg(&pSem->Owner, fibGetTidPid()); 119 111 LIBCLOG_RETURN_UINT(0); 120 112 } 121 113 } 122 LIBCLOG_RETURN_UINT( ERROR_MUTEX_OWNED);114 LIBCLOG_RETURN_UINT(STATUS_TIMEOUT); 123 115 } 124 116 … … 126 118 { 127 119 ULONG ulCount; 128 FS_VAR(); 129 FS_SAVE_LOAD(); 130 rc = DosResetEventSem(sem->hev, &ulCount); 131 FS_RESTORE(); 132 if (rc != 0 && rc != ERROR_ALREADY_RESET) 133 LIBCLOG_RETURN_UINT(rc); 134 if (__cxchg(&sem->fs, _FMS_OWNED_HARD) == _FMS_AVAILABLE) 135 { 136 __atomic_xchg(&sem->Owner, fibGetTidPid()); 120 if (__cxchg(&pSem->fs, _FMS_OWNED_HARD) == _FMS_AVAILABLE) 121 { 122 __atomic_xchg(&pSem->Owner, fibGetTidPid()); 137 123 LIBCLOG_RETURN_UINT(0); 138 124 } 139 if ( sem->Owner == fibGetTidPid())140 { 141 __fmutex_deadlock( sem, "Recursive mutex!");125 if (pSem->Owner == fibGetTidPid()) 126 { 127 __fmutex_deadlock(pSem, "Recursive mutex!"); 142 128 LIBCLOG_RETURN_UINT(-1); 143 129 } 144 130 145 FS_SAVE_LOAD();146 147 131 for (;;) 148 132 { 149 rc = DosWaitEventSem(sem->hev, sem->flags & _FMC_SHARED ? SEM_INDEFINITE_WAIT : 3000); 150 if (rc == ERROR_INTERRUPT) 133 LARGE_INTEGER Interval; 134 Interval.QuadPart = -30000000; /* 3sec */ 135 rc = NtWaitForSingleObject(pSem->hev, TRUE, &Interval); 136 if (rc == STATUS_WAIT_0) 137 break; 138 if ( rc == STATUS_ALERTED 139 || rc == STATUS_TIMEOUT) 151 140 { 152 /* 153 * An interrupt occured, this might be a bug in the wait, or 154 * more likely someone is killing us. If we're dying/exiting or 155 * something along those lines, we return to the caller no matter 156 * what flags it specified. 157 */ 158 if (!(flags & _FMR_IGNINT)) 159 break; 160 if (fibIsInExit()) 161 break; 162 rc = ERROR_TIMEOUT; 141 /** @todo check for process termination and validate owner. */ 163 142 } 164 if (rc != ERROR_TIMEOUT)143 else if (NT_SUCCESS(rc)) 165 144 break; 166 /* 167 * Deadlock detection - check if owner is around. 168 */ 169 unsigned Owner = sem->Owner; 170 if (!Owner) 171 break; 172 rc = DosVerifyPidTid(Owner >> 16, Owner & 0xffff); 173 if (rc) 174 { 175 __fmutex_deadlock(sem, "Owner died!"); 176 rc = ERROR_SEM_OWNER_DIED; 177 break; 178 } 179 } 180 FS_RESTORE(); 181 if (rc != 0) 182 LIBCLOG_RETURN_UINT(rc); 183 } 184 } 185 186 unsigned __fmutex_request_internal_must_complete(_fmutex *sem, unsigned flags) 187 { 188 LIBCLOG_ENTER("sem=%p{.pszDesc=%s} flags=%#x\n", (void *)sem, sem->pszDesc, flags); 189 int rc; 190 ULONG ulNesting = 0; 191 signed char fs; 192 FS_VAR(); 193 194 if (sem->fs == _FMS_UNINIT) 195 { 196 LIBC_ASSERTM_FAILED("Invalid handle, fs == _FMS_UNINIT\n"); 197 LIBCLOG_RETURN_UINT(ERROR_INVALID_HANDLE); 198 } 199 200 FS_SAVE_LOAD(); 201 DosEnterMustComplete(&ulNesting); 202 fs = __cxchg(&sem->fs, _FMS_OWNED_SIMPLE); 145 else 146 LIBCLOG_ERROR_RETURN_UINT(rc); 147 } 148 } 149 } 150 151 unsigned __fmutex_request_internal_must_complete(_fmutex *pSem, unsigned flags) 152 { 153 LIBCLOG_ENTER("pSem=%p{.pszDesc=%s} flags=%#x\n", (void *)pSem, pSem->pszDesc, flags); 154 /** @todo figure out how to do must_complete stuff on NT. */ 155 unsigned rc; 156 signed char fs = __cxchg(&pSem->fs, _FMS_OWNED_SIMPLE); 203 157 if (fs == _FMS_AVAILABLE) 204 158 { 205 __atomic_xchg(&sem->Owner, fibGetTidPid()); 206 FS_RESTORE(); 207 LIBCLOG_RETURN_UINT(0); 208 } 209 210 if (fs == _FMS_AUTO_INITIALIZE || !sem->hev) 211 { 212 HEV hev; 213 rc = DosCreateEventSemEx(NULL, &hev, sem->flags & _FMC_SHARED ? DC_SEM_SHARED : 0, FALSE); 214 if (rc) 215 { 216 LIBC_ASSERTM_FAILED("Failed to create event semaphore for fmutex '%s', rc=%d. flags=%#x\n", sem->pszDesc, rc, sem->flags); 217 FS_RESTORE(); 218 LIBCLOG_RETURN_UINT(ERROR_INVALID_HANDLE); 219 } 220 if (__atomic_cmpxchg32((volatile uint32_t *)&sem->hev, hev, 0)) 221 { 222 LIBCLOG_MSG("auto initialized fmutex %p '%s'\n", (void *)sem, sem->pszDesc); 223 __atomic_xchg(&sem->Owner, fibGetTidPid()); 224 FS_RESTORE(); 225 LIBCLOG_RETURN_UINT(NO_ERROR); 226 } 227 LIBCLOG_MSG("lost auto initialization race for fmutex %p '%s'\n", (void *)sem, sem->pszDesc); 228 DosCloseEventSemEx(hev); 229 fs = _FMS_OWNED_HARD; 230 } 231 232 if (flags & _FMR_NOWAIT) 233 { 234 if (fs == _FMS_OWNED_HARD) 235 { 236 if (__cxchg(&sem->fs, _FMS_OWNED_HARD) == _FMS_AVAILABLE) 237 { 238 __atomic_xchg(&sem->Owner, fibGetTidPid()); 239 FS_RESTORE(); 240 LIBCLOG_RETURN_UINT(0); 241 } 242 } 243 DosExitMustComplete(&ulNesting); 244 FS_RESTORE(); 245 LIBCLOG_RETURN_UINT(ERROR_MUTEX_OWNED); 246 } 247 248 for (;;) 249 { 250 ULONG ulCount; 251 rc = DosResetEventSem(sem->hev, &ulCount); 252 if (rc != 0 && rc != ERROR_ALREADY_RESET) 253 { 254 DosExitMustComplete(&ulNesting); 255 FS_RESTORE(); 256 LIBCLOG_RETURN_UINT(rc); 257 } 258 if (__cxchg(&sem->fs, _FMS_OWNED_HARD) == _FMS_AVAILABLE) 259 { 260 __atomic_xchg(&sem->Owner, fibGetTidPid()); 261 FS_RESTORE(); 262 LIBCLOG_RETURN_UINT(0); 263 } 264 if (sem->Owner == fibGetTidPid()) 265 { 266 DosExitMustComplete(&ulNesting); 267 __fmutex_deadlock(sem, "Recursive mutex!"); 268 FS_RESTORE(); 269 LIBCLOG_RETURN_UINT(-1); 270 } 271 272 for (;;) 273 { 274 DosExitMustComplete(&ulNesting); 275 rc = DosWaitEventSem(sem->hev, sem->flags & _FMC_SHARED ? SEM_INDEFINITE_WAIT : 3000); 276 DosEnterMustComplete(&ulNesting); 277 if (rc == ERROR_INTERRUPT) 278 { 279 /* 280 * An interrupt occured, this might be a bug in the wait, or 281 * more likely someone is killing us. If we're dying/exiting or 282 * something along those lines, we return to the caller no matter 283 * what flags it specified. 284 */ 285 if (!(flags & _FMR_IGNINT)) 286 break; 287 if (fibIsInExit()) 288 break; 289 rc = ERROR_TIMEOUT; 290 } 291 if (rc != ERROR_TIMEOUT) 292 break; 293 /* 294 * Deadlock detection - check if owner is around. 295 */ 296 unsigned Owner = sem->Owner; 297 if (!Owner) 298 break; 299 rc = DosVerifyPidTid(Owner >> 16, Owner & 0xffff); 300 if (rc) 301 { 302 DosExitMustComplete(&ulNesting); 303 __fmutex_deadlock(sem, "Owner died!"); 304 rc = ERROR_SEM_OWNER_DIED; 305 DosEnterMustComplete(&ulNesting); 306 break; 307 } 308 } 309 FS_RESTORE(); 310 if (rc != 0) 311 { 312 DosExitMustComplete(&ulNesting); 313 FS_RESTORE(); 314 LIBCLOG_RETURN_UINT(rc); 315 } 316 } 159 __atomic_xchg(&pSem->Owner, fibGetTidPid()); 160 rc = 0; 161 } 162 else 163 rc = __fmutex_request_internal(pSem, flags, fs); 164 LIBCLOG_RETURN_UINT(rc); 317 165 } 318 166 … … 328 176 } 329 177 330 unsigned __fmutex_release_internal_must_complete(_fmutex *sem) 331 { 332 LIBCLOG_ENTER("sem=%p{.pszDesc=%s}\n", (void *)sem, sem->pszDesc); 333 ULONG ulNesting; 334 __atomic_xchg(&sem->Owner, 0); 335 signed char fs = __cxchg(&sem->fs, _FMS_AVAILABLE); 178 unsigned __fmutex_release_internal_must_complete(_fmutex *pSem) 179 { 180 LIBCLOG_ENTER("pSem=%p{.pszDesc=%s}\n", (void *)pSem, pSem->pszDesc); 181 /** @todo figure out how to do must_complete stuff on NT. */ 182 __atomic_xchg(&pSem->Owner, 0); 183 signed char fs = __cxchg(&pSem->fs, _FMS_AVAILABLE); 184 unsigned rc; 336 185 if (fs != _FMS_OWNED_HARD) 337 { 338 FS_VAR_SAVE_LOAD(); 339 DosExitMustComplete(&ulNesting); 340 FS_RESTORE(); 341 LIBCLOG_RETURN_UINT(0); 342 } 186 rc = 0; 343 187 else 344 { 345 int rc = __fmutex_release_internal (sem); 346 FS_VAR_SAVE_LOAD(); 347 DosExitMustComplete(&ulNesting); 348 FS_RESTORE(); 349 LIBCLOG_RETURN_UINT(rc); 350 } 351 } 352 353 unsigned __fmutex_release_internal(_fmutex *sem) 354 { 355 LIBCLOG_ENTER("sem=%p{.pszDesc=%s}\n", (void *)sem, sem->pszDesc); 356 unsigned rc; 357 FS_VAR(); 358 359 FS_SAVE_LOAD(); 360 rc = DosPostEventSem(sem->hev); 361 if (rc != 0 && rc != ERROR_ALREADY_POSTED) 362 { 363 FS_RESTORE(); 364 LIBCLOG_RETURN_UINT(rc); 365 } 188 rc = __fmutex_release_internal(pSem); 189 LIBCLOG_RETURN_UINT(rc); 190 } 191 192 unsigned __fmutex_release_internal(_fmutex *pSem) 193 { 194 LIBCLOG_ENTER("pSem=%p{.pszDesc=%s}\n", (void *)pSem, pSem->pszDesc); 195 196 197 NTSTATUS rc = NtSetEvent(pSem->hev, NULL); 198 if (!NT_SUCCESS(rc)) 199 LIBCLOG_ERROR_RETURN_UINT(rc); 366 200 367 201 /* Give up our time slice to give other threads a chance. Without … … 370 204 _fmutex semaphore from running, forever. 371 205 372 Why? Without DosSleep, the thread will keep the CPU for the rest 373 of the time slice. It may request (and get) the semaphore again 374 in the same time slice, perhaps multiple times. Assume that the 375 semaphore is still owned at the end of the time slice. In one of 376 the next time slices, all the other threads blocking on the 377 semaphore will wake up for a short while only to see that the 378 semaphore is owned; they will all go sleeping again. The thread 379 which owns the semaphore will get the CPU again. And may happen 380 to own the semaphore again at the end of the time slice. And so 381 on. DosSleep reduces that problem a bit. 382 383 Even with DosSleep(0), assignment of time slices to threads 384 requesting a _fmutex semaphore can be quite unbalanced: The more 385 frequently a thread requests a _fmutex semaphore, the more CPU 386 time it will get. In consequence, a thread which only rarely 387 needs the resource protected by the _fmutex semaphore will get 388 much less CPU time than threads competing heavily for the 389 resource. 390 391 DosSleep(1) would make _fmutex semaphores behave a bit better, 392 but would also give up way too much CPU time (in the average, 393 half a time slice (or one and a half?) per call of this 394 function). 395 396 DosReleaseMutexSem does a better job; it gives the time slice to 397 the thread which has waited longest on the semaphore (if all the 398 threads have the same priority). 399 400 Unfortunately, we cannot use an HMTX instead of an HEV because 401 only the owner (the thread which got assigned ownership by 402 DosRequestMutexSem) can release the HMTX with DosReleaseMutexSem. 403 If we could, that would take advantage of the FIFO of blocked 404 threads maintained by the kernel for each HMTX. 405 406 Using an HMTX would require the first thread requesting an owned 407 _fmutex semaphore to request the HMTX on behalf of the thread 408 owning the _fmutex semaphore. */ 409 410 DosSleep(0); 411 FS_RESTORE(); 206 Read the rest of the rant in fmutex-os2.c */ 207 ZwYieldExecution(); 412 208 LIBCLOG_RETURN_UINT(0); 413 209 } 414 210 415 211 416 void _fmutex_dummy(_fmutex * sem)417 { 418 LIBCLOG_ENTER(" sem=%p\n", (void *)sem);419 sem->hev = 0;420 sem->fs = _FMS_AVAILABLE;421 sem->flags = _FMC_DUMMY;422 sem->Owner = 0;423 sem->pszDesc = "dummy";212 void _fmutex_dummy(_fmutex *pSem) 213 { 214 LIBCLOG_ENTER("pSem=%p\n", (void *)pSem); 215 pSem->hev = 0; 216 pSem->fs = _FMS_AVAILABLE; 217 pSem->flags = _FMC_DUMMY; 218 pSem->Owner = 0; 219 pSem->pszDesc = "dummy"; 424 220 LIBCLOG_RETURN_VOID(); 425 221 } -
trunk/libc/src/libc/process/nt/smutex-nt.c
r2719 r2723 2 2 3 3 #include "libc-alias.h" 4 #define INCL_DOSPROCESS 5 #define INCL_FSMACROS 6 #include <os2.h> 4 #include <klibc/nt/nt.h> 7 5 #include <sys/builtin.h> 8 6 #include <sys/smutex.h> 9 #include <InnoTekLIBC/FastInfoBlocks.h>10 7 #include <InnoTekLIBC/backend.h> 11 8 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_MUTEX … … 13 10 14 11 15 void __smutex_request_internal(volatile _smutex * sem)12 void __smutex_request_internal(volatile _smutex *pSem) 16 13 { 17 LIBCLOG_ENTER("sem=%p\n", sem); 18 FS_VAR(); 19 FS_SAVE_LOAD(); 20 DosSleep(1); 21 while (__cxchg(sem, 1) != 0) 22 { 23 if (fibIsInExit()) 24 { 25 __libc_Back_panic(0, NULL, "smutex deadlock: %p\n", sem); 26 break; 27 } 28 DosSleep(1); 29 } 30 FS_RESTORE(); 14 LIBCLOG_ENTER("pSem=%p\n", pSem); 15 do 16 ZwYieldExecution(); 17 while (__cxchg(pSem, 1)); 31 18 LIBCLOG_RETURN_VOID(); 32 19 } 20 -
trunk/libc/src/libc/process/os2/fmutex-os2.c
r2719 r2723 362 362 { 363 363 FS_RESTORE(); 364 LIBCLOG_ RETURN_UINT(rc);364 LIBCLOG_ERROR_RETURN_UINT(rc); 365 365 } 366 366
Note:
See TracChangeset
for help on using the changeset viewer.