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

📄 tclwinthrd.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 2 页
字号:
 * * 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 (DWORD **) */{    DWORD *indexPtr;    MASTER_LOCK;    if (*keyPtr == NULL) {	indexPtr = (DWORD *)ckalloc(sizeof(DWORD));	*indexPtr = TlsAlloc();	*keyPtr = (Tcl_ThreadDataKey)indexPtr;	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 (DWORD **) */{    DWORD *indexPtr = *(DWORD **)keyPtr;    if (indexPtr == NULL) {	return NULL;    } else {	return (VOID *) TlsGetValue(*indexPtr);    }}/* *---------------------------------------------------------------------- * * 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 */{    DWORD *indexPtr = *(DWORD **)keyPtr;    TlsSetValue(*indexPtr, (void *)data);}/* *---------------------------------------------------------------------- * * TclpFinalizeThreadData -- * *	This procedure cleans up the thread-local storage.  This is *	called once for each thread. * * Results: *	None. * * Side effects: *	Frees up the memory. * *---------------------------------------------------------------------- */voidTclpFinalizeThreadData(keyPtr)    Tcl_ThreadDataKey *keyPtr;{    VOID *result;    DWORD *indexPtr;#ifdef USE_THREAD_ALLOC    TclWinFreeAllocCache();#endif    if (*keyPtr != NULL) {	indexPtr = *(DWORD **)keyPtr;	result = (VOID *)TlsGetValue(*indexPtr);	if (result != NULL) {	    ckfree((char *)result);	    TlsSetValue(*indexPtr, (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;{    DWORD *indexPtr;    if (*keyPtr != NULL) {	indexPtr = *(DWORD **)keyPtr;	TlsFree(*indexPtr);	ckfree((char *)indexPtr);	*keyPtr = NULL;    }}/* *---------------------------------------------------------------------- * * Tcl_ConditionWait -- * *	This procedure is invoked to wait on a condition variable. *	The mutex is atomically 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 HANDLE *	and initialize this the first time this Tcl_Condition is used. * *---------------------------------------------------------------------- */voidTcl_ConditionWait(condPtr, mutexPtr, timePtr)    Tcl_Condition *condPtr;	/* Really (WinCondition **) */    Tcl_Mutex *mutexPtr;	/* Really (CRITICAL_SECTION **) */    Tcl_Time *timePtr;		/* Timeout on waiting period */{    WinCondition *winCondPtr;	/* Per-condition queue head */    CRITICAL_SECTION *csPtr;	/* Caller's Mutex, after casting */    DWORD wtime;		/* Windows time value */    int timeout;		/* True if we got a timeout */    int doExit = 0;		/* True if we need to do exit setup */    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (tsdPtr->flags & WIN_THREAD_DEAD) {	/*	 * No more per-thread event on which to wait.	 */	return;    }    /*     * Self initialize the two parts of the condition.     * The per-condition and per-thread parts need to be     * handled independently.     */    if (tsdPtr->flags == WIN_THREAD_UNINIT) {	MASTER_LOCK;	/* 	 * Create the per-thread event and queue pointers.	 */	if (tsdPtr->flags == WIN_THREAD_UNINIT) {	    tsdPtr->condEvent = CreateEvent(NULL, TRUE /* manual reset */,			FALSE /* non signaled */, NULL);	    tsdPtr->nextPtr = NULL;	    tsdPtr->prevPtr = NULL;	    tsdPtr->flags = WIN_THREAD_RUNNING;	    doExit = 1;	}	MASTER_UNLOCK;	if (doExit) {	    /*	     * Create a per-thread exit handler to clean up the condEvent.	     * We must be careful to do this outside the Master Lock	     * because Tcl_CreateThreadExitHandler uses its own	     * ThreadSpecificData, and initializing that may drop	     * back into the Master Lock.	     */	    	    Tcl_CreateThreadExitHandler(FinalizeConditionEvent,		    (ClientData) tsdPtr);	}    }    if (*condPtr == NULL) {	MASTER_LOCK;	/*	 * Initialize the per-condition queue pointers and Mutex.	 */	if (*condPtr == NULL) {	    winCondPtr = (WinCondition *)ckalloc(sizeof(WinCondition));	    InitializeCriticalSection(&winCondPtr->condLock);	    winCondPtr->firstPtr = NULL;	    winCondPtr->lastPtr = NULL;	    *condPtr = (Tcl_Condition)winCondPtr;	    TclRememberCondition(condPtr);	}	MASTER_UNLOCK;    }    csPtr = *((CRITICAL_SECTION **)mutexPtr);    winCondPtr = *((WinCondition **)condPtr);    if (timePtr == NULL) {	wtime = INFINITE;    } else {	wtime = timePtr->sec * 1000 + timePtr->usec / 1000;    }    /*     * Queue the thread on the condition, using     * the per-condition lock for serialization.     */    tsdPtr->flags = WIN_THREAD_BLOCKED;    tsdPtr->nextPtr = NULL;    EnterCriticalSection(&winCondPtr->condLock);    tsdPtr->prevPtr = winCondPtr->lastPtr;		/* A: */    winCondPtr->lastPtr = tsdPtr;    if (tsdPtr->prevPtr != NULL) {        tsdPtr->prevPtr->nextPtr = tsdPtr;    }    if (winCondPtr->firstPtr == NULL) {        winCondPtr->firstPtr = tsdPtr;    }    /*     * Unlock the caller's mutex and wait for the condition, or a timeout.     * There is a minor issue here in that we don't count down the     * timeout if we get notified, but another thread grabs the condition     * before we do.  In that race condition we'll wait again for the     * full timeout.  Timed waits are dubious anyway.  Either you have     * the locking protocol wrong and are masking a deadlock,     * or you are using conditions to pause your thread.     */        LeaveCriticalSection(csPtr);    timeout = 0;    while (!timeout && (tsdPtr->flags & WIN_THREAD_BLOCKED)) {	ResetEvent(tsdPtr->condEvent);	LeaveCriticalSection(&winCondPtr->condLock);	if (WaitForSingleObject(tsdPtr->condEvent, wtime) == WAIT_TIMEOUT) {	    timeout = 1;	}	EnterCriticalSection(&winCondPtr->condLock);    }    /*     * Be careful on timeouts because the signal might arrive right around     * time time limit and someone else could have taken us off the queue.     */        if (timeout) {	if (tsdPtr->flags & WIN_THREAD_RUNNING) {	    timeout = 0;	} else {	    /*	     * When dequeuing, we can leave the tsdPtr->nextPtr	     * and tsdPtr->prevPtr with dangling pointers because	     * they are reinitialilzed w/out reading them when the	     * thread is enqueued later.	     */            if (winCondPtr->firstPtr == tsdPtr) {                winCondPtr->firstPtr = tsdPtr->nextPtr;            } else {                tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;            }            if (winCondPtr->lastPtr == tsdPtr) {                winCondPtr->lastPtr = tsdPtr->prevPtr;            } else {                tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;            }            tsdPtr->flags = WIN_THREAD_RUNNING;	}    }    LeaveCriticalSection(&winCondPtr->condLock);    EnterCriticalSection(csPtr);}/* *---------------------------------------------------------------------- * * 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;{    WinCondition *winCondPtr;    ThreadSpecificData *tsdPtr;    if (condPtr != NULL) {	winCondPtr = *((WinCondition **)condPtr);	/*	 * Loop through all the threads waiting on the condition	 * and notify them (i.e., broadcast semantics).  The queue	 * manipulation is guarded by the per-condition coordinating mutex.	 */	EnterCriticalSection(&winCondPtr->condLock);	while (winCondPtr->firstPtr != NULL) {	    tsdPtr = winCondPtr->firstPtr;	    winCondPtr->firstPtr = tsdPtr->nextPtr;	    if (winCondPtr->lastPtr == tsdPtr) {		winCondPtr->lastPtr = NULL;	    }	    tsdPtr->flags = WIN_THREAD_RUNNING;	    tsdPtr->nextPtr = NULL;	    tsdPtr->prevPtr = NULL;	/* Not strictly necessary, see A: */	    SetEvent(tsdPtr->condEvent);	}	LeaveCriticalSection(&winCondPtr->condLock);    } else {	/*	 * Noone has used the condition variable, so there are no waiters.	 */    }}/* *---------------------------------------------------------------------- * * FinalizeConditionEvent -- * *	This procedure is invoked to clean up the per-thread *	event used to implement condition waiting. *	This is only safe to call at the end of time. * * Results: *	None. * * Side effects: *	The per-thread event is closed. * *---------------------------------------------------------------------- */static voidFinalizeConditionEvent(data)    ClientData data;{    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)data;    tsdPtr->flags = WIN_THREAD_DEAD;    CloseHandle(tsdPtr->condEvent);}/* *---------------------------------------------------------------------- * * 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;{    WinCondition *winCondPtr = *(WinCondition **)condPtr;    /*     * Note - this is called long after the thread-local storage is     * reclaimed.  The per-thread condition waiting event is     * reclaimed earlier in a per-thread exit handler, which is     * called before thread local storage is reclaimed.     */    if (winCondPtr != NULL) {	DeleteCriticalSection(&winCondPtr->condLock);	ckfree((char *)winCondPtr);	*condPtr = NULL;    }}/* * Additions by AOL for specialized thread memory allocator. */#ifdef USE_THREAD_ALLOCstatic DWORD key;Tcl_Mutex *TclpNewAllocMutex(void){    struct lock {        Tcl_Mutex        tlock;        CRITICAL_SECTION wlock;    } *lockPtr;    lockPtr = malloc(sizeof(struct lock));    if (lockPtr == NULL) {	panic("could not allocate lock");    }    lockPtr->tlock = (Tcl_Mutex) &lockPtr->wlock;    InitializeCriticalSection(&lockPtr->wlock);    return &lockPtr->tlock;}void *TclpGetAllocCache(void){    static int once = 0;    if (!once) {	/*	 * We need to make sure that TclWinFreeAllocCache is called	 * on each thread that calls this, but only on threads that	 * call this.	 */    	key = TlsAlloc();	once = 1;	if (key == TLS_OUT_OF_INDEXES) {	    panic("could not allocate thread local storage");	}    }    return TlsGetValue(key);}voidTclpSetAllocCache(void *ptr){    TlsSetValue(key, ptr);}voidTclWinFreeAllocCache(void){    void *ptr;    ptr = TlsGetValue(key);    if (ptr != NULL) {	TlsSetValue(key, NULL);	TclFreeAllocCache(ptr);    }}#endif /* USE_THREAD_ALLOC */#endif /* TCL_THREADS */

⌨️ 快捷键说明

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