os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclThread.c
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclThread.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,584 @@
1.4 +/*
1.5 + * tclThread.c --
1.6 + *
1.7 + * This file implements Platform independent thread operations.
1.8 + * Most of the real work is done in the platform dependent files.
1.9 + *
1.10 + * Copyright (c) 1998 by Sun Microsystems, Inc.
1.11 + * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
1.12 + *
1.13 + * See the file "license.terms" for information on usage and redistribution
1.14 + * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
1.15 + *
1.16 + * RCS: @(#) $Id: tclThread.c,v 1.6.2.1 2004/05/06 01:02:59 davygrvy Exp $
1.17 + */
1.18 +
1.19 +#include "tclInt.h"
1.20 +#if defined(__SYMBIAN32__)
1.21 +#include "tclSymbianGlobals.h"
1.22 +#endif
1.23 +
1.24 +/*
1.25 + * There are three classes of synchronization objects:
1.26 + * mutexes, thread data keys, and condition variables.
1.27 + * The following are used to record the memory used for these
1.28 + * objects so they can be finalized.
1.29 + *
1.30 + * These statics are guarded by the mutex in the caller of
1.31 + * TclRememberThreadData, e.g., TclpThreadDataKeyInit
1.32 + */
1.33 +
1.34 +#ifndef __SYMBIAN32__
1.35 +typedef struct {
1.36 + int num; /* Number of objects remembered */
1.37 + int max; /* Max size of the array */
1.38 + char **list; /* List of pointers */
1.39 +} SyncObjRecord;
1.40 +#endif
1.41 +#if !defined(__SYMBIAN32__) || !defined(__WINSCW__)
1.42 +static SyncObjRecord keyRecord = {0, 0, NULL};
1.43 +#endif
1.44 +static SyncObjRecord mutexRecord = {0, 0, NULL};
1.45 +static SyncObjRecord condRecord = {0, 0, NULL};
1.46 +
1.47 +/*
1.48 + * Prototypes of functions used only in this file
1.49 + */
1.50 +
1.51 +static void RememberSyncObject _ANSI_ARGS_((char *objPtr,
1.52 + SyncObjRecord *recPtr));
1.53 +static void ForgetSyncObject _ANSI_ARGS_((char *objPtr,
1.54 + SyncObjRecord *recPtr));
1.55 +
1.56 +/*
1.57 + * Several functions are #defined to nothing in tcl.h if TCL_THREADS is not
1.58 + * specified. Here we undo that so the procedures are defined in the
1.59 + * stubs table.
1.60 + */
1.61 +#ifndef TCL_THREADS
1.62 +#undef Tcl_MutexLock
1.63 +#undef Tcl_MutexUnlock
1.64 +#undef Tcl_MutexFinalize
1.65 +#undef Tcl_ConditionNotify
1.66 +#undef Tcl_ConditionWait
1.67 +#undef Tcl_ConditionFinalize
1.68 +#endif
1.69 +
1.70 +
1.71 +/*
1.72 + *----------------------------------------------------------------------
1.73 + *
1.74 + * Tcl_GetThreadData --
1.75 + *
1.76 + * This procedure allocates and initializes a chunk of thread
1.77 + * local storage.
1.78 + *
1.79 + * Results:
1.80 + * A thread-specific pointer to the data structure.
1.81 + *
1.82 + * Side effects:
1.83 + * Will allocate memory the first time this thread calls for
1.84 + * this chunk of storage.
1.85 + *
1.86 + *----------------------------------------------------------------------
1.87 + */
1.88 +
1.89 +EXPORT_C VOID *
1.90 +Tcl_GetThreadData(keyPtr, size)
1.91 + Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk */
1.92 + int size; /* Size of storage block */
1.93 +{
1.94 + VOID *result;
1.95 +#ifdef TCL_THREADS
1.96 +
1.97 + /*
1.98 + * See if this is the first thread to init this key.
1.99 + */
1.100 +
1.101 + if (*keyPtr == NULL) {
1.102 + TclpThreadDataKeyInit(keyPtr);
1.103 + }
1.104 +
1.105 + /*
1.106 + * Initialize the key for this thread.
1.107 + */
1.108 +
1.109 + result = TclpThreadDataKeyGet(keyPtr);
1.110 + if (result == NULL) {
1.111 + result = (VOID *)ckalloc((size_t)size);
1.112 + memset(result, 0, (size_t)size);
1.113 + TclpThreadDataKeySet(keyPtr, result);
1.114 + }
1.115 +#else
1.116 + if (*keyPtr == NULL) {
1.117 + result = (VOID *)ckalloc((size_t)size);
1.118 + memset((char *)result, 0, (size_t)size);
1.119 + *keyPtr = (Tcl_ThreadDataKey)result;
1.120 + TclRememberDataKey(keyPtr);
1.121 + }
1.122 + result = *(VOID **)keyPtr;
1.123 +#endif
1.124 + return result;
1.125 +}
1.126 +
1.127 +/*
1.128 + *----------------------------------------------------------------------
1.129 + *
1.130 + * TclThreadDataKeyGet --
1.131 + *
1.132 + * This procedure returns a pointer to a block of thread local storage.
1.133 + *
1.134 + * Results:
1.135 + * A thread-specific pointer to the data structure, or NULL
1.136 + * if the memory has not been assigned to this key for this thread.
1.137 + *
1.138 + * Side effects:
1.139 + * None.
1.140 + *
1.141 + *----------------------------------------------------------------------
1.142 + */
1.143 +
1.144 +VOID *
1.145 +TclThreadDataKeyGet(keyPtr)
1.146 + Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
1.147 + * really (pthread_key_t **) */
1.148 +{
1.149 +#ifdef TCL_THREADS
1.150 + return (VOID *)TclpThreadDataKeyGet(keyPtr);
1.151 +#else
1.152 + char *result = *(char **)keyPtr;
1.153 + return (VOID *)result;
1.154 +#endif /* TCL_THREADS */
1.155 +}
1.156 +
1.157 +
1.158 +/*
1.159 + *----------------------------------------------------------------------
1.160 + *
1.161 + * TclThreadDataKeySet --
1.162 + *
1.163 + * This procedure sets a thread local storage pointer.
1.164 + *
1.165 + * Results:
1.166 + * None.
1.167 + *
1.168 + * Side effects:
1.169 + * The assigned value will be returned by TclpThreadDataKeyGet.
1.170 + *
1.171 + *----------------------------------------------------------------------
1.172 + */
1.173 +
1.174 +void
1.175 +TclThreadDataKeySet(keyPtr, data)
1.176 + Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
1.177 + * really (pthread_key_t **) */
1.178 + VOID *data; /* Thread local storage */
1.179 +{
1.180 +#ifdef TCL_THREADS
1.181 + if (*keyPtr == NULL) {
1.182 + TclpThreadDataKeyInit(keyPtr);
1.183 + }
1.184 + TclpThreadDataKeySet(keyPtr, data);
1.185 +#else
1.186 + *keyPtr = (Tcl_ThreadDataKey)data;
1.187 +#endif /* TCL_THREADS */
1.188 +}
1.189 +
1.190 +
1.191 +
1.192 +/*
1.193 + *----------------------------------------------------------------------
1.194 + *
1.195 + * RememberSyncObject
1.196 + *
1.197 + * Keep a list of (mutexes/condition variable/data key)
1.198 + * used during finalization.
1.199 + *
1.200 + * Results:
1.201 + * None.
1.202 + *
1.203 + * Side effects:
1.204 + * Add to the appropriate list.
1.205 + *
1.206 + *----------------------------------------------------------------------
1.207 + */
1.208 +
1.209 +static void
1.210 +RememberSyncObject(objPtr, recPtr)
1.211 + char *objPtr; /* Pointer to sync object */
1.212 + SyncObjRecord *recPtr; /* Record of sync objects */
1.213 +{
1.214 + char **newList;
1.215 + int i, j;
1.216 +
1.217 + /*
1.218 + * Save the pointer to the allocated object so it can be finalized.
1.219 + * Grow the list of pointers if necessary, copying only non-NULL
1.220 + * pointers to the new list.
1.221 + */
1.222 +
1.223 + if (recPtr->num >= recPtr->max) {
1.224 + recPtr->max += 8;
1.225 + newList = (char **)ckalloc(recPtr->max * sizeof(char *));
1.226 + for (i=0,j=0 ; i<recPtr->num ; i++) {
1.227 + if (recPtr->list[i] != NULL) {
1.228 + newList[j++] = recPtr->list[i];
1.229 + }
1.230 + }
1.231 + if (recPtr->list != NULL) {
1.232 + ckfree((char *)recPtr->list);
1.233 + }
1.234 + recPtr->list = newList;
1.235 + recPtr->num = j;
1.236 + }
1.237 + recPtr->list[recPtr->num] = objPtr;
1.238 + recPtr->num++;
1.239 +}
1.240 +
1.241 +/*
1.242 + *----------------------------------------------------------------------
1.243 + *
1.244 + * ForgetSyncObject
1.245 + *
1.246 + * Remove a single object from the list.
1.247 + *
1.248 + * Results:
1.249 + * None.
1.250 + *
1.251 + * Side effects:
1.252 + * Remove from the appropriate list.
1.253 + *
1.254 + *----------------------------------------------------------------------
1.255 + */
1.256 +
1.257 +static void
1.258 +ForgetSyncObject(objPtr, recPtr)
1.259 + char *objPtr; /* Pointer to sync object */
1.260 + SyncObjRecord *recPtr; /* Record of sync objects */
1.261 +{
1.262 + int i;
1.263 +
1.264 + for (i=0 ; i<recPtr->num ; i++) {
1.265 + if (objPtr == recPtr->list[i]) {
1.266 + recPtr->list[i] = NULL;
1.267 + return;
1.268 + }
1.269 + }
1.270 +}
1.271 +
1.272 +/*
1.273 + *----------------------------------------------------------------------
1.274 + *
1.275 + * TclRememberMutex
1.276 + *
1.277 + * Keep a list of mutexes used during finalization.
1.278 + *
1.279 + * Results:
1.280 + * None.
1.281 + *
1.282 + * Side effects:
1.283 + * Add to the mutex list.
1.284 + *
1.285 + *----------------------------------------------------------------------
1.286 + */
1.287 +
1.288 +void
1.289 +TclRememberMutex(mutexPtr)
1.290 + Tcl_Mutex *mutexPtr;
1.291 +{
1.292 + RememberSyncObject((char *)mutexPtr, &mutexRecord);
1.293 +}
1.294 +
1.295 +/*
1.296 + *----------------------------------------------------------------------
1.297 + *
1.298 + * Tcl_MutexFinalize
1.299 + *
1.300 + * Finalize a single mutex and remove it from the
1.301 + * list of remembered objects.
1.302 + *
1.303 + * Results:
1.304 + * None.
1.305 + *
1.306 + * Side effects:
1.307 + * Remove the mutex from the list.
1.308 + *
1.309 + *----------------------------------------------------------------------
1.310 + */
1.311 +
1.312 +EXPORT_C void
1.313 +Tcl_MutexFinalize(mutexPtr)
1.314 + Tcl_Mutex *mutexPtr;
1.315 +{
1.316 +#ifdef TCL_THREADS
1.317 + TclpFinalizeMutex(mutexPtr);
1.318 +#endif
1.319 + ForgetSyncObject((char *)mutexPtr, &mutexRecord);
1.320 +}
1.321 +
1.322 +/*
1.323 + *----------------------------------------------------------------------
1.324 + *
1.325 + * TclRememberDataKey
1.326 + *
1.327 + * Keep a list of thread data keys used during finalization.
1.328 + *
1.329 + * Results:
1.330 + * None.
1.331 + *
1.332 + * Side effects:
1.333 + * Add to the key list.
1.334 + *
1.335 + *----------------------------------------------------------------------
1.336 + */
1.337 +
1.338 +void
1.339 +TclRememberDataKey(keyPtr)
1.340 + Tcl_ThreadDataKey *keyPtr;
1.341 +{
1.342 + RememberSyncObject((char *)keyPtr, &keyRecord);
1.343 +}
1.344 +
1.345 +/*
1.346 + *----------------------------------------------------------------------
1.347 + *
1.348 + * TclRememberCondition
1.349 + *
1.350 + * Keep a list of condition variables used during finalization.
1.351 + *
1.352 + * Results:
1.353 + * None.
1.354 + *
1.355 + * Side effects:
1.356 + * Add to the condition variable list.
1.357 + *
1.358 + *----------------------------------------------------------------------
1.359 + */
1.360 +
1.361 +void
1.362 +TclRememberCondition(condPtr)
1.363 + Tcl_Condition *condPtr;
1.364 +{
1.365 + RememberSyncObject((char *)condPtr, &condRecord);
1.366 +}
1.367 +
1.368 +/*
1.369 + *----------------------------------------------------------------------
1.370 + *
1.371 + * Tcl_ConditionFinalize
1.372 + *
1.373 + * Finalize a single condition variable and remove it from the
1.374 + * list of remembered objects.
1.375 + *
1.376 + * Results:
1.377 + * None.
1.378 + *
1.379 + * Side effects:
1.380 + * Remove the condition variable from the list.
1.381 + *
1.382 + *----------------------------------------------------------------------
1.383 + */
1.384 +
1.385 +EXPORT_C void
1.386 +Tcl_ConditionFinalize(condPtr)
1.387 + Tcl_Condition *condPtr;
1.388 +{
1.389 +#ifdef TCL_THREADS
1.390 + TclpFinalizeCondition(condPtr);
1.391 +#endif
1.392 + ForgetSyncObject((char *)condPtr, &condRecord);
1.393 +}
1.394 +
1.395 +/*
1.396 + *----------------------------------------------------------------------
1.397 + *
1.398 + * TclFinalizeThreadData --
1.399 + *
1.400 + * This procedure cleans up the thread-local storage. This is
1.401 + * called once for each thread.
1.402 + *
1.403 + * Results:
1.404 + * None.
1.405 + *
1.406 + * Side effects:
1.407 + * Frees up all thread local storage.
1.408 + *
1.409 + *----------------------------------------------------------------------
1.410 + */
1.411 +
1.412 +void
1.413 +TclFinalizeThreadData()
1.414 +{
1.415 + int i;
1.416 + Tcl_ThreadDataKey *keyPtr;
1.417 +
1.418 + TclpMasterLock();
1.419 + for (i=0 ; i<keyRecord.num ; i++) {
1.420 + keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i];
1.421 +#ifdef TCL_THREADS
1.422 + TclpFinalizeThreadData(keyPtr);
1.423 +#else
1.424 + if (*keyPtr != NULL) {
1.425 + ckfree((char *)*keyPtr);
1.426 + *keyPtr = NULL;
1.427 + }
1.428 +#endif
1.429 + }
1.430 + TclpMasterUnlock();
1.431 +}
1.432 +
1.433 +/*
1.434 + *----------------------------------------------------------------------
1.435 + *
1.436 + * TclFinalizeSynchronization --
1.437 + *
1.438 + * This procedure cleans up all synchronization objects:
1.439 + * mutexes, condition variables, and thread-local storage.
1.440 + *
1.441 + * Results:
1.442 + * None.
1.443 + *
1.444 + * Side effects:
1.445 + * Frees up the memory.
1.446 + *
1.447 + *----------------------------------------------------------------------
1.448 + */
1.449 +
1.450 +void
1.451 +TclFinalizeSynchronization()
1.452 +{
1.453 +#ifdef TCL_THREADS
1.454 + Tcl_ThreadDataKey *keyPtr;
1.455 + Tcl_Mutex *mutexPtr;
1.456 + Tcl_Condition *condPtr;
1.457 + int i;
1.458 +
1.459 + TclpMasterLock();
1.460 + for (i=0 ; i<keyRecord.num ; i++) {
1.461 + keyPtr = (Tcl_ThreadDataKey *)keyRecord.list[i];
1.462 + TclpFinalizeThreadDataKey(keyPtr);
1.463 + }
1.464 + if (keyRecord.list != NULL) {
1.465 + ckfree((char *)keyRecord.list);
1.466 + keyRecord.list = NULL;
1.467 + }
1.468 + keyRecord.max = 0;
1.469 + keyRecord.num = 0;
1.470 +
1.471 + for (i=0 ; i<mutexRecord.num ; i++) {
1.472 + mutexPtr = (Tcl_Mutex *)mutexRecord.list[i];
1.473 + if (mutexPtr != NULL) {
1.474 + TclpFinalizeMutex(mutexPtr);
1.475 + }
1.476 + }
1.477 + if (mutexRecord.list != NULL) {
1.478 + ckfree((char *)mutexRecord.list);
1.479 + mutexRecord.list = NULL;
1.480 + }
1.481 + mutexRecord.max = 0;
1.482 + mutexRecord.num = 0;
1.483 +
1.484 + for (i=0 ; i<condRecord.num ; i++) {
1.485 + condPtr = (Tcl_Condition *)condRecord.list[i];
1.486 + if (condPtr != NULL) {
1.487 + TclpFinalizeCondition(condPtr);
1.488 + }
1.489 + }
1.490 + if (condRecord.list != NULL) {
1.491 + ckfree((char *)condRecord.list);
1.492 + condRecord.list = NULL;
1.493 + }
1.494 + condRecord.max = 0;
1.495 + condRecord.num = 0;
1.496 +
1.497 + TclpMasterUnlock();
1.498 +#else
1.499 + if (keyRecord.list != NULL) {
1.500 + ckfree((char *)keyRecord.list);
1.501 + keyRecord.list = NULL;
1.502 + }
1.503 + keyRecord.max = 0;
1.504 + keyRecord.num = 0;
1.505 +#endif
1.506 +}
1.507 +
1.508 +
1.509 +/*
1.510 + *----------------------------------------------------------------------
1.511 + *
1.512 + * Tcl_ExitThread --
1.513 + *
1.514 + * This procedure is called to terminate the current thread.
1.515 + * This should be used by extensions that create threads with
1.516 + * additional interpreters in them.
1.517 + *
1.518 + * Results:
1.519 + * None.
1.520 + *
1.521 + * Side effects:
1.522 + * All thread exit handlers are invoked, then the thread dies.
1.523 + *
1.524 + *----------------------------------------------------------------------
1.525 + */
1.526 +
1.527 +EXPORT_C void
1.528 +Tcl_ExitThread(status)
1.529 + int status;
1.530 +{
1.531 + Tcl_FinalizeThread();
1.532 +#ifdef TCL_THREADS
1.533 + TclpThreadExit(status);
1.534 +#endif
1.535 +}
1.536 +
1.537 +#ifndef TCL_THREADS
1.538 +
1.539 +/*
1.540 + *----------------------------------------------------------------------
1.541 + *
1.542 + * Tcl_ConditionWait, et al. --
1.543 + *
1.544 + * These noop procedures are provided so the stub table does
1.545 + * not have to be conditionalized for threads. The real
1.546 + * implementations of these functions live in the platform
1.547 + * specific files.
1.548 + *
1.549 + * Results:
1.550 + * None.
1.551 + *
1.552 + * Side effects:
1.553 + * None.
1.554 + *
1.555 + *----------------------------------------------------------------------
1.556 + */
1.557 +
1.558 +#undef Tcl_ConditionWait
1.559 +EXPORT_C void
1.560 +Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
1.561 + Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */
1.562 + Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
1.563 + Tcl_Time *timePtr; /* Timeout on waiting period */
1.564 +{
1.565 +}
1.566 +
1.567 +#undef Tcl_ConditionNotify
1.568 +EXPORT_C void
1.569 +Tcl_ConditionNotify(condPtr)
1.570 + Tcl_Condition *condPtr;
1.571 +{
1.572 +}
1.573 +
1.574 +#undef Tcl_MutexLock
1.575 +EXPORT_C void
1.576 +Tcl_MutexLock(mutexPtr)
1.577 + Tcl_Mutex *mutexPtr;
1.578 +{
1.579 +}
1.580 +
1.581 +#undef Tcl_MutexUnlock
1.582 +EXPORT_C void
1.583 +Tcl_MutexUnlock(mutexPtr)
1.584 + Tcl_Mutex *mutexPtr;
1.585 +{
1.586 +}
1.587 +#endif