/[dtapublic]/projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclthread.c
ViewVC logotype

Annotation of /projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclthread.c

Parent Directory Parent Directory | Revision Log Revision Log


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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25