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

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25