source: trunk/essentials/dev-lang/perl/NetWare/NWTInfo.c@ 3299

Last change on this file since 3299 was 3181, checked in by bird, 19 years ago

perl 5.8.8

File size: 13.7 KB
Line 
1
2/*
3 * Copyright © 2001 Novell, Inc. All Rights Reserved.
4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
8 */
9
10/*
11 * FILENAME : NWTInfo.c
12 * DESCRIPTION : Thread-local storage for Perl.
13 * The thread's information is stored in a hashed table that is based on
14 * the lowest 5 bits of the current thread ID.
15 * Author : SGP, HYAK
16 * Date : January 2001.
17 *
18 */
19
20
21
22#include "win32ish.h" // For "BOOL", "TRUE" and "FALSE"
23#include "nwtinfo.h"
24
25#ifdef MPK_ON
26 #include <mpktypes.h>
27 #include <mpkapis.h>
28#else
29 #include <nwsemaph.h>
30#endif //MPK_ON
31
32// Number of entries in the hashtable
33//
34#define NUM_ENTRIES 32 /* 2^5 */
35
36
37// macro to calculate the hash index for a given Thread ID
38//
39#define INDEXOF(tid) ((tid) & 0x1f)
40
41
42// Semaphore to control access to global linked list
43//
44#ifdef MPK_ON
45 static SEMAPHORE g_tinfoSem = NULL;
46 static SEMAPHORE g_tCtxSem = NULL;
47#else
48 static LONG g_tinfoSem = 0L;
49 static LONG g_tCtxSem = 0L;
50#endif //MPK_ON
51
52// Hash table of thread information structures
53//
54ThreadInfo* g_ThreadInfo[NUM_ENTRIES];
55ThreadContext* g_ThreadCtx;
56
57
58
59/*============================================================================================
60
61 Function : fnTerminateThreadInfo
62
63 Description : This function undoes fnInitializeThreadInfo; call once per NLM instance.
64
65 Parameters : None.
66
67 Returns : Boolean.
68
69==============================================================================================*/
70
71BOOL fnTerminateThreadInfo(void)
72{
73 int index = 0;
74
75 if (g_tinfoSem)
76 {
77 #ifdef MPK_ON
78 kSemaphoreWait(g_tinfoSem);
79 #else
80 WaitOnLocalSemaphore(g_tinfoSem);
81 #endif //MPK_ON
82 for (index = 0; index < NUM_ENTRIES; index++)
83 {
84 if (g_ThreadInfo[index] != NULL)
85 {
86 #ifdef MPK_ON
87 kSemaphoreSignal(g_tinfoSem);
88 #else
89 SignalLocalSemaphore(g_tinfoSem);
90 #endif //MPK_ON
91 return FALSE;
92 }
93 }
94 #ifdef MPK_ON
95 kSemaphoreFree(g_tinfoSem);
96 g_tinfoSem = NULL;
97 #else
98 CloseLocalSemaphore(g_tinfoSem);
99 g_tinfoSem = 0;
100 #endif //MPK_ON
101 }
102
103 return TRUE;
104}
105
106
107/*============================================================================================
108
109 Function : fnInitializeThreadInfo
110
111 Description : Initializes the global ThreadInfo hashtable and semaphore.
112 Call once per NLM instance
113
114 Parameters : None.
115
116 Returns : Nothing.
117
118==============================================================================================*/
119
120void fnInitializeThreadInfo(void)
121{
122 int index = 0;
123
124 if (g_tinfoSem)
125 return;
126
127 #ifdef MPK_ON
128 g_tinfoSem = kSemaphoreAlloc((BYTE *)"threadInfo", 1);
129 #else
130 g_tinfoSem = OpenLocalSemaphore(1);
131 #endif //MPK_ON
132
133
134 for (index = 0; index < NUM_ENTRIES; index++)
135 g_ThreadInfo[index] = NULL;
136
137 return;
138}
139
140
141/*============================================================================================
142
143 Function : fnRegisterWithThreadTable
144
145 Description : This function registers/adds a new thread with the thread table.
146
147 Parameters : None.
148
149 Returns : Boolean.
150
151==============================================================================================*/
152
153BOOL fnRegisterWithThreadTable(void)
154{
155 ThreadInfo* tinfo = NULL;
156
157 #ifdef MPK_ON
158 tinfo = fnAddThreadInfo(labs((int)kCurrentThread()));
159 #else
160 tinfo = fnAddThreadInfo(GetThreadID());
161 #endif //MPK_ON
162
163 if (!tinfo)
164 return FALSE;
165 else
166 return TRUE;
167}
168
169
170/*============================================================================================
171
172 Function : fnUnregisterWithThreadTable
173
174 Description : This function unregisters/removes a thread from the thread table.
175
176 Parameters : None.
177
178 Returns : Boolean.
179
180==============================================================================================*/
181
182BOOL fnUnregisterWithThreadTable(void)
183{
184 #ifdef MPK_ON
185 return fnRemoveThreadInfo(labs((int)kCurrentThread()));
186 #else
187 return fnRemoveThreadInfo(GetThreadID());
188 #endif //MPK_ON
189}
190
191
192/*============================================================================================
193
194 Function : fnAddThreadInfo
195
196 Description : Adds a new ThreadInfo for the requested thread.
197
198 Parameters : tid (IN) - ID of the thread.
199
200 Returns : Pointer to the ThreadInfo Structure.
201
202==============================================================================================*/
203
204ThreadInfo* fnAddThreadInfo(int tid)
205{
206 ThreadInfo* tip = NULL;
207 int index = 0;
208
209 if (g_tinfoSem)
210 {
211 #ifdef MPK_ON
212 kSemaphoreWait(g_tinfoSem);
213 #else
214 WaitOnLocalSemaphore(g_tinfoSem);
215 #endif //MPK_ON
216 }
217
218 // Add a new one to the beginning of the hash entry
219 //
220 tip = (ThreadInfo *) malloc(sizeof(ThreadInfo));
221 if (tip == NULL)
222 {
223 if (g_tinfoSem)
224 {
225 #ifdef MPK_ON
226 kSemaphoreSignal(g_tinfoSem);
227 #else
228 SignalLocalSemaphore(g_tinfoSem);
229 #endif //MPK_ON
230 }
231 return NULL;
232 }
233 index = INDEXOF(tid); // just take the bottom five bits
234 tip->next = g_ThreadInfo[index];
235 tip->tid = tid;
236 tip->m_dontTouchHashLists = FALSE;
237 tip->m_allocList = NULL;
238
239 g_ThreadInfo [index] = tip;
240 if (g_tinfoSem)
241 {
242 #ifdef MPK_ON
243 kSemaphoreSignal(g_tinfoSem);
244 #else
245 SignalLocalSemaphore(g_tinfoSem);
246 #endif //MPK_ON
247 }
248
249 return tip;
250}
251
252
253/*============================================================================================
254
255 Function : fnRemoveThreadInfo
256
257 Description : Frees the specified thread info structure and removes it from the
258 global linked list.
259
260 Parameters : tid (IN) - ID of the thread.
261
262 Returns : Boolean.
263
264==============================================================================================*/
265
266BOOL fnRemoveThreadInfo(int tid)
267{
268 ThreadInfo* tip = NULL;
269 ThreadInfo* prevt = NULL;
270 int index = INDEXOF(tid); // just take the bottom five bits
271
272 if (g_tinfoSem)
273 {
274 #ifdef MPK_ON
275 kSemaphoreWait(g_tinfoSem);
276 #else
277 WaitOnLocalSemaphore(g_tinfoSem);
278 #endif //MPK_ON
279 }
280
281 for (tip = g_ThreadInfo[index]; tip != NULL; tip = tip->next)
282 {
283 if (tip->tid == tid)
284 {
285 if (prevt == NULL)
286 g_ThreadInfo[index] = tip->next;
287 else
288 prevt->next = tip->next;
289
290 free(tip);
291 tip=NULL;
292 if (g_tinfoSem)
293 {
294 #ifdef MPK_ON
295 kSemaphoreSignal(g_tinfoSem);
296 #else
297 SignalLocalSemaphore(g_tinfoSem);
298 #endif //MPK_ON
299 }
300
301 return TRUE;
302 }
303 prevt = tip;
304 }
305
306 if (g_tinfoSem)
307 {
308 #ifdef MPK_ON
309 kSemaphoreSignal(g_tinfoSem);
310 #else
311 SignalLocalSemaphore(g_tinfoSem);
312 #endif //MPK_ON
313 }
314
315 return FALSE; // entry not found
316}
317
318
319/*============================================================================================
320
321 Function : fnGetThreadInfo
322
323 Description : Returns the thread info for the given thread ID or NULL if not successful.
324
325 Parameters : tid (IN) - ID of the thread.
326
327 Returns : Pointer to the ThreadInfo Structure.
328
329==============================================================================================*/
330
331ThreadInfo* fnGetThreadInfo(int tid)
332{
333 ThreadInfo* tip;
334 int index = INDEXOF(tid); // just take the bottom five bits
335
336 if (g_tinfoSem) {
337 #ifdef MPK_ON
338 kSemaphoreWait(g_tinfoSem);
339 #else
340 WaitOnLocalSemaphore(g_tinfoSem);
341 #endif //MPK_ON
342 }
343
344 // see if this is already in the table at the index'th offset
345 //
346 for (tip = g_ThreadInfo[index]; tip != NULL; tip = tip->next)
347 {
348 if (tip->tid == tid)
349 {
350 if (g_tinfoSem)
351 {
352 #ifdef MPK_ON
353 kSemaphoreSignal(g_tinfoSem);
354 #else
355 SignalLocalSemaphore(g_tinfoSem);
356 #endif //MPK_ON
357 }
358 return tip;
359 }
360 }
361
362 if (g_tinfoSem)
363 {