diff options
author | Jarkko Hietaniemi <jhi@iki.fi> | 2001-06-16 19:46:38 +0000 |
---|---|---|
committer | Jarkko Hietaniemi <jhi@iki.fi> | 2001-06-16 19:46:38 +0000 |
commit | 2986a63f7e513cf37f46db9f211b77071260031f (patch) | |
tree | 9a6e62602396938ea5a612420f53ebf267e8d941 /NetWare/NWTInfo.c | |
parent | 87b11a197a59fac210fc9265bde0ef1ffe36de89 (diff) | |
download | perl-2986a63f7e513cf37f46db9f211b77071260031f.tar.gz |
NetWare port from Guruprasad S <SGURUPRASAD@novell.com>.
p4raw-id: //depot/perl@10643
Diffstat (limited to 'NetWare/NWTInfo.c')
-rw-r--r-- | NetWare/NWTInfo.c | 720 |
1 files changed, 720 insertions, 0 deletions
diff --git a/NetWare/NWTInfo.c b/NetWare/NWTInfo.c new file mode 100644 index 0000000000..4180fa796f --- /dev/null +++ b/NetWare/NWTInfo.c @@ -0,0 +1,720 @@ + +/* + * Copyright © 2001 Novell, Inc. All Rights Reserved. + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the README file. + * + */ + +/* + * FILENAME : NWTInfo.c + * DESCRIPTION : Thread-local storage for Perl. + * The thread's information is stored in a hashed table that is based on + * the lowest 5 bits of the current thread ID. + * Author : SGP, HYAK + * Date : January 2001. + * + */ + + + +#include "win32ish.h" // For "BOOL", "TRUE" and "FALSE" +#include "nwtinfo.h" + +#ifdef MPK_ON + #include <mpktypes.h> + #include <mpkapis.h> +#else + #include <nwsemaph.h> +#endif //MPK_ON + +// Number of entries in the hashtable +// +#define NUM_ENTRIES 32 /* 2^5 */ + + +// macro to calculate the hash index for a given Thread ID +// +#define INDEXOF(tid) ((tid) & 0x1f) + + +// Semaphore to control access to global linked list +// +#ifdef MPK_ON + static SEMAPHORE g_tinfoSem = NULL; + static SEMAPHORE g_tCtxSem = NULL; +#else + static LONG g_tinfoSem = 0L; + static LONG g_tCtxSem = 0L; +#endif //MPK_ON + +// Hash table of thread information structures +// +ThreadInfo* g_ThreadInfo[NUM_ENTRIES]; +ThreadContext* g_ThreadCtx; + + + +/*============================================================================================ + + Function : fnTerminateThreadInfo + + Description : This function undoes fnInitializeThreadInfo; call once per NLM instance. + + Parameters : None. + + Returns : Boolean. + +==============================================================================================*/ + +BOOL fnTerminateThreadInfo(void) +{ + int index = 0; + + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreWait(g_tinfoSem); + #else + WaitOnLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + for (index = 0; index < NUM_ENTRIES; index++) + { + if (g_ThreadInfo[index] != NULL) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tinfoSem); + #else + SignalLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + return FALSE; + } + } + #ifdef MPK_ON + kSemaphoreFree(g_tinfoSem); + g_tinfoSem = NULL; + #else + CloseLocalSemaphore(g_tinfoSem); + g_tinfoSem = 0; + #endif //MPK_ON + } + + return TRUE; +} + + +/*============================================================================================ + + Function : fnInitializeThreadInfo + + Description : Initializes the global ThreadInfo hashtable and semaphore. + Call once per NLM instance + + Parameters : None. + + Returns : Nothing. + +==============================================================================================*/ + +void fnInitializeThreadInfo(void) +{ + int index = 0; + + if (g_tinfoSem) + return; + + #ifdef MPK_ON + g_tinfoSem = kSemaphoreAlloc((BYTE *)"threadInfo", 1); + #else + g_tinfoSem = OpenLocalSemaphore(1); + #endif //MPK_ON + + + for (index = 0; index < NUM_ENTRIES; index++) + g_ThreadInfo[index] = NULL; + + return; +} + + +/*============================================================================================ + + Function : fnRegisterWithThreadTable + + Description : This function registers/adds a new thread with the thread table. + + Parameters : None. + + Returns : Boolean. + +==============================================================================================*/ + +BOOL fnRegisterWithThreadTable(void) +{ + ThreadInfo* tinfo = NULL; + + #ifdef MPK_ON + tinfo = fnAddThreadInfo(labs((int)kCurrentThread())); + #else + tinfo = fnAddThreadInfo(GetThreadID()); + #endif //MPK_ON + + if (!tinfo) + return FALSE; + else + return TRUE; +} + + +/*============================================================================================ + + Function : fnUnregisterWithThreadTable + + Description : This function unregisters/removes a thread from the thread table. + + Parameters : None. + + Returns : Boolean. + +==============================================================================================*/ + +BOOL fnUnregisterWithThreadTable(void) +{ + #ifdef MPK_ON + return fnRemoveThreadInfo(labs((int)kCurrentThread())); + #else + return fnRemoveThreadInfo(GetThreadID()); + #endif //MPK_ON +} + + +/*============================================================================================ + + Function : fnAddThreadInfo + + Description : Adds a new ThreadInfo for the requested thread. + + Parameters : tid (IN) - ID of the thread. + + Returns : Pointer to the ThreadInfo Structure. + +==============================================================================================*/ + +ThreadInfo* fnAddThreadInfo(int tid) +{ + ThreadInfo* tip = NULL; + int index = 0; + + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreWait(g_tinfoSem); + #else + WaitOnLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + + // Add a new one to the beginning of the hash entry + // + tip = (ThreadInfo *) malloc(sizeof(ThreadInfo)); + if (tip == NULL) + { + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tinfoSem); + #else + SignalLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + return NULL; + } + index = INDEXOF(tid); // just take the bottom five bits + tip->next = g_ThreadInfo[index]; + tip->tid = tid; + tip->m_dontTouchHashLists = FALSE; + tip->m_allocList = NULL; + + g_ThreadInfo [index] = tip; + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tinfoSem); + #else + SignalLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + + return tip; +} + + +/*============================================================================================ + + Function : fnRemoveThreadInfo + + Description : Frees the specified thread info structure and removes it from the + global linked list. + + Parameters : tid (IN) - ID of the thread. + + Returns : Boolean. + +==============================================================================================*/ + +BOOL fnRemoveThreadInfo(int tid) +{ + ThreadInfo* tip = NULL; + ThreadInfo* prevt = NULL; + int index = INDEXOF(tid); // just take the bottom five bits + + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreWait(g_tinfoSem); + #else + WaitOnLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + + for (tip = g_ThreadInfo[index]; tip != NULL; tip = tip->next) + { + if (tip->tid == tid) + { + if (prevt == NULL) + g_ThreadInfo[index] = tip->next; + else + prevt->next = tip->next; + + free(tip); + tip=NULL; + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tinfoSem); + #else + SignalLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + + return TRUE; + } + prevt = tip; + } + + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tinfoSem); + #else + SignalLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + + return FALSE; // entry not found +} + + +/*============================================================================================ + + Function : fnGetThreadInfo + + Description : Returns the thread info for the given thread ID or NULL if not successful. + + Parameters : tid (IN) - ID of the thread. + + Returns : Pointer to the ThreadInfo Structure. + +==============================================================================================*/ + +ThreadInfo* fnGetThreadInfo(int tid) +{ + ThreadInfo* tip; + int index = INDEXOF(tid); // just take the bottom five bits + + if (g_tinfoSem) { + #ifdef MPK_ON + kSemaphoreWait(g_tinfoSem); + #else + WaitOnLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + + // see if this is already in the table at the index'th offset + // + for (tip = g_ThreadInfo[index]; tip != NULL; tip = tip->next) + { + if (tip->tid == tid) + { + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tinfoSem); + #else + SignalLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + return tip; + } + } + + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tinfoSem); + #else + SignalLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + + return NULL; +} + +BOOL fnInsertHashListAddrs(void *addrs, BOOL dontTouchHashList) +{ + ThreadInfo* tip; + int index,tid; + + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreWait(g_tinfoSem); + #else + WaitOnLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + + #ifdef MPK_ON + tid=index = abs(kCurrentThread()); + #else + tid=index = GetThreadID(); + #endif //MPK_ON + + index = INDEXOF(index); // just take the bottom five bits + + // see if this is already in the table at the index'th offset + // + for (tip = g_ThreadInfo[index]; tip != NULL; tip = tip->next) + { + if (tip->tid == tid) + { + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tinfoSem); + #else + SignalLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + tip->m_allocList = addrs; + tip->m_dontTouchHashLists = dontTouchHashList; + return TRUE; + } + } + + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tinfoSem); + #else + SignalLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + + return FALSE; +} + +BOOL fnGetHashListAddrs(void **addrs, BOOL *dontTouchHashList) +{ + ThreadInfo* tip; + int index,tid; + + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreWait(g_tinfoSem); + #else + WaitOnLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + + #ifdef MPK_ON + tid=index = abs(kCurrentThread()); + #else + tid=index = GetThreadID(); + #endif //MPK_ON + + index = INDEXOF(index); // just take the bottom five bits + + // see if this is already in the table at the index'th offset + // + for (tip = g_ThreadInfo[index]; tip != NULL; tip = tip->next) + { + if (tip->tid == tid) + { + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tinfoSem); + #else + SignalLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + *addrs = tip->m_allocList; + *dontTouchHashList = tip->m_dontTouchHashLists; + return TRUE; + } + } + + if (g_tinfoSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tinfoSem); + #else + SignalLocalSemaphore(g_tinfoSem); + #endif //MPK_ON + } + + return FALSE; +} + + +/*============================================================================================ + + Function : fnInitializeThreadCtx + + Description : Initialises the thread context. + + Parameters : None. + + Returns : Nothing. + +==============================================================================================*/ + +long fnInitializeThreadCtx(void) +{ + int index = 0; + //long tid; + + if (!g_tCtxSem) { + #ifdef MPK_ON + g_tCtxSem = kSemaphoreAlloc((BYTE *)"threadCtx", 1); + #else + g_tCtxSem = OpenLocalSemaphore(1); + #endif //MPK_ON + + g_ThreadCtx =NULL; + } + + return 0l; +} + + +/*============================================================================================ + + Function : fnAddThreadCtx + + Description : Add a new thread context. + + Parameters : lTLSIndex (IN) - Index + t (IN) - void pointer. + + Returns : Pointer to ThreadContext structure. + +==============================================================================================*/ + +ThreadContext* fnAddThreadCtx(long lTLSIndex, void *t) +{ + ThreadContext* tip = NULL; + ThreadContext* temp = NULL; + + if (g_tCtxSem) + { + #ifdef MPK_ON + kSemaphoreWait(g_tCtxSem); + #else + WaitOnLocalSemaphore(g_tCtxSem); + #endif //MPK_ON + } + + // add a new one to the beginning of the list + // + tip = (ThreadContext *) malloc(sizeof(ThreadContext)); + if (tip == NULL) + { + if (g_tCtxSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tCtxSem); + #else + SignalLocalSemaphore(g_tCtxSem); + #endif //MPK_ON + } + return NULL; + } + + #ifdef MPK_ON + lTLSIndex = labs(kCurrentThread()); + #else + lTLSIndex = GetThreadID(); + #endif //MPK_ON + + tip->next = NULL; + tip->tid = lTLSIndex; + tip->tInfo = t; + + if(g_ThreadCtx==NULL) { + g_ThreadCtx = tip; + } else { + int count=0; + //Traverse to the end + temp = g_ThreadCtx; + while(temp->next != NULL) + { + temp = temp->next; + count++; + } + temp->next = tip; + } + + if (g_tCtxSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tCtxSem); + #else + SignalLocalSemaphore(g_tCtxSem); + #endif //MPK_ON + } + return tip; +} + + +/*============================================================================================ + + Function : fnRemoveThreadCtx + + Description : Removes a thread context. + + Parameters : lTLSIndex (IN) - Index + + Returns : Boolean. + +==============================================================================================*/ + +BOOL fnRemoveThreadCtx(long lTLSIndex) +{ + ThreadContext* tip = NULL; + ThreadContext* prevt = NULL; + + if (g_tCtxSem) + { + #ifdef MPK_ON + kSemaphoreWait(g_tCtxSem); + #else + WaitOnLocalSemaphore(g_tCtxSem); + #endif //MPK_ON + } + + #ifdef MPK_ON + lTLSIndex = labs(kCurrentThread()); + #else + lTLSIndex = GetThreadID(); + #endif //MPK_ON + + tip = g_ThreadCtx; + while(tip) { + if (tip->tid == lTLSIndex) { + if (prevt == NULL) + g_ThreadCtx = tip->next; + else + prevt->next = tip->next; + + free(tip); + tip=NULL; + if (g_tCtxSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tCtxSem); + #else + SignalLocalSemaphore(g_tCtxSem); + #endif //MPK_ON + } + return TRUE; + } + prevt = tip; + tip = tip->next; + } + + if (g_tCtxSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tCtxSem); + #else + SignalLocalSemaphore(g_tCtxSem); + #endif //MPK_ON + } + + return FALSE; // entry not found +} + + +/*============================================================================================ + + Function : fnGetThreadCtx + + Description : Get a thread context. + + Parameters : lTLSIndex (IN) - Index + + Returns : Nothing. + +==============================================================================================*/ + +void* fnGetThreadCtx(long lTLSIndex) +{ + ThreadContext* tip; + + if (g_tCtxSem) + { + #ifdef MPK_ON + kSemaphoreWait(g_tCtxSem); + #else + WaitOnLocalSemaphore(g_tCtxSem); + #endif //MPK_ON + } + + #ifdef MPK_ON + lTLSIndex = labs(kCurrentThread()); + #else + lTLSIndex = GetThreadID(); + #endif //MPK_ON + + tip = g_ThreadCtx; + while(tip) { + if (tip->tid == lTLSIndex) { + if (g_tCtxSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tCtxSem); + #else + SignalLocalSemaphore(g_tCtxSem); + #endif //MPK_ON + } + return (tip->tInfo); + } + tip=tip->next; + } + + if (g_tCtxSem) + { + #ifdef MPK_ON + kSemaphoreSignal(g_tCtxSem); + #else + SignalLocalSemaphore(g_tCtxSem); + #endif //MPK_ON + } + + return NULL; +} + |