os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclThread.c
Update contrib.
4 * This file implements Platform independent thread operations.
5 * Most of the real work is done in the platform dependent files.
7 * Copyright (c) 1998 by Sun Microsystems, Inc.
8 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * RCS: @(#) $Id: tclThread.c,v 1.6.2.1 2004/05/06 01:02:59 davygrvy Exp $
17 #if defined(__SYMBIAN32__)
18 #include "tclSymbianGlobals.h"
22 * There are three classes of synchronization objects:
23 * mutexes, thread data keys, and condition variables.
24 * The following are used to record the memory used for these
25 * objects so they can be finalized.
27 * These statics are guarded by the mutex in the caller of
28 * TclRememberThreadData, e.g., TclpThreadDataKeyInit
33 int num; /* Number of objects remembered */
34 int max; /* Max size of the array */
35 char **list; /* List of pointers */
38 #if !defined(__SYMBIAN32__) || !defined(__WINSCW__)
39 static SyncObjRecord keyRecord = {0, 0, NULL};
41 static SyncObjRecord mutexRecord = {0, 0, NULL};
42 static SyncObjRecord condRecord = {0, 0, NULL};
45 * Prototypes of functions used only in this file
48 static void RememberSyncObject _ANSI_ARGS_((char *objPtr,
49 SyncObjRecord *recPtr));
50 static void ForgetSyncObject _ANSI_ARGS_((char *objPtr,
51 SyncObjRecord *recPtr));
54 * Several functions are #defined to nothing in tcl.h if TCL_THREADS is not
55 * specified. Here we undo that so the procedures are defined in the
60 #undef Tcl_MutexUnlock
61 #undef Tcl_MutexFinalize
62 #undef Tcl_ConditionNotify
63 #undef Tcl_ConditionWait
64 #undef Tcl_ConditionFinalize
69 *----------------------------------------------------------------------
71 * Tcl_GetThreadData --
73 * This procedure allocates and initializes a chunk of thread
77 * A thread-specific pointer to the data structure.
80 * Will allocate memory the first time this thread calls for
81 * this chunk of storage.
83 *----------------------------------------------------------------------
87 Tcl_GetThreadData(keyPtr, size)
88 Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk */
89 int size; /* Size of storage block */
95 * See if this is the first thread to init this key.
98 if (*keyPtr == NULL) {
99 TclpThreadDataKeyInit(keyPtr);
103 * Initialize the key for this thread.
106 result = TclpThreadDataKeyGet(keyPtr);
107 if (result == NULL) {
108 result = (VOID *)ckalloc((size_t)size);
109 memset(result, 0, (size_t)size);
110 TclpThreadDataKeySet(keyPtr, result);
113 if (*keyPtr == NULL) {
114 result = (VOID *)ckalloc((size_t)size);
115 memset((char *)result, 0, (size_t)size);
116 *keyPtr = (Tcl_ThreadDataKey)result;
117 TclRememberDataKey(keyPtr);
119 result = *(VOID **)keyPtr;
125 *----------------------------------------------------------------------
127 * TclThreadDataKeyGet --
129 * This procedure returns a pointer to a block of thread local storage.
132 * A thread-specific pointer to the data structure, or NULL
133 * if the memory has not been assigned to this key for this thread.
138 *----------------------------------------------------------------------
142 TclThreadDataKeyGet(keyPtr)
143 Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
144 * really (pthread_key_t **) */
147 return (VOID *)TclpThreadDataKeyGet(keyPtr);
149 char *result = *(char **)keyPtr;
150 return (VOID *)result;
151 #endif /* TCL_THREADS */
156 *----------------------------------------------------------------------
158 * TclThreadDataKeySet --
160 * This procedure sets a thread local storage pointer.
166 * The assigned value will be returned by TclpThreadDataKeyGet.
168 *----------------------------------------------------------------------
172 TclThreadDataKeySet(keyPtr, data)
173 Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
174 * really (pthread_key_t **) */
175 VOID *data; /* Thread local storage */
178 if (*keyPtr == NULL) {
179 TclpThreadDataKeyInit(keyPtr);
181 TclpThreadDataKeySet(keyPtr, data);
183 *keyPtr = (Tcl_ThreadDataKey)data;
184 #endif /* TCL_THREADS */
190 *----------------------------------------------------------------------
194 * Keep a list of (mutexes/condition variable/data key)
195 * used during finalization.
201 * Add to the appropriate list.
203 *----------------------------------------------------------------------
207 RememberSyncObject(objPtr, recPtr)
208 char *objPtr; /* Pointer to sync object */
209 SyncObjRecord *recPtr; /* Record of sync objects */
215 * Save the pointer to the allocated object so it can be finalized.
216 * Grow the list of pointers if necessary, copying only non-NULL
217 * pointers to the new list.
220 if (recPtr->num >= recPtr->max) {
222 newList = (char **)ckalloc(recPtr->max * sizeof(char *));
223 for (i=0,j=0 ; i<recPtr->num ; i++) {
224 if (recPtr->list[i] != NULL) {
225 newList[j++] = recPtr->list[i];
228 if (recPtr->list != NULL) {
229 ckfree((char *)recPtr->list);
231 recPtr->list = newList;
234 recPtr->list[recPtr->num] = objPtr;
239 *----------------------------------------------------------------------
243 * Remove a single object from the list.
249 * Remove from the appropriate list.
251 *----------------------------------------------------------------------
255 ForgetSyncObject(objPtr, recPtr)
256 char *objPtr; /* Pointer to sync object */
257 SyncObjRecord *recPtr; /* Record of sync objects */
261 for (i=0 ; i<recPtr->num ; i++) {
262 if (objPtr == recPtr->list[i]) {
263 recPtr->list[i] = NULL;
270 *----------------------------------------------------------------------
274 * Keep a list of mutexes used during finalization.
280 * Add to the mutex list.
282 *----------------------------------------------------------------------
286 TclRememberMutex(mutexPtr)
289 RememberSyncObject((char *)mutexPtr, &mutexRecord);
293 *----------------------------------------------------------------------
297 * Finalize a single mutex and remove it from the
298 * list of remembered objects.
304 * Remove the mutex from the list.
306 *----------------------------------------------------------------------
310 Tcl_MutexFinalize(mutexPtr)
314 TclpFinalizeMutex(mutexPtr);
316 ForgetSyncObject((char *)mutexPtr, &mutexRecord);
320 *----------------------------------------------------------------------
324 * Keep a list of thread data keys used during finalization.
330 * Add to the key list.
332 *----------------------------------------------------------------------
336 TclRememberDataKey(keyPtr)
337 Tcl_ThreadDataKey *keyPtr;
339 RememberSyncObject((char *)keyPtr, &keyRecord);
343 *----------------------------------------------------------------------
345 * TclRememberCondition
347 * Keep a list of condition variables used during finalization.
353 * Add to the condition variable list.
355 *----------------------------------------------------------------------
359 TclRememberCondition(condPtr)
360 Tcl_Condition *condPtr;
362 RememberSyncObject((char *)condPtr, &condRecord);
366 *----------------------------------------------------------------------
368 * Tcl_ConditionFinalize
370 * Finalize a single condition variable and remove it from the
371 * list of remembered objects.
377 * Remove the condition variable from the list.
379 *----------------------------------------------------------------------
383 Tcl_ConditionFinalize(condPtr)
384 Tcl_Condition *condPtr;
387 TclpFinalizeCondition(condPtr);
389 ForgetSyncObject((char *)condPtr, &condRecord);
393 *----------------------------------------------------------------------
395 * TclFinalizeThreadData --
397 * This procedure cleans up the thread-local storage. This is
398 * called once for each thread.
404 * Frees up all thread local storage.
406 *----------------------------------------------------------------------
410 TclFinalizeThreadData()
413 Tcl_ThreadDataKey *keyPtr;
416 for (i=0 ; i<keyRecord.num ; i++) {
417 keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i];
419 TclpFinalizeThreadData(keyPtr);
421 if (*keyPtr != NULL) {
422 ckfree((char *)*keyPtr);
431 *----------------------------------------------------------------------
433 * TclFinalizeSynchronization --
435 * This procedure cleans up all synchronization objects:
436 * mutexes, condition variables, and thread-local storage.
442 * Frees up the memory.
444 *----------------------------------------------------------------------
448 TclFinalizeSynchronization()
451 Tcl_ThreadDataKey *keyPtr;
453 Tcl_Condition *condPtr;
457 for (i=0 ; i<keyRecord.num ; i++) {
458 keyPtr = (Tcl_ThreadDataKey *)keyRecord.list[i];
459 TclpFinalizeThreadDataKey(keyPtr);
461 if (keyRecord.list != NULL) {
462 ckfree((char *)keyRecord.list);
463 keyRecord.list = NULL;
468 for (i=0 ; i<mutexRecord.num ; i++) {
469 mutexPtr = (Tcl_Mutex *)mutexRecord.list[i];
470 if (mutexPtr != NULL) {
471 TclpFinalizeMutex(mutexPtr);
474 if (mutexRecord.list != NULL) {
475 ckfree((char *)mutexRecord.list);
476 mutexRecord.list = NULL;
481 for (i=0 ; i<condRecord.num ; i++) {
482 condPtr = (Tcl_Condition *)condRecord.list[i];
483 if (condPtr != NULL) {
484 TclpFinalizeCondition(condPtr);
487 if (condRecord.list != NULL) {
488 ckfree((char *)condRecord.list);
489 condRecord.list = NULL;
496 if (keyRecord.list != NULL) {
497 ckfree((char *)keyRecord.list);
498 keyRecord.list = NULL;
507 *----------------------------------------------------------------------
511 * This procedure is called to terminate the current thread.
512 * This should be used by extensions that create threads with
513 * additional interpreters in them.
519 * All thread exit handlers are invoked, then the thread dies.
521 *----------------------------------------------------------------------
525 Tcl_ExitThread(status)
528 Tcl_FinalizeThread();
530 TclpThreadExit(status);
537 *----------------------------------------------------------------------
539 * Tcl_ConditionWait, et al. --
541 * These noop procedures are provided so the stub table does
542 * not have to be conditionalized for threads. The real
543 * implementations of these functions live in the platform
552 *----------------------------------------------------------------------
555 #undef Tcl_ConditionWait
557 Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
558 Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */
559 Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
560 Tcl_Time *timePtr; /* Timeout on waiting period */
564 #undef Tcl_ConditionNotify
566 Tcl_ConditionNotify(condPtr)
567 Tcl_Condition *condPtr;
573 Tcl_MutexLock(mutexPtr)
578 #undef Tcl_MutexUnlock
580 Tcl_MutexUnlock(mutexPtr)