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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 67 - (show annotations) (download)
Mon Oct 31 00:57:34 2016 UTC (6 years, 2 months ago) by dashley
File MIME type: text/plain
File size: 13150 byte(s)
Header and footer cleanup.
1 /* $Header$ */
2 /*
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 /* End of tclthread.c */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25