Diff
Not logged in

Differences From Artifact [dccd3ec028]:

To Artifact [017176e5b1]:


1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * tclWinThread.c --
 *
 *	This file implements the Windows-specific thread operations.
 *
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWinThrd.c,v 1.8 2000/04/20 01:30:20 hobbs Exp $
 * RCS: @(#) $Id: tclWinThrd.c,v 1.9 2000/05/02 22:02:38 kupries Exp $
 */

#include "tclWinInt.h"

#include <dos.h>
#include <fcntl.h>
#include <io.h>
40
41
42
43
44
45
46









47
48
49
50
51
52
53
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62







+
+
+
+
+
+
+
+
+







 * allocLock is used by Tcl's version of malloc for synchronization.
 * For obvious reasons, cannot use any dyamically allocated storage.
 */

static CRITICAL_SECTION allocLock;
static Tcl_Mutex allocLockPtr = (Tcl_Mutex) &allocLock;

/*
 * 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.
 */

static CRITICAL_SECTION joinLock;

/*
 * Condition variables are implemented with a combination of a 
 * per-thread Windows Event and a per-condition waiting queue.
 * The idea is that each thread has its own Event that it waits
 * on when it is doing a ConditionWait; it uses the same event for
 * all condition variables because it only waits on one at a time.
 * Each condition variable has a queue of waiting threads, and a 
120
121
122
123
124
125
126


127
128
129

130

131
132





133
134
135



























136
137
138
139
140
141
142
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187







+
+



+

+


+
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    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 */
{
    unsigned long code;

    EnterCriticalSection(&joinLock);

    code = _beginthreadex(NULL, stackSize, proc, clientData, 0,
	(unsigned *)idPtr);

    if (code == 0) {
        LeaveCriticalSection(&joinLock);
	return TCL_ERROR;
    } else {
        if (flags & TCL_THREAD_JOINABLE) {
	    TclRememberJoinableThread (*idPtr);
	}

	LeaveCriticalSection(&joinLock);
	return TCL_OK;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_JoinThread --
 *
 *	This procedure waits upon the exit of the specified thread.
 *
 * Results:
 *	TCL_OK if the wait was successful, TCL_ERROR else.
 *
 * Side effects:
 *	The result area is set to the exit code of the thread we
 *	waited upon.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_JoinThread(id, result)
    Tcl_ThreadId id;	/* Id of the thread to wait upon */
    int*     result;	/* Reference to the storage the result
			 * of the thread we wait upon will be
			 * written into. */
{
    return TclJoinThread (id, result);
}

/*
 *----------------------------------------------------------------------
 *
 * TclpThreadExit --
 *
 *	This procedure terminates the current thread.
150
151
152
153
154
155
156




157
158
159
160
161
162
163
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212







+
+
+
+







 *----------------------------------------------------------------------
 */

void
TclpThreadExit(status)
    int status;
{
    EnterCriticalSection(&joinLock);
    TclSignalExitThread (Tcl_GetCurrentThread (), status);
    LeaveCriticalSection(&joinLock);

    _endthreadex((DWORD)status);
}


/*
 *----------------------------------------------------------------------
 *
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
654
655
656
657
658
659
660

661
662
663
664
665
666
667
668







-
+








/*
 *----------------------------------------------------------------------
 *
 * Tcl_ConditionWait --
 *
 *	This procedure is invoked to wait on a condition variable.
 *	The mutex is automically released as part of the wait, and
 *	The mutex is atomically released as part of the wait, and
 *	automatically grabbed when the condition is signaled.
 *
 *	The mutex must be held when this procedure is called.
 *
 * Results:
 *	None.
 *
643
644
645
646
647
648
649
650

651
652
653
654
655
656
657
692
693
694
695
696
697
698

699
700
701
702
703
704
705
706







-
+







	 * No more per-thread event on which to wait.
	 */

	return;
    }

    /*
     * Self initialize the two parts of the contition.
     * 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) {
	MASTER_LOCK;

668
669
670
671
672
673
674
675

676
677
678
679
680
681
682
717
718
719
720
721
722
723

724
725
726
727
728
729
730
731







-
+







	    doExit = 1;
	}
	MASTER_UNLOCK;

	if (doExit) {
	    /*
	     * Create a per-thread exit handler to clean up the condEvent.
	     * We must be careful do do this outside the Master Lock
	     * We must be careful to do this outside the Master Lock
	     * because Tcl_CreateThreadExitHandler uses its own
	     * ThreadSpecificData, and initializing that may drop
	     * back into the Master Lock.
	     */
	    
	    Tcl_CreateThreadExitHandler(FinalizeConditionEvent,
		    (ClientData) tsdPtr);