📄 tclunixthrd.c
字号:
/* * tclUnixThrd.c -- * * This file implements the UNIX-specific thread support. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tclUnixThrd.c 1.18 98/02/19 14:24:12 */#include "tclInt.h"#include "tclPort.h"#ifdef TCL_THREADS#include "pthread.h"typedef struct ThreadSpecificData { char nabuf[16]; struct tm gtbuf; struct tm ltbuf; struct { Tcl_DirEntry ent; char name[MAXNAMLEN+1]; } rdbuf;} ThreadSpecificData;static Tcl_ThreadDataKey dataKey;/* * masterLock is used to serialize creation of mutexes, condition * variables, and thread local storage. * This is the only place that can count on the ability to statically * initialize the mutex. */static pthread_mutex_t masterLock = PTHREAD_MUTEX_INITIALIZER;/* * initLock is used to serialize initialization and finalization * of Tcl. It cannot use any dyamically allocated storage. */static pthread_mutex_t initLock = PTHREAD_MUTEX_INITIALIZER;/* * allocLock is used by Tcl's version of malloc for synchronization. * For obvious reasons, cannot use any dyamically allocated storage. */static pthread_mutex_t allocLock = PTHREAD_MUTEX_INITIALIZER;static pthread_mutex_t *allocLockPtr = &allocLock;/* * These are for the critical sections inside this file. */#define MASTER_LOCK pthread_mutex_lock(&masterLock)#define MASTER_UNLOCK pthread_mutex_unlock(&masterLock)#endif /* TCL_THREADS *//* *---------------------------------------------------------------------- * * Tcl_CreateThread -- * * This procedure creates a new thread. * * Results: * TCL_OK if the thread could be created. The thread ID is * returned in a parameter. * * Side effects: * A new thread is created. * *---------------------------------------------------------------------- */intTcl_CreateThread(idPtr, proc, clientData, stackSize, flags) Tcl_ThreadId *idPtr; /* Return, the ID of the thread */ Tcl_ThreadCreateProc proc; /* Main() function of the thread */ ClientData clientData; /* The one argument to Main() */ int stackSize; /* Size of stack for the new thread */ int flags; /* Flags controlling behaviour of * the new thread */{#ifdef TCL_THREADS pthread_attr_t attr; int result; pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE if (stackSize != TCL_THREAD_STACK_DEFAULT) { pthread_attr_setstacksize(&attr, (size_t) stackSize);#ifdef TCL_THREAD_STACK_MIN } else { /* * Certain systems define a thread stack size that by default is * too small for many operations. The user has the option of * defining TCL_THREAD_STACK_MIN to a value large enough to work * for their needs. This would look like (for 128K min stack): * make MEM_DEBUG_FLAGS=-DTCL_THREAD_STACK_MIN=131072L * * This solution is not optimal, as we should allow the user to * specify a size at runtime, but we don't want to slow this function * down, and that would still leave the main thread at the default. */ size_t size; result = pthread_attr_getstacksize(&attr, &size); if (!result && (size < TCL_THREAD_STACK_MIN)) { pthread_attr_setstacksize(&attr, (size_t) TCL_THREAD_STACK_MIN); }#endif }#endif if (! (flags & TCL_THREAD_JOINABLE)) { pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); } if (pthread_create((pthread_t *)idPtr, &attr, (void * (*)())proc, (void *)clientData) && pthread_create((pthread_t *)idPtr, NULL, (void * (*)())proc, (void *)clientData)) { result = TCL_ERROR; } else { result = TCL_OK; } pthread_attr_destroy(&attr); return result;#else return TCL_ERROR;#endif /* TCL_THREADS */}/* *---------------------------------------------------------------------- * * Tcl_JoinThread -- * * This procedure waits upon the exit of the specified thread. * * Results: * TCL_OK if the wait was successful, TCL_ERROR else. * * Side effects: * The result area is set to the exit code of the thread we * waited upon. * *---------------------------------------------------------------------- */intTcl_JoinThread(id, state) Tcl_ThreadId id; /* Id of the thread to wait upon */ int* state; /* Reference to the storage the result * of the thread we wait upon will be * written into. */{#ifdef TCL_THREADS int result; result = pthread_join ((pthread_t) id, (VOID**) state); return (result == 0) ? TCL_OK : TCL_ERROR;#else return TCL_ERROR;#endif}#ifdef TCL_THREADS/* *---------------------------------------------------------------------- * * TclpThreadExit -- * * This procedure terminates the current thread. * * Results: * None. * * Side effects: * This procedure terminates the current thread. * *---------------------------------------------------------------------- */voidTclpThreadExit(status) int status;{ pthread_exit((VOID *)status);}#endif /* TCL_THREADS *//* *---------------------------------------------------------------------- * * Tcl_GetCurrentThread -- * * This procedure returns the ID of the currently running thread. * * Results: * A thread ID. * * Side effects: * None. * *---------------------------------------------------------------------- */Tcl_ThreadIdTcl_GetCurrentThread(){#ifdef TCL_THREADS return (Tcl_ThreadId) pthread_self();#else return (Tcl_ThreadId) 0;#endif}/* *---------------------------------------------------------------------- * * TclpInitLock * * This procedure is used to grab a lock that serializes initialization * and finalization of Tcl. On some platforms this may also initialize * the mutex used to serialize creation of more mutexes and thread * local storage keys. * * Results: * None. * * Side effects: * Acquire the initialization mutex. * *---------------------------------------------------------------------- */voidTclpInitLock(){#ifdef TCL_THREADS pthread_mutex_lock(&initLock);#endif}/* *---------------------------------------------------------------------- * * TclpInitUnlock * * This procedure is used to release a lock that serializes initialization * and finalization of Tcl. * * Results: * None. * * Side effects: * Release the initialization mutex. * *---------------------------------------------------------------------- */voidTclpInitUnlock(){#ifdef TCL_THREADS pthread_mutex_unlock(&initLock);#endif}/* *---------------------------------------------------------------------- * * TclpMasterLock * * This procedure is used to grab a lock that serializes creation * and finalization of serialization objects. This interface is * only needed in finalization; it is hidden during * creation of the objects. * * This lock must be different than the initLock because the * initLock is held during creation of syncronization objects. * * Results: * None. * * Side effects: * Acquire the master mutex. * *---------------------------------------------------------------------- */voidTclpMasterLock(){#ifdef TCL_THREADS pthread_mutex_lock(&masterLock);#endif}/* *---------------------------------------------------------------------- * * TclpMasterUnlock * * This procedure is used to release a lock that serializes creation * and finalization of synchronization objects. * * Results: * None. * * Side effects: * Release the master mutex. * *---------------------------------------------------------------------- */voidTclpMasterUnlock(){#ifdef TCL_THREADS pthread_mutex_unlock(&masterLock);#endif}/* *---------------------------------------------------------------------- * * Tcl_GetAllocMutex * * This procedure returns a pointer to a statically initialized * mutex for use by the memory allocator. The alloctor must * use this lock, because all other locks are allocated... * * Results: * A pointer to a mutex that is suitable for passing to * Tcl_MutexLock and Tcl_MutexUnlock. * * Side effects: * None. * *---------------------------------------------------------------------- */Tcl_Mutex *Tcl_GetAllocMutex(){#ifdef TCL_THREADS return (Tcl_Mutex *)&allocLockPtr;#else return NULL;#endif}#ifdef TCL_THREADS/* *---------------------------------------------------------------------- * * Tcl_MutexLock -- * * This procedure is invoked to lock a mutex. This procedure * handles initializing the mutex, if necessary. The caller * can rely on the fact that Tcl_Mutex is an opaque pointer. * This routine will change that pointer from NULL after first use. * * Results: * None. * * Side effects: * May block the current thread. The mutex is aquired when * this returns. Will allocate memory for a pthread_mutex_t * and initialize this the first time this Tcl_Mutex is used. * *---------------------------------------------------------------------- */voidTcl_MutexLock(mutexPtr) Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */{ pthread_mutex_t *pmutexPtr; if (*mutexPtr == NULL) { MASTER_LOCK; if (*mutexPtr == NULL) { /* * Double inside master lock check to avoid a race condition. */ pmutexPtr = (pthread_mutex_t *)ckalloc(sizeof(pthread_mutex_t)); pthread_mutex_init(pmutexPtr, NULL); *mutexPtr = (Tcl_Mutex)pmutexPtr; TclRememberMutex(mutexPtr); } MASTER_UNLOCK; } pmutexPtr = *((pthread_mutex_t **)mutexPtr); pthread_mutex_lock(pmutexPtr);}/* *---------------------------------------------------------------------- * * Tcl_MutexUnlock -- * * This procedure is invoked to unlock a mutex. The mutex must * have been locked by Tcl_MutexLock. * * Results: * None. * * Side effects: * The mutex is released when this returns. * *---------------------------------------------------------------------- */voidTcl_MutexUnlock(mutexPtr) Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */{ pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr; pthread_mutex_unlock(pmutexPtr);}/* *---------------------------------------------------------------------- * * TclpFinalizeMutex -- * * This procedure is invoked to clean up one mutex. This is only * safe to call at the end of time. * * This assumes the Master Lock is held. * * Results: * None. * * Side effects: * The mutex list is deallocated. * *---------------------------------------------------------------------- */voidTclpFinalizeMutex(mutexPtr) Tcl_Mutex *mutexPtr;{ pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr; if (pmutexPtr != NULL) { ckfree((char *)pmutexPtr); *mutexPtr = NULL; }}/* *----------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -