summaryrefslogtreecommitdiff
path: root/NetWare/NWTInfo.c
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>2001-06-16 19:46:38 +0000
committerJarkko Hietaniemi <jhi@iki.fi>2001-06-16 19:46:38 +0000
commit2986a63f7e513cf37f46db9f211b77071260031f (patch)
tree9a6e62602396938ea5a612420f53ebf267e8d941 /NetWare/NWTInfo.c
parent87b11a197a59fac210fc9265bde0ef1ffe36de89 (diff)
downloadperl-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.c720
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;
+}
+