⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclunixthrd.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 2 页
字号:
 * * TclpThreadDataKeyInit -- * *	This procedure initializes a thread specific data block key. *	Each thread has table of pointers to thread specific data. *	all threads agree on which table entry is used by each module. *	this is remembered in a "data key", that is just an index into *	this table.  To allow self initialization, the interface *	passes a pointer to this key and the first thread to use *	the key fills in the pointer to the key.  The key should be *	a process-wide static. * * Results: *	None. * * Side effects: *	Will allocate memory the first time this process calls for *	this key.  In this case it modifies its argument *	to hold the pointer to information about the key. * *---------------------------------------------------------------------- */voidTclpThreadDataKeyInit(keyPtr)    Tcl_ThreadDataKey *keyPtr;	/* Identifier for the data chunk,				 * really (pthread_key_t **) */{    pthread_key_t *pkeyPtr;    MASTER_LOCK;    if (*keyPtr == NULL) {	pkeyPtr = (pthread_key_t *)ckalloc(sizeof(pthread_key_t));	pthread_key_create(pkeyPtr, NULL);	*keyPtr = (Tcl_ThreadDataKey)pkeyPtr;	TclRememberDataKey(keyPtr);    }    MASTER_UNLOCK;}/* *---------------------------------------------------------------------- * * TclpThreadDataKeyGet -- * *	This procedure returns a pointer to a block of thread local storage. * * Results: *	A thread-specific pointer to the data structure, or NULL *	if the memory has not been assigned to this key for this thread. * * Side effects: *	None. * *---------------------------------------------------------------------- */VOID *TclpThreadDataKeyGet(keyPtr)    Tcl_ThreadDataKey *keyPtr;	/* Identifier for the data chunk,				 * really (pthread_key_t **) */{    pthread_key_t *pkeyPtr = *(pthread_key_t **)keyPtr;    if (pkeyPtr == NULL) {	return NULL;    } else {	return (VOID *)pthread_getspecific(*pkeyPtr);    }}/* *---------------------------------------------------------------------- * * TclpThreadDataKeySet -- * *	This procedure sets the pointer to a block of thread local storage. * * Results: *	None. * * Side effects: *	Sets up the thread so future calls to TclpThreadDataKeyGet with *	this key will return the data pointer. * *---------------------------------------------------------------------- */voidTclpThreadDataKeySet(keyPtr, data)    Tcl_ThreadDataKey *keyPtr;	/* Identifier for the data chunk,				 * really (pthread_key_t **) */    VOID *data;			/* Thread local storage */{    pthread_key_t *pkeyPtr = *(pthread_key_t **)keyPtr;    pthread_setspecific(*pkeyPtr, data);}/* *---------------------------------------------------------------------- * * TclpFinalizeThreadData -- * *	This procedure cleans up the thread-local storage.  This is *	called once for each thread. * * Results: *	None. * * Side effects: *	Frees up all thread local storage. * *---------------------------------------------------------------------- */voidTclpFinalizeThreadData(keyPtr)    Tcl_ThreadDataKey *keyPtr;{    VOID *result;    pthread_key_t *pkeyPtr;    if (*keyPtr != NULL) {	pkeyPtr = *(pthread_key_t **)keyPtr;	result = (VOID *)pthread_getspecific(*pkeyPtr);	if (result != NULL) {	    ckfree((char *)result);	    pthread_setspecific(*pkeyPtr, (void *)NULL);	}    }}/* *---------------------------------------------------------------------- * * TclpFinalizeThreadDataKey -- * *	This procedure is invoked to clean up one key.  This is a *	process-wide storage identifier.  The thread finalization code *	cleans up the thread local storage itself. * *	This assumes the master lock is held. * * Results: *	None. * * Side effects: *	The key is deallocated. * *---------------------------------------------------------------------- */voidTclpFinalizeThreadDataKey(keyPtr)    Tcl_ThreadDataKey *keyPtr;{    pthread_key_t *pkeyPtr;    if (*keyPtr != NULL) {	pkeyPtr = *(pthread_key_t **)keyPtr;	pthread_key_delete(*pkeyPtr);	ckfree((char *)pkeyPtr);	*keyPtr = NULL;    }}/* *---------------------------------------------------------------------- * * Tcl_ConditionWait -- * *	This procedure is invoked to wait on a condition variable. *	The mutex is automically released as part of the wait, and *	automatically grabbed when the condition is signaled. * *	The mutex must be held when this procedure is called. * * 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_ConditionWait(condPtr, mutexPtr, timePtr)    Tcl_Condition *condPtr;	/* Really (pthread_cond_t **) */    Tcl_Mutex *mutexPtr;	/* Really (pthread_mutex_t **) */    Tcl_Time *timePtr;		/* Timeout on waiting period */{    pthread_cond_t *pcondPtr;    pthread_mutex_t *pmutexPtr;    struct timespec ptime;    if (*condPtr == NULL) {	MASTER_LOCK;	/* 	 * Double check inside mutex to avoid race,	 * then initialize condition variable if necessary.	 */	if (*condPtr == NULL) {	    pcondPtr = (pthread_cond_t *)ckalloc(sizeof(pthread_cond_t));	    pthread_cond_init(pcondPtr, NULL);	    *condPtr = (Tcl_Condition)pcondPtr;	    TclRememberCondition(condPtr);	}	MASTER_UNLOCK;    }    pmutexPtr = *((pthread_mutex_t **)mutexPtr);    pcondPtr = *((pthread_cond_t **)condPtr);    if (timePtr == NULL) {	pthread_cond_wait(pcondPtr, pmutexPtr);    } else {	Tcl_Time now;	/*	 * Make sure to take into account the microsecond component of the	 * current time, including possible overflow situations. [Bug #411603]	 */	Tcl_GetTime(&now);	ptime.tv_sec = timePtr->sec + now.sec +	    (timePtr->usec + now.usec) / 1000000;	ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000);	pthread_cond_timedwait(pcondPtr, pmutexPtr, &ptime);    }}/* *---------------------------------------------------------------------- * * Tcl_ConditionNotify -- * *	This procedure is invoked to signal a condition variable. * *	The mutex must be held during this call to avoid races, *	but this interface does not enforce that. * * Results: *	None. * * Side effects: *	May unblock another thread. * *---------------------------------------------------------------------- */voidTcl_ConditionNotify(condPtr)    Tcl_Condition *condPtr;{    pthread_cond_t *pcondPtr = *((pthread_cond_t **)condPtr);    if (pcondPtr != NULL) {	pthread_cond_broadcast(pcondPtr);    } else {	/*	 * Noone has used the condition variable, so there are no waiters.	 */    }}/* *---------------------------------------------------------------------- * * TclpFinalizeCondition -- * *	This procedure is invoked to clean up a condition variable. *	This is only safe to call at the end of time. * *	This assumes the Master Lock is held. * * Results: *	None. * * Side effects: *	The condition variable is deallocated. * *---------------------------------------------------------------------- */voidTclpFinalizeCondition(condPtr)    Tcl_Condition *condPtr;{    pthread_cond_t *pcondPtr = *(pthread_cond_t **)condPtr;    if (pcondPtr != NULL) {	pthread_cond_destroy(pcondPtr);	ckfree((char *)pcondPtr);	*condPtr = NULL;    }}#endif /* TCL_THREADS *//* *---------------------------------------------------------------------- * * TclpReaddir, TclpLocaltime, TclpGmtime, TclpInetNtoa -- * *	These procedures replace core C versions to be used in a *	threaded environment. * * Results: *	See documentation of C functions. * * Side effects: *	See documentation of C functions. * *---------------------------------------------------------------------- */#if defined(TCL_THREADS) && !defined(HAVE_READDIR_R)TCL_DECLARE_MUTEX( rdMutex )#undef readdir#endifTcl_DirEntry *TclpReaddir(DIR * dir){    Tcl_DirEntry *ent;#ifdef TCL_THREADS    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);#ifdef HAVE_READDIR_R    ent = &tsdPtr->rdbuf.ent;     if (TclOSreaddir_r(dir, ent, &ent) != 0) {	ent = NULL;    }#else /* !HAVE_READDIR_R */    Tcl_MutexLock(&rdMutex);#   ifdef HAVE_STRUCT_DIRENT64    ent = readdir64(dir);#   else /* !HAVE_STRUCT_DIRENT64 */    ent = readdir(dir);#   endif /* HAVE_STRUCT_DIRENT64 */    if (ent != NULL) {	memcpy((VOID *) &tsdPtr->rdbuf.ent, (VOID *) ent,		sizeof(&tsdPtr->rdbuf));	ent = &tsdPtr->rdbuf.ent;    }    Tcl_MutexUnlock(&rdMutex);#endif /* HAVE_READDIR_R */#else#   ifdef HAVE_STRUCT_DIRENT64    ent = readdir64(dir);#   else /* !HAVE_STRUCT_DIRENT64 */    ent = readdir(dir);#   endif /* HAVE_STRUCT_DIRENT64 */#endif    return ent;}#if defined(TCL_THREADS) && (!defined(HAVE_GMTIME_R) || !defined(HAVE_LOCALTIME_R))TCL_DECLARE_MUTEX( tmMutex )#undef localtime#undef gmtime#endifstruct tm *TclpLocaltime(time_t * clock){#ifdef TCL_THREADS    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);#ifdef HAVE_LOCALTIME_R    return localtime_r(clock, &tsdPtr->ltbuf);#else    Tcl_MutexLock( &tmMutex );    memcpy( (VOID *) &tsdPtr->ltbuf, (VOID *) localtime( clock ), sizeof (struct tm) );    Tcl_MutexUnlock( &tmMutex );    return &tsdPtr->ltbuf;#endif    #else    return localtime(clock);#endif}struct tm *TclpGmtime(time_t * clock){#ifdef TCL_THREADS    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);#ifdef HAVE_GMTIME_R    return gmtime_r(clock, &tsdPtr->gtbuf);#else    Tcl_MutexLock( &tmMutex );    memcpy( (VOID *) &tsdPtr->gtbuf, (VOID *) gmtime( clock ), sizeof (struct tm) );    Tcl_MutexUnlock( &tmMutex );    return &tsdPtr->gtbuf;#endif    #else    return gmtime(clock);#endif}char *TclpInetNtoa(struct in_addr addr){#ifdef TCL_THREADS    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    union {    	unsigned long l;    	unsigned char b[4];    } u;        u.l = (unsigned long) addr.s_addr;    sprintf(tsdPtr->nabuf, "%u.%u.%u.%u", u.b[0], u.b[1], u.b[2], u.b[3]);    return tsdPtr->nabuf;#else    return inet_ntoa(addr);#endif}#ifdef TCL_THREADS/* * Additions by AOL for specialized thread memory allocator. */#ifdef USE_THREAD_ALLOCstatic int initialized = 0;static pthread_key_t	key;static pthread_once_t	once = PTHREAD_ONCE_INIT;Tcl_Mutex *TclpNewAllocMutex(void){    struct lock {        Tcl_Mutex       tlock;        pthread_mutex_t plock;    } *lockPtr;    lockPtr = malloc(sizeof(struct lock));    if (lockPtr == NULL) {	panic("could not allocate lock");    }    lockPtr->tlock = (Tcl_Mutex) &lockPtr->plock;    pthread_mutex_init(&lockPtr->plock, NULL);    return &lockPtr->tlock;}static voidInitKey(void){    extern void TclFreeAllocCache(void *);    pthread_key_create(&key, TclFreeAllocCache);    initialized = 1;}void *TclpGetAllocCache(void){    if (!initialized) {	pthread_once(&once, InitKey);    }    return pthread_getspecific(key);}voidTclpSetAllocCache(void *arg){    pthread_setspecific(key, arg);}#endif /* USE_THREAD_ALLOC */#endif /* TCL_THREADS */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -