Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Missing TCL_NORETURN for Tcl_ExitThread() (and TclpThreadExit()). Backported from 8.7/9.0. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | core-8-6-branch |
Files: | files | file ages | folders |
SHA3-256: |
5103ed9db220640ca9905c0fbfb23093 |
User & Date: | jan.nijtmans 2024-04-29 07:12:31 |
Context
2024-04-29
| ||
10:06 | TCL_NORETURN1 is empty for extensions, just not for Tcl and Tk builds. Why? Backport changing this f... check-in: 93a57aa32c user: jan.nijtmans tags: core-8-6-branch | |
08:26 | Merge 8.6 check-in: 78280ba2b5 user: jan.nijtmans tags: core-8-branch | |
07:12 | Missing TCL_NORETURN for Tcl_ExitThread() (and TclpThreadExit()). Backported from 8.7/9.0. check-in: 5103ed9db2 user: jan.nijtmans tags: core-8-6-branch | |
2024-04-26
| ||
14:50 | Fix clang warning: tclWinTime.c:84:6: error: suggest braces around initialization of subobject [-Wer... check-in: c9564c2520 user: jan.nijtmans tags: core-8-6-branch | |
Changes
Changes to generic/tcl.decls.
︙ | ︙ | |||
1054 1055 1056 1057 1058 1059 1060 | int Tcl_EvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags) } declare 293 { int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags) } declare 294 { | | | 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 | int Tcl_EvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags) } declare 293 { int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags) } declare 294 { TCL_NORETURN void Tcl_ExitThread(int status) } declare 295 { int Tcl_ExternalToUtf(Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr) } |
︙ | ︙ |
Changes to generic/tclDecls.h.
︙ | ︙ | |||
873 874 875 876 877 878 879 | /* 292 */ EXTERN int Tcl_EvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 293 */ EXTERN int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 294 */ | | | 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 | /* 292 */ EXTERN int Tcl_EvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 293 */ EXTERN int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 294 */ EXTERN TCL_NORETURN void Tcl_ExitThread(int status); /* 295 */ EXTERN int Tcl_ExternalToUtf(Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); |
︙ | ︙ | |||
2201 2202 2203 2204 2205 2206 2207 | Tcl_Encoding (*tcl_CreateEncoding) (const Tcl_EncodingType *typePtr); /* 287 */ void (*tcl_CreateThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 288 */ void (*tcl_DeleteThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 289 */ void (*tcl_DiscardResult) (Tcl_SavedResult *statePtr); /* 290 */ int (*tcl_EvalEx) (Tcl_Interp *interp, const char *script, int numBytes, int flags); /* 291 */ int (*tcl_EvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 292 */ int (*tcl_EvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 293 */ | | | 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 | Tcl_Encoding (*tcl_CreateEncoding) (const Tcl_EncodingType *typePtr); /* 287 */ void (*tcl_CreateThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 288 */ void (*tcl_DeleteThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 289 */ void (*tcl_DiscardResult) (Tcl_SavedResult *statePtr); /* 290 */ int (*tcl_EvalEx) (Tcl_Interp *interp, const char *script, int numBytes, int flags); /* 291 */ int (*tcl_EvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 292 */ int (*tcl_EvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 293 */ TCL_NORETURN1 void (*tcl_ExitThread) (int status); /* 294 */ int (*tcl_ExternalToUtf) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 295 */ char * (*tcl_ExternalToUtfDString) (Tcl_Encoding encoding, const char *src, int srcLen, Tcl_DString *dsPtr); /* 296 */ void (*tcl_FinalizeThread) (void); /* 297 */ void (*tcl_FinalizeNotifier) (ClientData clientData); /* 298 */ void (*tcl_FreeEncoding) (Tcl_Encoding encoding); /* 299 */ Tcl_ThreadId (*tcl_GetCurrentThread) (void); /* 300 */ Tcl_Encoding (*tcl_GetEncoding) (Tcl_Interp *interp, const char *name); /* 301 */ |
︙ | ︙ |
Changes to generic/tclEvent.c.
︙ | ︙ | |||
988 989 990 991 992 993 994 | * Tcl_Channels that may have data enqueued. */ FinalizeThread(/* quick */ 1); } } | | < | 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 | * Tcl_Channels that may have data enqueued. */ FinalizeThread(/* quick */ 1); } } exit(status); } /* *------------------------------------------------------------------------- * * TclInitSubsystems -- * |
︙ | ︙ |
Changes to generic/tclInt.h.
︙ | ︙ | |||
3116 3117 3118 3119 3120 3121 3122 | Tcl_PathPart portion); MODULE_SCOPE char * TclpReadlink(const char *fileName, Tcl_DString *linkPtr); MODULE_SCOPE void TclpSetVariables(Tcl_Interp *interp); MODULE_SCOPE void * TclThreadStorageKeyGet(Tcl_ThreadDataKey *keyPtr); MODULE_SCOPE void TclThreadStorageKeySet(Tcl_ThreadDataKey *keyPtr, void *data); | | | 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 | Tcl_PathPart portion); MODULE_SCOPE char * TclpReadlink(const char *fileName, Tcl_DString *linkPtr); MODULE_SCOPE void TclpSetVariables(Tcl_Interp *interp); MODULE_SCOPE void * TclThreadStorageKeyGet(Tcl_ThreadDataKey *keyPtr); MODULE_SCOPE void TclThreadStorageKeySet(Tcl_ThreadDataKey *keyPtr, void *data); MODULE_SCOPE void TCL_NORETURN TclpThreadExit(int status); MODULE_SCOPE void TclRememberCondition(Tcl_Condition *mutex); MODULE_SCOPE void TclRememberJoinableThread(Tcl_ThreadId id); MODULE_SCOPE void TclRememberMutex(Tcl_Mutex *mutex); MODULE_SCOPE void TclRemoveScriptLimitCallbacks(Tcl_Interp *interp); MODULE_SCOPE int TclReToGlob(Tcl_Interp *interp, const char *reStr, int reStrLen, Tcl_DString *dsPtr, int *flagsPtr, int *quantifiersFoundPtr); |
︙ | ︙ |
Changes to generic/tclPanic.c.
︙ | ︙ | |||
72 73 74 75 76 77 78 | * * Side effects: * The process dies, entering the debugger if possible. * *---------------------------------------------------------------------- */ | | | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | * * Side effects: * The process dies, entering the debugger if possible. * *---------------------------------------------------------------------- */ TCL_NORETURN void Tcl_PanicVA( const char *format, /* Format string, suitable for passing to * fprintf. */ va_list argList) /* Variable argument list. */ { char *arg1, *arg2, *arg3; /* Additional arguments (variable in number) * to pass to fprintf. */ |
︙ | ︙ | |||
102 103 104 105 106 107 108 109 | tclWinDebugPanic(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); #endif } else { fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); fprintf(stderr, "\n"); fflush(stderr); #if defined(_WIN32) || defined(__CYGWIN__) | > | | | | | | | | | | | < | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | tclWinDebugPanic(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); #endif } else { fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); fprintf(stderr, "\n"); fflush(stderr); } #if defined(_WIN32) || defined(__CYGWIN__) #if defined(__GNUC__) __builtin_trap(); #elif defined(_WIN64) __debugbreak(); #elif defined(_MSC_VER) && defined (_M_IX86) _asm {int 3} #else DebugBreak(); #endif #endif #if defined(_WIN32) ExitProcess(1); #else abort(); #endif } /* *---------------------------------------------------------------------- * * Tcl_Panic -- * |
︙ | ︙ | |||
145 146 147 148 149 150 151 | /* * The following comment is here so that Coverity's static analyzer knows that * a Tcl_Panic() call can never return and avoids lots of false positives. */ /* coverity[+kill] */ | | < | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | /* * The following comment is here so that Coverity's static analyzer knows that * a Tcl_Panic() call can never return and avoids lots of false positives. */ /* coverity[+kill] */ TCL_NORETURN void Tcl_Panic( const char *format, ...) { va_list argList; va_start(argList, format); Tcl_PanicVA(format, argList); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ |
Changes to generic/tclTest.c.
︙ | ︙ | |||
815 816 817 818 819 820 821 | } else if (strcmp(argv[1], "marklater") == 0) { if (argc != 3) { goto wrongNumArgs; } if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) { return TCL_ERROR; } | | | | 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 | } else if (strcmp(argv[1], "marklater") == 0) { if (argc != 3) { goto wrongNumArgs; } if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) { return TCL_ERROR; } Tcl_MutexLock(&asyncTestMutex); for (asyncPtr = firstHandler; asyncPtr != NULL; asyncPtr = asyncPtr->nextPtr) { if (asyncPtr->id == id) { Tcl_ThreadId threadID; if (Tcl_CreateThread(&threadID, AsyncThreadProc, INT2PTR(id), TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS) != TCL_OK) { Tcl_AppendResult(interp, "can't create thread", NULL); Tcl_MutexUnlock(&asyncTestMutex); return TCL_ERROR; } break; } } Tcl_MutexUnlock(&asyncTestMutex); } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be create, delete, int, mark, or marklater", NULL); return TCL_ERROR; #else /* !TCL_THREADS */ } else { Tcl_AppendResult(interp, "bad option \"", argv[1], |
︙ | ︙ |
Changes to generic/tclThread.c.
︙ | ︙ | |||
464 465 466 467 468 469 470 | * * Side effects: * All thread exit handlers are invoked, then the thread dies. * *---------------------------------------------------------------------- */ | | > > | 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 | * * Side effects: * All thread exit handlers are invoked, then the thread dies. * *---------------------------------------------------------------------- */ TCL_NORETURN void Tcl_ExitThread( int status) { Tcl_FinalizeThread(); #ifdef TCL_THREADS TclpThreadExit(status); #else exit(status); #endif } #ifndef TCL_THREADS /* *---------------------------------------------------------------------- |
︙ | ︙ |
Changes to unix/tclUnixThrd.c.
︙ | ︙ | |||
184 185 186 187 188 189 190 | * * Side effects: * This procedure terminates the current thread. * *---------------------------------------------------------------------- */ | | | 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | * * Side effects: * This procedure terminates the current thread. * *---------------------------------------------------------------------- */ TCL_NORETURN void TclpThreadExit( int status) { pthread_exit(INT2PTR(status)); } #endif /* TCL_THREADS */ |
︙ | ︙ |
Changes to win/tclWinError.c.
1 2 3 4 5 6 | /* * tclWinError.c -- * * This file contains code for converting from Win32 errors to errno * errors. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* * tclWinError.c -- * * This file contains code for converting from Win32 errors to errno * errors. * * Copyright (c) 1995-1996 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* |
︙ | ︙ | |||
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 | * * Side effects: * None. * *---------------------------------------------------------------------- */ TCL_NORETURN void tclWinDebugPanic( const char *format, ...) { #define TCL_MAX_WARN_LEN 1024 va_list argList; va_start(argList, format); if (IsDebuggerPresent()) { WCHAR msgString[TCL_MAX_WARN_LEN]; | > > > | | | | 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | * * Side effects: * None. * *---------------------------------------------------------------------- */ MODULE_SCOPE TCL_NORETURN void tclWinDebugPanic(const char *format, ...); TCL_NORETURN void tclWinDebugPanic( const char *format, ...) { #define TCL_MAX_WARN_LEN 1024 va_list argList; va_start(argList, format); if (IsDebuggerPresent()) { WCHAR msgString[TCL_MAX_WARN_LEN]; char buf[TCL_MAX_WARN_LEN * 3]; vsnprintf(buf, sizeof(buf), format, argList); msgString[TCL_MAX_WARN_LEN-1] = '\0'; MultiByteToWideChar(CP_UTF8, 0, buf, -1, msgString, TCL_MAX_WARN_LEN); /* * Truncate MessageBox string if it is too long to not overflow the buffer. */ if (msgString[TCL_MAX_WARN_LEN-1] != '\0') { memcpy(msgString + (TCL_MAX_WARN_LEN - 5), L" ...", 5 * sizeof(WCHAR)); } OutputDebugStringW(msgString); } else { vfprintf(stderr, format, argList); fprintf(stderr, "\n"); fflush(stderr); |
︙ | ︙ |
Changes to win/tclWinThrd.c.
1 2 3 4 5 | /* * tclWinThread.c -- * * This file implements the Windows-specific thread operations. * | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /* * tclWinThread.c -- * * This file implements the Windows-specific thread operations. * * Copyright (c) 1998 Sun Microsystems, Inc. * Copyright (c) 1999 Scriptics Corporation * Copyright (c) 2008 George Peter Staplin * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclWinInt.h" |
︙ | ︙ | |||
25 26 27 28 29 30 31 | /* * This is the global lock used to serialize access to other serialization * data structures. */ static CRITICAL_SECTION globalLock; | | < < < | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | /* * This is the global lock used to serialize access to other serialization * data structures. */ static CRITICAL_SECTION globalLock; static int initialized = 0; /* * This is the global lock used to serialize initialization and finalization * of Tcl as a whole. */ static CRITICAL_SECTION initLock; |
︙ | ︙ | |||
210 211 212 213 214 215 216 | Tcl_ThreadId *idPtr, /* Return, the ID of the thread. */ Tcl_ThreadCreateProc *proc, /* Main() function of the thread. */ ClientData clientData, /* The one argument to Main(). */ int stackSize, /* Size of stack for the new thread. */ int flags) /* Flags controlling behaviour of the new * thread. */ { | | | < | | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | Tcl_ThreadId *idPtr, /* Return, the ID of the thread. */ Tcl_ThreadCreateProc *proc, /* Main() function of the thread. */ ClientData clientData, /* The one argument to Main(). */ int stackSize, /* Size of stack for the new thread. */ int flags) /* Flags controlling behaviour of the new * thread. */ { WinThread *winThreadPtr; /* Per-thread startup info */ HANDLE tHandle; winThreadPtr = (WinThread *)ckalloc(sizeof(WinThread)); winThreadPtr->lpStartAddress = (LPTHREAD_START_ROUTINE) proc; winThreadPtr->lpParameter = clientData; winThreadPtr->fpControl = _controlfp(0, 0); EnterCriticalSection(&joinLock); *idPtr = 0; /* must initialize as Tcl_Thread is a pointer and * on WIN64 sizeof void* != sizeof unsigned */ #if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__) tHandle = (HANDLE) _beginthreadex(NULL, (unsigned) stackSize, (Tcl_ThreadCreateProc*) TclWinThreadStart, winThreadPtr, 0, (unsigned *)idPtr); #else tHandle = CreateThread(NULL, (DWORD)stackSize, TclWinThreadStart, winThreadPtr, 0, (LPDWORD)idPtr); #endif if (tHandle == NULL) { LeaveCriticalSection(&joinLock); return TCL_ERROR; } else { |
︙ | ︙ | |||
294 295 296 297 298 299 300 | * * Side effects: * This procedure terminates the current thread. * *---------------------------------------------------------------------- */ | | | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | * * Side effects: * This procedure terminates the current thread. * *---------------------------------------------------------------------- */ TCL_NORETURN void TclpThreadExit( int status) { EnterCriticalSection(&joinLock); TclSignalExitThread(Tcl_GetCurrentThread(), status); LeaveCriticalSection(&joinLock); |
︙ | ︙ | |||
328 329 330 331 332 333 334 | * *---------------------------------------------------------------------- */ Tcl_ThreadId Tcl_GetCurrentThread(void) { | | | 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | * *---------------------------------------------------------------------- */ Tcl_ThreadId Tcl_GetCurrentThread(void) { return (Tcl_ThreadId)INT2PTR(GetCurrentThreadId()); } /* *---------------------------------------------------------------------- * * TclpInitLock * |
︙ | ︙ | |||
353 354 355 356 357 358 359 | * *---------------------------------------------------------------------- */ void TclpInitLock(void) { | | | | 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | * *---------------------------------------------------------------------- */ void TclpInitLock(void) { if (!initialized) { /* * There is a fundamental race here that is solved by creating the * first Tcl interpreter in a single threaded environment. Once the * interpreter has been created, it is safe to create more threads * that create interpreters in parallel. */ initialized = 1; InitializeCriticalSection(&joinLock); InitializeCriticalSection(&initLock); InitializeCriticalSection(&globalLock); } EnterCriticalSection(&initLock); } |
︙ | ︙ | |||
415 416 417 418 419 420 421 | * *---------------------------------------------------------------------- */ void TclpGlobalLock(void) { | | | | 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 | * *---------------------------------------------------------------------- */ void TclpGlobalLock(void) { if (!initialized) { /* * There is a fundamental race here that is solved by creating the * first Tcl interpreter in a single threaded environment. Once the * interpreter has been created, it is safe to create more threads * that create interpreters in parallel. */ initialized = 1; InitializeCriticalSection(&joinLock); InitializeCriticalSection(&initLock); InitializeCriticalSection(&globalLock); } EnterCriticalSection(&globalLock); } |
︙ | ︙ | |||
490 491 492 493 494 495 496 | return NULL; #endif } /* *---------------------------------------------------------------------- * | | | | | 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 | return NULL; #endif } /* *---------------------------------------------------------------------- * * TclFinalizeLock * * This procedure is used to destroy all private resources used in this * file. * * Results: * None. * * Side effects: * Destroys everything private. TclpInitLock must be held entering this * function. * *---------------------------------------------------------------------- */ void TclFinalizeLock(void) { TclpGlobalLock(); DeleteCriticalSection(&joinLock); /* * Destroy the critical section that we are holding! */ DeleteCriticalSection(&globalLock); initialized = 0; #ifdef TCL_THREADS if (allocOnce) { DeleteCriticalSection(&allocLock.crit); allocOnce = 0; } #endif |
︙ | ︙ | |||
563 564 565 566 567 568 569 | void Tcl_MutexLock( Tcl_Mutex *mutexPtr) /* The lock */ { CRITICAL_SECTION *csPtr; if (*mutexPtr == NULL) { | | | | 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 | void Tcl_MutexLock( Tcl_Mutex *mutexPtr) /* The lock */ { CRITICAL_SECTION *csPtr; if (*mutexPtr == NULL) { TclpGlobalLock(); /* * Double inside global lock check to avoid a race. */ if (*mutexPtr == NULL) { csPtr = (CRITICAL_SECTION *)ckalloc(sizeof(CRITICAL_SECTION)); InitializeCriticalSection(csPtr); *mutexPtr = (Tcl_Mutex)csPtr; TclRememberMutex(mutexPtr); } TclpGlobalUnlock(); } csPtr = *((CRITICAL_SECTION **)mutexPtr); EnterCriticalSection(csPtr); } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
677 678 679 680 681 682 683 | /* * Self initialize the two parts of the condition. The per-condition and * per-thread parts need to be handled independently. */ if (tsdPtr->flags == WIN_THREAD_UNINIT) { | | | | | | 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 | /* * Self initialize the two parts of the condition. The per-condition and * per-thread parts need to be handled independently. */ if (tsdPtr->flags == WIN_THREAD_UNINIT) { TclpGlobalLock(); /* * Create the per-thread event and queue pointers. */ if (tsdPtr->flags == WIN_THREAD_UNINIT) { tsdPtr->condEvent = CreateEventW(NULL, TRUE /* manual reset */, FALSE /* non signaled */, NULL); tsdPtr->nextPtr = NULL; tsdPtr->prevPtr = NULL; tsdPtr->flags = WIN_THREAD_RUNNING; doExit = 1; } TclpGlobalUnlock(); if (doExit) { /* * Create a per-thread exit handler to clean up the condEvent. We * must be careful to do this outside the Global Lock because * Tcl_CreateThreadExitHandler uses its own ThreadSpecificData, * and initializing that may drop back into the Global Lock. */ Tcl_CreateThreadExitHandler(FinalizeConditionEvent, tsdPtr); } } if (*condPtr == NULL) { TclpGlobalLock(); /* * Initialize the per-condition queue pointers and Mutex. */ if (*condPtr == NULL) { winCondPtr = (WinCondition *)ckalloc(sizeof(WinCondition)); InitializeCriticalSection(&winCondPtr->condLock); winCondPtr->firstPtr = NULL; winCondPtr->lastPtr = NULL; *condPtr = (Tcl_Condition) winCondPtr; TclRememberCondition(condPtr); } TclpGlobalUnlock(); } csPtr = *((CRITICAL_SECTION **)mutexPtr); winCondPtr = *((WinCondition **)condPtr); if (timePtr == NULL) { wtime = INFINITE; } else { wtime = timePtr->sec * 1000 + timePtr->usec / 1000; |
︙ | ︙ |