| ︙ | | |
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
-
-
-
-
-
-
-
-
-
-
|
#ifndef _MCW_EM
# define _MCW_EM 0x0008001F /* Error masks */
# define _MCW_RC 0x00000300 /* Rounding */
# define _MCW_PC 0x00030000 /* Precision */
_CRTIMP unsigned int __cdecl _controlfp (unsigned int unNew, unsigned int unMask);
#endif
/*
* This is the number of milliseconds to wait between internal retries in
* the Tcl_MutexLock function. This value must be greater than or equal
* to zero and should be a suitable value for the given platform.
*/
#ifndef TCL_MUTEX_LOCK_SLEEP_TIME
# define TCL_MUTEX_LOCK_SLEEP_TIME (0)
#endif
/*
* This is the master lock used to serialize access to other serialization
* data structures.
*/
static CRITICAL_SECTION masterLock;
static int init = 0;
|
| ︙ | | |
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
-
-
-
-
-
-
-
|
CRITICAL_SECTION crit;
} allocLock;
static Tcl_Mutex allocLockPtr = &allocLock;
static int allocOnce = 0;
#endif /* TCL_THREADS */
/*
* The mutexLock serializes Tcl_MutexLock. This is necessary to prevent
* races when finalizing a mutex that some other thread may want to lock.
*/
static CRITICAL_SECTION mutexLock;
/*
* The joinLock serializes Create- and ExitThread. This is necessary to
* prevent a race where a new joinable thread exits before the creating thread
* had the time to create the necessary data structures in the emulation
* layer.
*/
|
| ︙ | | |
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
|
365
366
367
368
369
370
371
372
373
374
375
376
377
378
|
-
|
* 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.
*/
init = 1;
InitializeCriticalSection(&mutexLock);
InitializeCriticalSection(&joinLock);
InitializeCriticalSection(&initLock);
InitializeCriticalSection(&masterLock);
}
EnterCriticalSection(&initLock);
}
|
| ︙ | | |
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
|
512
513
514
515
516
517
518
519
520
521
522
523
524
525
|
-
|
*----------------------------------------------------------------------
*/
void
TclFinalizeLock(void)
{
MASTER_LOCK;
DeleteCriticalSection(&mutexLock);
DeleteCriticalSection(&joinLock);
/*
* Destroy the critical section that we are holding!
*/
DeleteCriticalSection(&masterLock);
|
| ︙ | | |
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
|
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
|
-
+
-
-
-
+
+
-
-
-
-
+
+
+
-
-
-
-
-
-
|
csPtr = ckalloc(sizeof(CRITICAL_SECTION));
InitializeCriticalSection(csPtr);
*mutexPtr = (Tcl_Mutex)csPtr;
TclRememberMutex(mutexPtr);
}
MASTER_UNLOCK;
}
while (1) {
EnterCriticalSection(&mutexLock);
csPtr = *((CRITICAL_SECTION **)mutexPtr);
if (csPtr == NULL) {
csPtr = *((CRITICAL_SECTION **)mutexPtr);
if (csPtr == NULL) {
LeaveCriticalSection(&mutexLock);
goto retry;
}
if (TryEnterCriticalSection(csPtr)) {
goto retry;
}
EnterCriticalSection(csPtr);
LeaveCriticalSection(&mutexLock);
return;
}
LeaveCriticalSection(&mutexLock);
Tcl_Sleep(TCL_MUTEX_LOCK_SLEEP_TIME);
}
}
/*
*----------------------------------------------------------------------
*
* Tcl_MutexUnlock --
*
|
| ︙ | | |