os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixThrd.c
First public contribution.
4 * This file implements the UNIX-specific thread support.
6 * Copyright (c) 1991-1994 The Regents of the University of California.
7 * Copyright (c) 1994-1997 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 * SCCS: @(#) tclUnixThrd.c 1.18 98/02/19 14:24:12
23 typedef struct ThreadSpecificData {
27 static Tcl_ThreadDataKey dataKey;
30 * masterLock is used to serialize creation of mutexes, condition
31 * variables, and thread local storage.
32 * This is the only place that can count on the ability to statically
33 * initialize the mutex.
36 static pthread_mutex_t masterLock = PTHREAD_MUTEX_INITIALIZER;
39 * initLock is used to serialize initialization and finalization
40 * of Tcl. It cannot use any dyamically allocated storage.
43 static pthread_mutex_t initLock = PTHREAD_MUTEX_INITIALIZER;
46 * allocLock is used by Tcl's version of malloc for synchronization.
47 * For obvious reasons, cannot use any dyamically allocated storage.
50 static pthread_mutex_t allocLock = PTHREAD_MUTEX_INITIALIZER;
51 static pthread_mutex_t *allocLockPtr = &allocLock;
54 * These are for the critical sections inside this file.
57 #define MASTER_LOCK pthread_mutex_lock(&masterLock)
58 #define MASTER_UNLOCK pthread_mutex_unlock(&masterLock)
60 #endif /* TCL_THREADS */
64 *----------------------------------------------------------------------
68 * This procedure creates a new thread.
71 * TCL_OK if the thread could be created. The thread ID is
72 * returned in a parameter.
75 * A new thread is created.
77 *----------------------------------------------------------------------
81 TclpThreadCreate(idPtr, proc, clientData, stackSize, flags)
82 Tcl_ThreadId *idPtr; /* Return, the ID of the thread */
83 Tcl_ThreadCreateProc proc; /* Main() function of the thread */
84 ClientData clientData; /* The one argument to Main() */
85 int stackSize; /* Size of stack for the new thread */
86 int flags; /* Flags controlling behaviour of
94 pthread_attr_init(&attr);
95 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
97 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
98 if (stackSize != TCL_THREAD_STACK_DEFAULT) {
99 pthread_attr_setstacksize(&attr, (size_t) stackSize);
100 #ifdef TCL_THREAD_STACK_MIN
103 * Certain systems define a thread stack size that by default is
104 * too small for many operations. The user has the option of
105 * defining TCL_THREAD_STACK_MIN to a value large enough to work
106 * for their needs. This would look like (for 128K min stack):
107 * make MEM_DEBUG_FLAGS=-DTCL_THREAD_STACK_MIN=131072L
109 * This solution is not optimal, as we should allow the user to
110 * specify a size at runtime, but we don't want to slow this function
111 * down, and that would still leave the main thread at the default.
115 result = pthread_attr_getstacksize(&attr, &size);
116 if (!result && (size < TCL_THREAD_STACK_MIN)) {
117 pthread_attr_setstacksize(&attr, (size_t) TCL_THREAD_STACK_MIN);
122 if (! (flags & TCL_THREAD_JOINABLE)) {
123 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
127 if (pthread_create(&theThread, &attr,
128 (void * (*)())proc, (void *)clientData) &&
129 pthread_create(&theThread, NULL,
130 (void * (*)())proc, (void *)clientData)) {
133 *idPtr = (Tcl_ThreadId)theThread;
136 pthread_attr_destroy(&attr);
140 #endif /* TCL_THREADS */
144 *----------------------------------------------------------------------
148 * This procedure waits upon the exit of the specified thread.
151 * TCL_OK if the wait was successful, TCL_ERROR else.
154 * The result area is set to the exit code of the thread we
157 *----------------------------------------------------------------------
161 Tcl_JoinThread(threadId, state)
162 Tcl_ThreadId threadId; /* Id of the thread to wait upon */
163 int* state; /* Reference to the storage the result
164 * of the thread we wait upon will be
170 result = pthread_join ((pthread_t) threadId, (VOID**) state);
171 return (result == 0) ? TCL_OK : TCL_ERROR;
179 *----------------------------------------------------------------------
183 * This procedure terminates the current thread.
189 * This procedure terminates the current thread.
191 *----------------------------------------------------------------------
195 TclpThreadExit(status)
198 pthread_exit((VOID *)status);
200 #endif /* TCL_THREADS */
203 *----------------------------------------------------------------------
205 * Tcl_GetCurrentThread --
207 * This procedure returns the ID of the currently running thread.
215 *----------------------------------------------------------------------
218 EXPORT_C Tcl_ThreadId
219 Tcl_GetCurrentThread()
222 return (Tcl_ThreadId) pthread_self();
224 return (Tcl_ThreadId) 0;
230 *----------------------------------------------------------------------
234 * This procedure is used to grab a lock that serializes initialization
235 * and finalization of Tcl. On some platforms this may also initialize
236 * the mutex used to serialize creation of more mutexes and thread
237 * local storage keys.
243 * Acquire the initialization mutex.
245 *----------------------------------------------------------------------
252 pthread_mutex_lock(&initLock);
257 *----------------------------------------------------------------------
261 * This procedure is used to destroy all private resources used in
268 * Destroys everything private. TclpInitLock must be held
269 * entering this function.
271 *----------------------------------------------------------------------
279 * You do not need to destroy mutexes that were created with the
280 * PTHREAD_MUTEX_INITIALIZER macro. These mutexes do not need
281 * any destruction: masterLock, allocLock, and initLock.
283 pthread_mutex_unlock(&initLock);
288 *----------------------------------------------------------------------
292 * This procedure is used to release a lock that serializes initialization
293 * and finalization of Tcl.
299 * Release the initialization mutex.
301 *----------------------------------------------------------------------
308 pthread_mutex_unlock(&initLock);
313 *----------------------------------------------------------------------
317 * This procedure is used to grab a lock that serializes creation
318 * and finalization of serialization objects. This interface is
319 * only needed in finalization; it is hidden during
320 * creation of the objects.
322 * This lock must be different than the initLock because the
323 * initLock is held during creation of syncronization objects.
329 * Acquire the master mutex.
331 *----------------------------------------------------------------------
338 pthread_mutex_lock(&masterLock);
344 *----------------------------------------------------------------------
348 * This procedure is used to release a lock that serializes creation
349 * and finalization of synchronization objects.
355 * Release the master mutex.
357 *----------------------------------------------------------------------
364 pthread_mutex_unlock(&masterLock);
370 *----------------------------------------------------------------------
374 * This procedure returns a pointer to a statically initialized
375 * mutex for use by the memory allocator. The alloctor must
376 * use this lock, because all other locks are allocated...
379 * A pointer to a mutex that is suitable for passing to
380 * Tcl_MutexLock and Tcl_MutexUnlock.
385 *----------------------------------------------------------------------
392 return (Tcl_Mutex *)&allocLockPtr;
401 *----------------------------------------------------------------------
405 * This procedure is invoked to lock a mutex. This procedure
406 * handles initializing the mutex, if necessary. The caller
407 * can rely on the fact that Tcl_Mutex is an opaque pointer.
408 * This routine will change that pointer from NULL after first use.
414 * May block the current thread. The mutex is aquired when
415 * this returns. Will allocate memory for a pthread_mutex_t
416 * and initialize this the first time this Tcl_Mutex is used.
418 *----------------------------------------------------------------------
422 Tcl_MutexLock(mutexPtr)
423 Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
425 pthread_mutex_t *pmutexPtr;
426 if (*mutexPtr == NULL) {
428 if (*mutexPtr == NULL) {
430 * Double inside master lock check to avoid a race condition.
433 pmutexPtr = (pthread_mutex_t *)ckalloc(sizeof(pthread_mutex_t));
434 pthread_mutex_init(pmutexPtr, NULL);
435 *mutexPtr = (Tcl_Mutex)pmutexPtr;
436 TclRememberMutex(mutexPtr);
440 pmutexPtr = *((pthread_mutex_t **)mutexPtr);
441 pthread_mutex_lock(pmutexPtr);
446 *----------------------------------------------------------------------
450 * This procedure is invoked to unlock a mutex. The mutex must
451 * have been locked by Tcl_MutexLock.
457 * The mutex is released when this returns.
459 *----------------------------------------------------------------------
463 Tcl_MutexUnlock(mutexPtr)
464 Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
466 pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr;
467 pthread_mutex_unlock(pmutexPtr);
472 *----------------------------------------------------------------------
474 * TclpFinalizeMutex --
476 * This procedure is invoked to clean up one mutex. This is only
477 * safe to call at the end of time.
479 * This assumes the Master Lock is held.
485 * The mutex list is deallocated.
487 *----------------------------------------------------------------------
491 TclpFinalizeMutex(mutexPtr)
494 pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr;
495 if (pmutexPtr != NULL) {
496 pthread_mutex_destroy(pmutexPtr);
497 ckfree((char *)pmutexPtr);
504 *----------------------------------------------------------------------
506 * TclpThreadDataKeyInit --
508 * This procedure initializes a thread specific data block key.
509 * Each thread has table of pointers to thread specific data.
510 * all threads agree on which table entry is used by each module.
511 * this is remembered in a "data key", that is just an index into
512 * this table. To allow self initialization, the interface
513 * passes a pointer to this key and the first thread to use
514 * the key fills in the pointer to the key. The key should be
515 * a process-wide static.
521 * Will allocate memory the first time this process calls for
522 * this key. In this case it modifies its argument
523 * to hold the pointer to information about the key.
525 *----------------------------------------------------------------------
529 TclpThreadDataKeyInit(keyPtr)
530 Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
531 * really (pthread_key_t **) */
533 pthread_key_t *pkeyPtr;
536 if (*keyPtr == NULL) {
537 pkeyPtr = (pthread_key_t *)ckalloc(sizeof(pthread_key_t));
538 pthread_key_create(pkeyPtr, NULL);
539 *keyPtr = (Tcl_ThreadDataKey)pkeyPtr;
540 TclRememberDataKey(keyPtr);
546 *----------------------------------------------------------------------
548 * TclpThreadDataKeyGet --
550 * This procedure returns a pointer to a block of thread local storage.
553 * A thread-specific pointer to the data structure, or NULL
554 * if the memory has not been assigned to this key for this thread.
559 *----------------------------------------------------------------------
563 TclpThreadDataKeyGet(keyPtr)
564 Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
565 * really (pthread_key_t **) */
567 pthread_key_t *pkeyPtr = *(pthread_key_t **)keyPtr;
568 if (pkeyPtr == NULL) {
571 return (VOID *)pthread_getspecific(*pkeyPtr);
577 *----------------------------------------------------------------------
579 * TclpThreadDataKeySet --
581 * This procedure sets the pointer to a block of thread local storage.
587 * Sets up the thread so future calls to TclpThreadDataKeyGet with
588 * this key will return the data pointer.
590 *----------------------------------------------------------------------
594 TclpThreadDataKeySet(keyPtr, data)
595 Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
596 * really (pthread_key_t **) */
597 VOID *data; /* Thread local storage */
599 pthread_key_t *pkeyPtr = *(pthread_key_t **)keyPtr;
600 pthread_setspecific(*pkeyPtr, data);
604 *----------------------------------------------------------------------
606 * TclpFinalizeThreadData --
608 * This procedure cleans up the thread-local storage. This is
609 * called once for each thread.
615 * Frees up all thread local storage.
617 *----------------------------------------------------------------------
621 TclpFinalizeThreadData(keyPtr)
622 Tcl_ThreadDataKey *keyPtr;
625 pthread_key_t *pkeyPtr;
627 if (*keyPtr != NULL) {
628 pkeyPtr = *(pthread_key_t **)keyPtr;
629 result = (VOID *)pthread_getspecific(*pkeyPtr);
630 if (result != NULL) {
631 ckfree((char *)result);
632 pthread_setspecific(*pkeyPtr, (void *)NULL);
638 *----------------------------------------------------------------------
640 * TclpFinalizeThreadDataKey --
642 * This procedure is invoked to clean up one key. This is a
643 * process-wide storage identifier. The thread finalization code
644 * cleans up the thread local storage itself.
646 * This assumes the master lock is held.
652 * The key is deallocated.
654 *----------------------------------------------------------------------
658 TclpFinalizeThreadDataKey(keyPtr)
659 Tcl_ThreadDataKey *keyPtr;
661 pthread_key_t *pkeyPtr;
662 if (*keyPtr != NULL) {
663 pkeyPtr = *(pthread_key_t **)keyPtr;
664 pthread_key_delete(*pkeyPtr);
665 ckfree((char *)pkeyPtr);
672 *----------------------------------------------------------------------
674 * Tcl_ConditionWait --
676 * This procedure is invoked to wait on a condition variable.
677 * The mutex is automically released as part of the wait, and
678 * automatically grabbed when the condition is signaled.
680 * The mutex must be held when this procedure is called.
686 * May block the current thread. The mutex is aquired when
687 * this returns. Will allocate memory for a pthread_mutex_t
688 * and initialize this the first time this Tcl_Mutex is used.
690 *----------------------------------------------------------------------
694 Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
695 Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */
696 Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
697 Tcl_Time *timePtr; /* Timeout on waiting period */
699 pthread_cond_t *pcondPtr;
700 pthread_mutex_t *pmutexPtr;
701 struct timespec ptime;
703 if (*condPtr == NULL) {
707 * Double check inside mutex to avoid race,
708 * then initialize condition variable if necessary.
711 if (*condPtr == NULL) {
712 pcondPtr = (pthread_cond_t *)ckalloc(sizeof(pthread_cond_t));
713 pthread_cond_init(pcondPtr, NULL);
714 *condPtr = (Tcl_Condition)pcondPtr;
715 TclRememberCondition(condPtr);
719 pmutexPtr = *((pthread_mutex_t **)mutexPtr);
720 pcondPtr = *((pthread_cond_t **)condPtr);
721 if (timePtr == NULL) {
722 pthread_cond_wait(pcondPtr, pmutexPtr);
727 * Make sure to take into account the microsecond component of the
728 * current time, including possible overflow situations. [Bug #411603]
732 ptime.tv_sec = timePtr->sec + now.sec +
733 (timePtr->usec + now.usec) / 1000000;
734 ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000);
735 pthread_cond_timedwait(pcondPtr, pmutexPtr, &ptime);
740 *----------------------------------------------------------------------
742 * Tcl_ConditionNotify --
744 * This procedure is invoked to signal a condition variable.
746 * The mutex must be held during this call to avoid races,
747 * but this interface does not enforce that.
753 * May unblock another thread.
755 *----------------------------------------------------------------------
759 Tcl_ConditionNotify(condPtr)
760 Tcl_Condition *condPtr;
762 pthread_cond_t *pcondPtr = *((pthread_cond_t **)condPtr);
763 if (pcondPtr != NULL) {
764 pthread_cond_broadcast(pcondPtr);
767 * Noone has used the condition variable, so there are no waiters.
774 *----------------------------------------------------------------------
776 * TclpFinalizeCondition --
778 * This procedure is invoked to clean up a condition variable.
779 * This is only safe to call at the end of time.
781 * This assumes the Master Lock is held.
787 * The condition variable is deallocated.
789 *----------------------------------------------------------------------
793 TclpFinalizeCondition(condPtr)
794 Tcl_Condition *condPtr;
796 pthread_cond_t *pcondPtr = *(pthread_cond_t **)condPtr;
797 if (pcondPtr != NULL) {
798 pthread_cond_destroy(pcondPtr);
799 ckfree((char *)pcondPtr);
803 #endif /* TCL_THREADS */
806 *----------------------------------------------------------------------
808 * TclpReaddir, TclpLocaltime, TclpGmtime, TclpInetNtoa --
810 * These procedures replace core C versions to be used in a
811 * threaded environment.
814 * See documentation of C functions.
817 * See documentation of C functions.
820 * TclpReaddir is no longer used by the core (see 1095909),
821 * but it appears in the internal stubs table (see #589526).
822 *----------------------------------------------------------------------
826 TclpReaddir(DIR * dir)
828 return TclOSreaddir(dir);
832 TclpInetNtoa(struct in_addr addr)
835 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
836 unsigned char *b = (unsigned char*) &addr.s_addr;
838 sprintf(tsdPtr->nabuf, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]);
839 return tsdPtr->nabuf;
841 return inet_ntoa(addr);
845 #if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) && !defined(TCL_MEM_DEBUG)
847 * Additions by AOL for specialized thread memory allocator.
849 #ifdef USE_THREAD_ALLOC
850 static volatile int initialized = 0;
851 static pthread_key_t key;
853 typedef struct allocMutex {
855 pthread_mutex_t plock;
859 TclpNewAllocMutex(void)
861 struct allocMutex *lockPtr;
863 lockPtr = malloc(sizeof(struct allocMutex));
864 if (lockPtr == NULL) {
865 panic("could not allocate lock");
867 lockPtr->tlock = (Tcl_Mutex) &lockPtr->plock;
868 pthread_mutex_init(&lockPtr->plock, NULL);
869 return &lockPtr->tlock;
873 TclpFreeAllocMutex(mutex)
874 Tcl_Mutex *mutex; /* The alloc mutex to free. */
876 allocMutex* lockPtr = (allocMutex*) mutex;
877 if (!lockPtr) return;
878 pthread_mutex_destroy(&lockPtr->plock);
882 void TclpFreeAllocCache(ptr)
887 * Called by the pthread lib when a thread exits
889 TclFreeAllocCache(ptr);
890 } else if (initialized) {
892 * Called by us in TclFinalizeThreadAlloc() during
893 * the library finalization initiated from Tcl_Finalize()
895 pthread_key_delete(key);
901 TclpGetAllocCache(void)
904 pthread_mutex_lock(allocLockPtr);
906 pthread_key_create(&key, TclpFreeAllocCache);
909 pthread_mutex_unlock(allocLockPtr);
911 return pthread_getspecific(key);
915 TclpSetAllocCache(void *arg)
917 pthread_setspecific(key, arg);
920 #endif /* USE_THREAD_ALLOC */
921 #endif /* TCL_THREADS */