1 |
/* $Header$ */ |
/* $Header$ */ |
2 |
/* |
/* |
3 |
* tclThread.c -- |
* tclThread.c -- |
4 |
* |
* |
5 |
* This file implements Platform independent thread operations. |
* This file implements Platform independent thread operations. |
6 |
* Most of the real work is done in the platform dependent files. |
* Most of the real work is done in the platform dependent files. |
7 |
* |
* |
8 |
* Copyright (c) 1998 by Sun Microsystems, Inc. |
* Copyright (c) 1998 by Sun Microsystems, Inc. |
9 |
* |
* |
10 |
* See the file "license.terms" for information on usage and redistribution |
* See the file "license.terms" for information on usage and redistribution |
11 |
* of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
* of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
12 |
* |
* |
13 |
* RCS: @(#) $Id: tclthread.c,v 1.1.1.1 2001/06/13 04:46:27 dtashley Exp $ |
* RCS: @(#) $Id: tclthread.c,v 1.1.1.1 2001/06/13 04:46:27 dtashley Exp $ |
14 |
*/ |
*/ |
15 |
|
|
16 |
#include "tclInt.h" |
#include "tclInt.h" |
17 |
|
|
18 |
/* |
/* |
19 |
* There are three classes of synchronization objects: |
* There are three classes of synchronization objects: |
20 |
* mutexes, thread data keys, and condition variables. |
* mutexes, thread data keys, and condition variables. |
21 |
* The following are used to record the memory used for these |
* The following are used to record the memory used for these |
22 |
* objects so they can be finalized. |
* objects so they can be finalized. |
23 |
* |
* |
24 |
* These statics are guarded by the mutex in the caller of |
* These statics are guarded by the mutex in the caller of |
25 |
* TclRememberThreadData, e.g., TclpThreadDataKeyInit |
* TclRememberThreadData, e.g., TclpThreadDataKeyInit |
26 |
*/ |
*/ |
27 |
|
|
28 |
typedef struct { |
typedef struct { |
29 |
int num; /* Number of objects remembered */ |
int num; /* Number of objects remembered */ |
30 |
int max; /* Max size of the array */ |
int max; /* Max size of the array */ |
31 |
char **list; /* List of pointers */ |
char **list; /* List of pointers */ |
32 |
} SyncObjRecord; |
} SyncObjRecord; |
33 |
|
|
34 |
static SyncObjRecord keyRecord; |
static SyncObjRecord keyRecord; |
35 |
static SyncObjRecord mutexRecord; |
static SyncObjRecord mutexRecord; |
36 |
static SyncObjRecord condRecord; |
static SyncObjRecord condRecord; |
37 |
|
|
38 |
/* |
/* |
39 |
* Prototypes of functions used only in this file |
* Prototypes of functions used only in this file |
40 |
*/ |
*/ |
41 |
|
|
42 |
static void RememberSyncObject _ANSI_ARGS_((char *objPtr, |
static void RememberSyncObject _ANSI_ARGS_((char *objPtr, |
43 |
SyncObjRecord *recPtr)); |
SyncObjRecord *recPtr)); |
44 |
static void ForgetSyncObject _ANSI_ARGS_((char *objPtr, |
static void ForgetSyncObject _ANSI_ARGS_((char *objPtr, |
45 |
SyncObjRecord *recPtr)); |
SyncObjRecord *recPtr)); |
46 |
|
|
47 |
/* |
/* |
48 |
* Several functions are #defined to nothing in tcl.h if TCL_THREADS is not |
* Several functions are #defined to nothing in tcl.h if TCL_THREADS is not |
49 |
* specified. Here we undo that so the procedures are defined in the |
* specified. Here we undo that so the procedures are defined in the |
50 |
* stubs table. |
* stubs table. |
51 |
*/ |
*/ |
52 |
#ifndef TCL_THREADS |
#ifndef TCL_THREADS |
53 |
#undef Tcl_MutexLock |
#undef Tcl_MutexLock |
54 |
#undef Tcl_MutexUnlock |
#undef Tcl_MutexUnlock |
55 |
#undef Tcl_MutexFinalize |
#undef Tcl_MutexFinalize |
56 |
#undef Tcl_ConditionNotify |
#undef Tcl_ConditionNotify |
57 |
#undef Tcl_ConditionWait |
#undef Tcl_ConditionWait |
58 |
#undef Tcl_ConditionFinalize |
#undef Tcl_ConditionFinalize |
59 |
#endif |
#endif |
60 |
|
|
61 |
|
|
62 |
/* |
/* |
63 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
64 |
* |
* |
65 |
* Tcl_GetThreadData -- |
* Tcl_GetThreadData -- |
66 |
* |
* |
67 |
* This procedure allocates and initializes a chunk of thread |
* This procedure allocates and initializes a chunk of thread |
68 |
* local storage. |
* local storage. |
69 |
* |
* |
70 |
* Results: |
* Results: |
71 |
* A thread-specific pointer to the data structure. |
* A thread-specific pointer to the data structure. |
72 |
* |
* |
73 |
* Side effects: |
* Side effects: |
74 |
* Will allocate memory the first time this thread calls for |
* Will allocate memory the first time this thread calls for |
75 |
* this chunk of storage. |
* this chunk of storage. |
76 |
* |
* |
77 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
78 |
*/ |
*/ |
79 |
|
|
80 |
VOID * |
VOID * |
81 |
Tcl_GetThreadData(keyPtr, size) |
Tcl_GetThreadData(keyPtr, size) |
82 |
Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk */ |
Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk */ |
83 |
int size; /* Size of storage block */ |
int size; /* Size of storage block */ |
84 |
{ |
{ |
85 |
VOID *result; |
VOID *result; |
86 |
#ifdef TCL_THREADS |
#ifdef TCL_THREADS |
87 |
|
|
88 |
/* |
/* |
89 |
* See if this is the first thread to init this key. |
* See if this is the first thread to init this key. |
90 |
*/ |
*/ |
91 |
|
|
92 |
if (*keyPtr == NULL) { |
if (*keyPtr == NULL) { |
93 |
TclpThreadDataKeyInit(keyPtr); |
TclpThreadDataKeyInit(keyPtr); |
94 |
} |
} |
95 |
|
|
96 |
/* |
/* |
97 |
* Initialize the key for this thread. |
* Initialize the key for this thread. |
98 |
*/ |
*/ |
99 |
|
|
100 |
result = TclpThreadDataKeyGet(keyPtr); |
result = TclpThreadDataKeyGet(keyPtr); |
101 |
if (result == NULL) { |
if (result == NULL) { |
102 |
result = (VOID *)ckalloc((size_t)size); |
result = (VOID *)ckalloc((size_t)size); |
103 |
memset(result, 0, (size_t)size); |
memset(result, 0, (size_t)size); |
104 |
TclpThreadDataKeySet(keyPtr, result); |
TclpThreadDataKeySet(keyPtr, result); |
105 |
} |
} |
106 |
#else |
#else |
107 |
if (*keyPtr == NULL) { |
if (*keyPtr == NULL) { |
108 |
result = (VOID *)ckalloc((size_t)size); |
result = (VOID *)ckalloc((size_t)size); |
109 |
memset((char *)result, 0, (size_t)size); |
memset((char *)result, 0, (size_t)size); |
110 |
*keyPtr = (Tcl_ThreadDataKey)result; |
*keyPtr = (Tcl_ThreadDataKey)result; |
111 |
TclRememberDataKey(keyPtr); |
TclRememberDataKey(keyPtr); |
112 |
} |
} |
113 |
result = *(VOID **)keyPtr; |
result = *(VOID **)keyPtr; |
114 |
#endif |
#endif |
115 |
return result; |
return result; |
116 |
} |
} |
117 |
|
|
118 |
/* |
/* |
119 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
120 |
* |
* |
121 |
* TclThreadDataKeyGet -- |
* TclThreadDataKeyGet -- |
122 |
* |
* |
123 |
* This procedure returns a pointer to a block of thread local storage. |
* This procedure returns a pointer to a block of thread local storage. |
124 |
* |
* |
125 |
* Results: |
* Results: |
126 |
* A thread-specific pointer to the data structure, or NULL |
* A thread-specific pointer to the data structure, or NULL |
127 |
* if the memory has not been assigned to this key for this thread. |
* if the memory has not been assigned to this key for this thread. |
128 |
* |
* |
129 |
* Side effects: |
* Side effects: |
130 |
* None. |
* None. |
131 |
* |
* |
132 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
133 |
*/ |
*/ |
134 |
|
|
135 |
VOID * |
VOID * |
136 |
TclThreadDataKeyGet(keyPtr) |
TclThreadDataKeyGet(keyPtr) |
137 |
Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, |
Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, |
138 |
* really (pthread_key_t **) */ |
* really (pthread_key_t **) */ |
139 |
{ |
{ |
140 |
#ifdef TCL_THREADS |
#ifdef TCL_THREADS |
141 |
return (VOID *)TclpThreadDataKeyGet(keyPtr); |
return (VOID *)TclpThreadDataKeyGet(keyPtr); |
142 |
#else |
#else |
143 |
char *result = *(char **)keyPtr; |
char *result = *(char **)keyPtr; |
144 |
return (VOID *)result; |
return (VOID *)result; |
145 |
#endif /* TCL_THREADS */ |
#endif /* TCL_THREADS */ |
146 |
} |
} |
147 |
|
|
148 |
|
|
149 |
/* |
/* |
150 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
151 |
* |
* |
152 |
* TclThreadDataKeySet -- |
* TclThreadDataKeySet -- |
153 |
* |
* |
154 |
* This procedure sets a thread local storage pointer. |
* This procedure sets a thread local storage pointer. |
155 |
* |
* |
156 |
* Results: |
* Results: |
157 |
* None. |
* None. |
158 |
* |
* |
159 |
* Side effects: |
* Side effects: |
160 |
* The assigned value will be returned by TclpThreadDataKeyGet. |
* The assigned value will be returned by TclpThreadDataKeyGet. |
161 |
* |
* |
162 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
163 |
*/ |
*/ |
164 |
|
|
165 |
void |
void |
166 |
TclThreadDataKeySet(keyPtr, data) |
TclThreadDataKeySet(keyPtr, data) |
167 |
Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, |
Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, |
168 |
* really (pthread_key_t **) */ |
* really (pthread_key_t **) */ |
169 |
VOID *data; /* Thread local storage */ |
VOID *data; /* Thread local storage */ |
170 |
{ |
{ |
171 |
#ifdef TCL_THREADS |
#ifdef TCL_THREADS |
172 |
if (*keyPtr == NULL) { |
if (*keyPtr == NULL) { |
173 |
TclpThreadDataKeyInit(keyPtr); |
TclpThreadDataKeyInit(keyPtr); |
174 |
} |
} |
175 |
TclpThreadDataKeySet(keyPtr, data); |
TclpThreadDataKeySet(keyPtr, data); |
176 |
#else |
#else |
177 |
*keyPtr = (Tcl_ThreadDataKey)data; |
*keyPtr = (Tcl_ThreadDataKey)data; |
178 |
#endif /* TCL_THREADS */ |
#endif /* TCL_THREADS */ |
179 |
} |
} |
180 |
|
|
181 |
|
|
182 |
|
|
183 |
/* |
/* |
184 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
185 |
* |
* |
186 |
* RememberSyncObject |
* RememberSyncObject |
187 |
* |
* |
188 |
* Keep a list of (mutexes/condition variable/data key) |
* Keep a list of (mutexes/condition variable/data key) |
189 |
* used during finalization. |
* used during finalization. |
190 |
* |
* |
191 |
* Results: |
* Results: |
192 |
* None. |
* None. |
193 |
* |
* |
194 |
* Side effects: |
* Side effects: |
195 |
* Add to the appropriate list. |
* Add to the appropriate list. |
196 |
* |
* |
197 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
198 |
*/ |
*/ |
199 |
|
|
200 |
static void |
static void |
201 |
RememberSyncObject(objPtr, recPtr) |
RememberSyncObject(objPtr, recPtr) |
202 |
char *objPtr; /* Pointer to sync object */ |
char *objPtr; /* Pointer to sync object */ |
203 |
SyncObjRecord *recPtr; /* Record of sync objects */ |
SyncObjRecord *recPtr; /* Record of sync objects */ |
204 |
{ |
{ |
205 |
char **newList; |
char **newList; |
206 |
int i, j; |
int i, j; |
207 |
|
|
208 |
/* |
/* |
209 |
* Save the pointer to the allocated object so it can be finalized. |
* Save the pointer to the allocated object so it can be finalized. |
210 |
* Grow the list of pointers if necessary, copying only non-NULL |
* Grow the list of pointers if necessary, copying only non-NULL |
211 |
* pointers to the new list. |
* pointers to the new list. |
212 |
*/ |
*/ |
213 |
|
|
214 |
if (recPtr->num >= recPtr->max) { |
if (recPtr->num >= recPtr->max) { |
215 |
recPtr->max += 8; |
recPtr->max += 8; |
216 |
newList = (char **)ckalloc(recPtr->max * sizeof(char *)); |
newList = (char **)ckalloc(recPtr->max * sizeof(char *)); |
217 |
for (i=0,j=0 ; i<recPtr->num ; i++) { |
for (i=0,j=0 ; i<recPtr->num ; i++) { |
218 |
if (recPtr->list[i] != NULL) { |
if (recPtr->list[i] != NULL) { |
219 |
newList[j++] = recPtr->list[i]; |
newList[j++] = recPtr->list[i]; |
220 |
} |
} |
221 |
} |
} |
222 |
if (recPtr->list != NULL) { |
if (recPtr->list != NULL) { |
223 |
ckfree((char *)recPtr->list); |
ckfree((char *)recPtr->list); |
224 |
} |
} |
225 |
recPtr->list = newList; |
recPtr->list = newList; |
226 |
recPtr->num = j; |
recPtr->num = j; |
227 |
} |
} |
228 |
recPtr->list[recPtr->num] = objPtr; |
recPtr->list[recPtr->num] = objPtr; |
229 |
recPtr->num++; |
recPtr->num++; |
230 |
} |
} |
231 |
|
|
232 |
/* |
/* |
233 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
234 |
* |
* |
235 |
* ForgetSyncObject |
* ForgetSyncObject |
236 |
* |
* |
237 |
* Remove a single object from the list. |
* Remove a single object from the list. |
238 |
* |
* |
239 |
* Results: |
* Results: |
240 |
* None. |
* None. |
241 |
* |
* |
242 |
* Side effects: |
* Side effects: |
243 |
* Remove from the appropriate list. |
* Remove from the appropriate list. |
244 |
* |
* |
245 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
246 |
*/ |
*/ |
247 |
|
|
248 |
static void |
static void |
249 |
ForgetSyncObject(objPtr, recPtr) |
ForgetSyncObject(objPtr, recPtr) |
250 |
char *objPtr; /* Pointer to sync object */ |
char *objPtr; /* Pointer to sync object */ |
251 |
SyncObjRecord *recPtr; /* Record of sync objects */ |
SyncObjRecord *recPtr; /* Record of sync objects */ |
252 |
{ |
{ |
253 |
int i; |
int i; |
254 |
|
|
255 |
for (i=0 ; i<recPtr->num ; i++) { |
for (i=0 ; i<recPtr->num ; i++) { |
256 |
if (objPtr == recPtr->list[i]) { |
if (objPtr == recPtr->list[i]) { |
257 |
recPtr->list[i] = NULL; |
recPtr->list[i] = NULL; |
258 |
return; |
return; |
259 |
} |
} |
260 |
} |
} |
261 |
} |
} |
262 |
|
|
263 |
/* |
/* |
264 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
265 |
* |
* |
266 |
* TclRememberMutex |
* TclRememberMutex |
267 |
* |
* |
268 |
* Keep a list of mutexes used during finalization. |
* Keep a list of mutexes used during finalization. |
269 |
* |
* |
270 |
* Results: |
* Results: |
271 |
* None. |
* None. |
272 |
* |
* |
273 |
* Side effects: |
* Side effects: |
274 |
* Add to the mutex list. |
* Add to the mutex list. |
275 |
* |
* |
276 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
277 |
*/ |
*/ |
278 |
|
|
279 |
void |
void |
280 |
TclRememberMutex(mutexPtr) |
TclRememberMutex(mutexPtr) |
281 |
Tcl_Mutex *mutexPtr; |
Tcl_Mutex *mutexPtr; |
282 |
{ |
{ |
283 |
RememberSyncObject((char *)mutexPtr, &mutexRecord); |
RememberSyncObject((char *)mutexPtr, &mutexRecord); |
284 |
} |
} |
285 |
|
|
286 |
/* |
/* |
287 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
288 |
* |
* |
289 |
* Tcl_MutexFinalize |
* Tcl_MutexFinalize |
290 |
* |
* |
291 |
* Finalize a single mutex and remove it from the |
* Finalize a single mutex and remove it from the |
292 |
* list of remembered objects. |
* list of remembered objects. |
293 |
* |
* |
294 |
* Results: |
* Results: |
295 |
* None. |
* None. |
296 |
* |
* |
297 |
* Side effects: |
* Side effects: |
298 |
* Remove the mutex from the list. |
* Remove the mutex from the list. |
299 |
* |
* |
300 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
301 |
*/ |
*/ |
302 |
|
|
303 |
void |
void |
304 |
Tcl_MutexFinalize(mutexPtr) |
Tcl_MutexFinalize(mutexPtr) |
305 |
Tcl_Mutex *mutexPtr; |
Tcl_Mutex *mutexPtr; |
306 |
{ |
{ |
307 |
#ifdef TCL_THREADS |
#ifdef TCL_THREADS |
308 |
TclpFinalizeMutex(mutexPtr); |
TclpFinalizeMutex(mutexPtr); |
309 |
#endif |
#endif |
310 |
ForgetSyncObject((char *)mutexPtr, &mutexRecord); |
ForgetSyncObject((char *)mutexPtr, &mutexRecord); |
311 |
} |
} |
312 |
|
|
313 |
/* |
/* |
314 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
315 |
* |
* |
316 |
* TclRememberDataKey |
* TclRememberDataKey |
317 |
* |
* |
318 |
* Keep a list of thread data keys used during finalization. |
* Keep a list of thread data keys used during finalization. |
319 |
* |
* |
320 |
* Results: |
* Results: |
321 |
* None. |
* None. |
322 |
* |
* |
323 |
* Side effects: |
* Side effects: |
324 |
* Add to the key list. |
* Add to the key list. |
325 |
* |
* |
326 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
327 |
*/ |
*/ |
328 |
|
|
329 |
void |
void |
330 |
TclRememberDataKey(keyPtr) |
TclRememberDataKey(keyPtr) |
331 |
Tcl_ThreadDataKey *keyPtr; |
Tcl_ThreadDataKey *keyPtr; |
332 |
{ |
{ |
333 |
RememberSyncObject((char *)keyPtr, &keyRecord); |
RememberSyncObject((char *)keyPtr, &keyRecord); |
334 |
} |
} |
335 |
|
|
336 |
/* |
/* |
337 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
338 |
* |
* |
339 |
* TclRememberCondition |
* TclRememberCondition |
340 |
* |
* |
341 |
* Keep a list of condition variables used during finalization. |
* Keep a list of condition variables used during finalization. |
342 |
* |
* |
343 |
* Results: |
* Results: |
344 |
* None. |
* None. |
345 |
* |
* |
346 |
* Side effects: |
* Side effects: |
347 |
* Add to the condition variable list. |
* Add to the condition variable list. |
348 |
* |
* |
349 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
350 |
*/ |
*/ |
351 |
|
|
352 |
void |
void |
353 |
TclRememberCondition(condPtr) |
TclRememberCondition(condPtr) |
354 |
Tcl_Condition *condPtr; |
Tcl_Condition *condPtr; |
355 |
{ |
{ |
356 |
RememberSyncObject((char *)condPtr, &condRecord); |
RememberSyncObject((char *)condPtr, &condRecord); |
357 |
} |
} |
358 |
|
|
359 |
/* |
/* |
360 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
361 |
* |
* |
362 |
* Tcl_ConditionFinalize |
* Tcl_ConditionFinalize |
363 |
* |
* |
364 |
* Finalize a single condition variable and remove it from the |
* Finalize a single condition variable and remove it from the |
365 |
* list of remembered objects. |
* list of remembered objects. |
366 |
* |
* |
367 |
* Results: |
* Results: |
368 |
* None. |
* None. |
369 |
* |
* |
370 |
* Side effects: |
* Side effects: |
371 |
* Remove the condition variable from the list. |
* Remove the condition variable from the list. |
372 |
* |
* |
373 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
374 |
*/ |
*/ |
375 |
|
|
376 |
void |
void |
377 |
Tcl_ConditionFinalize(condPtr) |
Tcl_ConditionFinalize(condPtr) |
378 |
Tcl_Condition *condPtr; |
Tcl_Condition *condPtr; |
379 |
{ |
{ |
380 |
#ifdef TCL_THREADS |
#ifdef TCL_THREADS |
381 |
TclpFinalizeCondition(condPtr); |
TclpFinalizeCondition(condPtr); |
382 |
#endif |
#endif |
383 |
ForgetSyncObject((char *)condPtr, &condRecord); |
ForgetSyncObject((char *)condPtr, &condRecord); |
384 |
} |
} |
385 |
|
|
386 |
/* |
/* |
387 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
388 |
* |
* |
389 |
* TclFinalizeThreadData -- |
* TclFinalizeThreadData -- |
390 |
* |
* |
391 |
* This procedure cleans up the thread-local storage. This is |
* This procedure cleans up the thread-local storage. This is |
392 |
* called once for each thread. |
* called once for each thread. |
393 |
* |
* |
394 |
* Results: |
* Results: |
395 |
* None. |
* None. |
396 |
* |
* |
397 |
* Side effects: |
* Side effects: |
398 |
* Frees up all thread local storage. |
* Frees up all thread local storage. |
399 |
* |
* |
400 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
401 |
*/ |
*/ |
402 |
|
|
403 |
void |
void |
404 |
TclFinalizeThreadData() |
TclFinalizeThreadData() |
405 |
{ |
{ |
406 |
int i; |
int i; |
407 |
Tcl_ThreadDataKey *keyPtr; |
Tcl_ThreadDataKey *keyPtr; |
408 |
|
|
409 |
TclpMasterLock(); |
TclpMasterLock(); |
410 |
for (i=0 ; i<keyRecord.num ; i++) { |
for (i=0 ; i<keyRecord.num ; i++) { |
411 |
keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i]; |
keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i]; |
412 |
#ifdef TCL_THREADS |
#ifdef TCL_THREADS |
413 |
TclpFinalizeThreadData(keyPtr); |
TclpFinalizeThreadData(keyPtr); |
414 |
#else |
#else |
415 |
if (*keyPtr != NULL) { |
if (*keyPtr != NULL) { |
416 |
ckfree((char *)*keyPtr); |
ckfree((char *)*keyPtr); |
417 |
*keyPtr = NULL; |
*keyPtr = NULL; |
418 |
} |
} |
419 |
#endif |
#endif |
420 |
} |
} |
421 |
#ifdef TCL_THREADS |
#ifdef TCL_THREADS |
422 |
TclpMasterUnlock(); |
TclpMasterUnlock(); |
423 |
#endif |
#endif |
424 |
} |
} |
425 |
|
|
426 |
/* |
/* |
427 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
428 |
* |
* |
429 |
* TclFinalizeSynchronization -- |
* TclFinalizeSynchronization -- |
430 |
* |
* |
431 |
* This procedure cleans up all synchronization objects: |
* This procedure cleans up all synchronization objects: |
432 |
* mutexes, condition variables, and thread-local storage. |
* mutexes, condition variables, and thread-local storage. |
433 |
* |
* |
434 |
* Results: |
* Results: |
435 |
* None. |
* None. |
436 |
* |
* |
437 |
* Side effects: |
* Side effects: |
438 |
* Frees up the memory. |
* Frees up the memory. |
439 |
* |
* |
440 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
441 |
*/ |
*/ |
442 |
|
|
443 |
void |
void |
444 |
TclFinalizeSynchronization() |
TclFinalizeSynchronization() |
445 |
{ |
{ |
446 |
#ifdef TCL_THREADS |
#ifdef TCL_THREADS |
447 |
Tcl_ThreadDataKey *keyPtr; |
Tcl_ThreadDataKey *keyPtr; |
448 |
Tcl_Mutex *mutexPtr; |
Tcl_Mutex *mutexPtr; |
449 |
Tcl_Condition *condPtr; |
Tcl_Condition *condPtr; |
450 |
int i; |
int i; |
451 |
|
|
452 |
TclpMasterLock(); |
TclpMasterLock(); |
453 |
for (i=0 ; i<keyRecord.num ; i++) { |
for (i=0 ; i<keyRecord.num ; i++) { |
454 |
keyPtr = (Tcl_ThreadDataKey *)keyRecord.list[i]; |
keyPtr = (Tcl_ThreadDataKey *)keyRecord.list[i]; |
455 |
TclpFinalizeThreadDataKey(keyPtr); |
TclpFinalizeThreadDataKey(keyPtr); |
456 |
} |
} |
457 |
if (keyRecord.list != NULL) { |
if (keyRecord.list != NULL) { |
458 |
ckfree((char *)keyRecord.list); |
ckfree((char *)keyRecord.list); |
459 |
keyRecord.list = NULL; |
keyRecord.list = NULL; |
460 |
} |
} |
461 |
keyRecord.max = 0; |
keyRecord.max = 0; |
462 |
keyRecord.num = 0; |
keyRecord.num = 0; |
463 |
|
|
464 |
for (i=0 ; i<mutexRecord.num ; i++) { |
for (i=0 ; i<mutexRecord.num ; i++) { |
465 |
mutexPtr = (Tcl_Mutex *)mutexRecord.list[i]; |
mutexPtr = (Tcl_Mutex *)mutexRecord.list[i]; |
466 |
if (mutexPtr != NULL) { |
if (mutexPtr != NULL) { |
467 |
TclpFinalizeMutex(mutexPtr); |
TclpFinalizeMutex(mutexPtr); |
468 |
} |
} |
469 |
} |
} |
470 |
if (mutexRecord.list != NULL) { |
if (mutexRecord.list != NULL) { |
471 |
ckfree((char *)mutexRecord.list); |
ckfree((char *)mutexRecord.list); |
472 |
mutexRecord.list = NULL; |
mutexRecord.list = NULL; |
473 |
} |
} |
474 |
mutexRecord.max = 0; |
mutexRecord.max = 0; |
475 |
mutexRecord.num = 0; |
mutexRecord.num = 0; |
476 |
|
|
477 |
for (i=0 ; i<condRecord.num ; i++) { |
for (i=0 ; i<condRecord.num ; i++) { |
478 |
condPtr = (Tcl_Condition *)condRecord.list[i]; |
condPtr = (Tcl_Condition *)condRecord.list[i]; |
479 |
if (condPtr != NULL) { |
if (condPtr != NULL) { |
480 |
TclpFinalizeCondition(condPtr); |
TclpFinalizeCondition(condPtr); |
481 |
} |
} |
482 |
} |
} |
483 |
if (condRecord.list != NULL) { |
if (condRecord.list != NULL) { |
484 |
ckfree((char *)condRecord.list); |
ckfree((char *)condRecord.list); |
485 |
condRecord.list = NULL; |
condRecord.list = NULL; |
486 |
} |
} |
487 |
condRecord.max = 0; |
condRecord.max = 0; |
488 |
condRecord.num = 0; |
condRecord.num = 0; |
489 |
|
|
490 |
TclpMasterUnlock(); |
TclpMasterUnlock(); |
491 |
#else |
#else |
492 |
if (keyRecord.list != NULL) { |
if (keyRecord.list != NULL) { |
493 |
ckfree((char *)keyRecord.list); |
ckfree((char *)keyRecord.list); |
494 |
keyRecord.list = NULL; |
keyRecord.list = NULL; |
495 |
} |
} |
496 |
keyRecord.max = 0; |
keyRecord.max = 0; |
497 |
keyRecord.num = 0; |
keyRecord.num = 0; |
498 |
#endif |
#endif |
499 |
} |
} |
500 |
|
|
501 |
|
|
502 |
/* |
/* |
503 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
504 |
* |
* |
505 |
* Tcl_ExitThread -- |
* Tcl_ExitThread -- |
506 |
* |
* |
507 |
* This procedure is called to terminate the current thread. |
* This procedure is called to terminate the current thread. |
508 |
* This should be used by extensions that create threads with |
* This should be used by extensions that create threads with |
509 |
* additional interpreters in them. |
* additional interpreters in them. |
510 |
* |
* |
511 |
* Results: |
* Results: |
512 |
* None. |
* None. |
513 |
* |
* |
514 |
* Side effects: |
* Side effects: |
515 |
* All thread exit handlers are invoked, then the thread dies. |
* All thread exit handlers are invoked, then the thread dies. |
516 |
* |
* |
517 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
518 |
*/ |
*/ |
519 |
|
|
520 |
void |
void |
521 |
Tcl_ExitThread(status) |
Tcl_ExitThread(status) |
522 |
int status; |
int status; |
523 |
{ |
{ |
524 |
Tcl_FinalizeThread(); |
Tcl_FinalizeThread(); |
525 |
#ifdef TCL_THREADS |
#ifdef TCL_THREADS |
526 |
TclpThreadExit(status); |
TclpThreadExit(status); |
527 |
#endif |
#endif |
528 |
} |
} |
529 |
|
|
530 |
#ifndef TCL_THREADS |
#ifndef TCL_THREADS |
531 |
|
|
532 |
/* |
/* |
533 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
534 |
* |
* |
535 |
* Tcl_ConditionWait, et al. -- |
* Tcl_ConditionWait, et al. -- |
536 |
* |
* |
537 |
* These noop procedures are provided so the stub table does |
* These noop procedures are provided so the stub table does |
538 |
* not have to be conditionalized for threads. The real |
* not have to be conditionalized for threads. The real |
539 |
* implementations of these functions live in the platform |
* implementations of these functions live in the platform |
540 |
* specific files. |
* specific files. |
541 |
* |
* |
542 |
* Results: |
* Results: |
543 |
* None. |
* None. |
544 |
* |
* |
545 |
* Side effects: |
* Side effects: |
546 |
* None. |
* None. |
547 |
* |
* |
548 |
*---------------------------------------------------------------------- |
*---------------------------------------------------------------------- |
549 |
*/ |
*/ |
550 |
|
|
551 |
#undef Tcl_ConditionWait |
#undef Tcl_ConditionWait |
552 |
void |
void |
553 |
Tcl_ConditionWait(condPtr, mutexPtr, timePtr) |
Tcl_ConditionWait(condPtr, mutexPtr, timePtr) |
554 |
Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */ |
Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */ |
555 |
Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */ |
Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */ |
556 |
Tcl_Time *timePtr; /* Timeout on waiting period */ |
Tcl_Time *timePtr; /* Timeout on waiting period */ |
557 |
{ |
{ |
558 |
} |
} |
559 |
|
|
560 |
#undef Tcl_ConditionNotify |
#undef Tcl_ConditionNotify |
561 |
void |
void |
562 |
Tcl_ConditionNotify(condPtr) |
Tcl_ConditionNotify(condPtr) |
563 |
Tcl_Condition *condPtr; |
Tcl_Condition *condPtr; |
564 |
{ |
{ |
565 |
} |
} |
566 |
|
|
567 |
#undef Tcl_MutexLock |
#undef Tcl_MutexLock |
568 |
void |
void |
569 |
Tcl_MutexLock(mutexPtr) |
Tcl_MutexLock(mutexPtr) |
570 |
Tcl_Mutex *mutexPtr; |
Tcl_Mutex *mutexPtr; |
571 |
{ |
{ |
572 |
} |
} |
573 |
|
|
574 |
#undef Tcl_MutexUnlock |
#undef Tcl_MutexUnlock |
575 |
void |
void |
576 |
Tcl_MutexUnlock(mutexPtr) |
Tcl_MutexUnlock(mutexPtr) |
577 |
Tcl_Mutex *mutexPtr; |
Tcl_Mutex *mutexPtr; |
578 |
{ |
{ |
579 |
} |
} |
580 |
#endif |
#endif |
581 |
|
|
582 |
/* End of tclthread.c */ |
/* End of tclthread.c */ |