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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (show annotations) (download)
Fri Oct 14 01:50:00 2016 UTC (7 years, 5 months ago) by dashley
File MIME type: text/plain
File size: 13479 byte(s)
Move shared source code to commonize.
1 /* $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