Regenerate META.yml
[p5sagit/p5-mst-13.2.git] / NetWare / NWTInfo.c
CommitLineData
2986a63f 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 {
364 #ifdef MPK_ON
365 kSemaphoreSignal(g_tinfoSem);
366 #else
367 SignalLocalSemaphore(g_tinfoSem);
368 #endif //MPK_ON
369 }
370
371 return NULL;
372}
373
374BOOL fnInsertHashListAddrs(void *addrs, BOOL dontTouchHashList)
375{
376 ThreadInfo* tip;
377 int index,tid;
378
379 if (g_tinfoSem)
380 {
381 #ifdef MPK_ON
382 kSemaphoreWait(g_tinfoSem);
383 #else
384 WaitOnLocalSemaphore(g_tinfoSem);
385 #endif //MPK_ON
386 }
387
388 #ifdef MPK_ON
389 tid=index = abs(kCurrentThread());
390 #else
391 tid=index = GetThreadID();
392 #endif //MPK_ON
393
394 index = INDEXOF(index); // just take the bottom five bits
395
396 // see if this is already in the table at the index'th offset
397 //
398 for (tip = g_ThreadInfo[index]; tip != NULL; tip = tip->next)
399 {
400 if (tip->tid == tid)
401 {
402 if (g_tinfoSem)
403 {
404 #ifdef MPK_ON
405 kSemaphoreSignal(g_tinfoSem);
406 #else
407 SignalLocalSemaphore(g_tinfoSem);
408 #endif //MPK_ON
409 }
410 tip->m_allocList = addrs;
411 tip->m_dontTouchHashLists = dontTouchHashList;
412 return TRUE;
413 }
414 }
415
416 if (g_tinfoSem)
417 {
418 #ifdef MPK_ON
419 kSemaphoreSignal(g_tinfoSem);
420 #else
421 SignalLocalSemaphore(g_tinfoSem);
422 #endif //MPK_ON
423 }
424
425 return FALSE;
426}
427
428BOOL fnGetHashListAddrs(void **addrs, BOOL *dontTouchHashList)
429{
430 ThreadInfo* tip;
431 int index,tid;
432
433 if (g_tinfoSem)
434 {
435 #ifdef MPK_ON
436 kSemaphoreWait(g_tinfoSem);
437 #else
438 WaitOnLocalSemaphore(g_tinfoSem);
439 #endif //MPK_ON
440 }
441
442 #ifdef MPK_ON
443 tid=index = abs(kCurrentThread());
444 #else
445 tid=index = GetThreadID();
446 #endif //MPK_ON
447
448 index = INDEXOF(index); // just take the bottom five bits
449
450 // see if this is already in the table at the index'th offset
451 //
452 for (tip = g_ThreadInfo[index]; tip != NULL; tip = tip->next)
453 {
454 if (tip->tid == tid)
455 {
456 if (g_tinfoSem)
457 {
458 #ifdef MPK_ON
459 kSemaphoreSignal(g_tinfoSem);
460 #else
461 SignalLocalSemaphore(g_tinfoSem);
462 #endif //MPK_ON
463 }
464 *addrs = tip->m_allocList;
465 *dontTouchHashList = tip->m_dontTouchHashLists;
466 return TRUE;
467 }
468 }
469
470 if (g_tinfoSem)
471 {
472 #ifdef MPK_ON
473 kSemaphoreSignal(g_tinfoSem);
474 #else
475 SignalLocalSemaphore(g_tinfoSem);
476 #endif //MPK_ON
477 }
478
479 return FALSE;
480}
481
482
483/*============================================================================================
484
485 Function : fnInitializeThreadCtx
486
487 Description : Initialises the thread context.
488
489 Parameters : None.
490
491 Returns : Nothing.
492
493==============================================================================================*/
494
495long fnInitializeThreadCtx(void)
496{
497 int index = 0;
498 //long tid;
499
500 if (!g_tCtxSem) {
501 #ifdef MPK_ON
502 g_tCtxSem = kSemaphoreAlloc((BYTE *)"threadCtx", 1);
503 #else
504 g_tCtxSem = OpenLocalSemaphore(1);
505 #endif //MPK_ON
506
507 g_ThreadCtx =NULL;
508 }
509
510 return 0l;
511}
512
513
514/*============================================================================================
515
516 Function : fnAddThreadCtx
517
518 Description : Add a new thread context.
519
520 Parameters : lTLSIndex (IN) - Index
521 t (IN) - void pointer.
522
523 Returns : Pointer to ThreadContext structure.
524
525==============================================================================================*/
526
527ThreadContext* fnAddThreadCtx(long lTLSIndex, void *t)
528{
529 ThreadContext* tip = NULL;
530 ThreadContext* temp = NULL;
531
532 if (g_tCtxSem)
533 {
534 #ifdef MPK_ON
535 kSemaphoreWait(g_tCtxSem);
536 #else
537 WaitOnLocalSemaphore(g_tCtxSem);
538 #endif //MPK_ON
539 }
540
541 // add a new one to the beginning of the list
542 //
543 tip = (ThreadContext *) malloc(sizeof(ThreadContext));
544 if (tip == NULL)
545 {
546 if (g_tCtxSem)
547 {
548 #ifdef MPK_ON
549 kSemaphoreSignal(g_tCtxSem);
550 #else
551 SignalLocalSemaphore(g_tCtxSem);
552 #endif //MPK_ON
553 }
554 return NULL;
555 }
556
557 #ifdef MPK_ON
558 lTLSIndex = labs(kCurrentThread());
559 #else
560 lTLSIndex = GetThreadID();
561 #endif //MPK_ON
562
563 tip->next = NULL;
564 tip->tid = lTLSIndex;
565 tip->tInfo = t;
566
567 if(g_ThreadCtx==NULL) {
568 g_ThreadCtx = tip;
569 } else {
570 int count=0;
571 //Traverse to the end
572 temp = g_ThreadCtx;
573 while(temp->next != NULL)
574 {
575 temp = temp->next;
576 count++;
577 }
578 temp->next = tip;
579 }
580
581 if (g_tCtxSem)
582 {
583 #ifdef MPK_ON
584 kSemaphoreSignal(g_tCtxSem);
585 #else
586 SignalLocalSemaphore(g_tCtxSem);
587 #endif //MPK_ON
588 }
589 return tip;
590}
591
592
593/*============================================================================================
594
595 Function : fnRemoveThreadCtx
596
597 Description : Removes a thread context.
598
599 Parameters : lTLSIndex (IN) - Index
600
601 Returns : Boolean.
602
603==============================================================================================*/
604
605BOOL fnRemoveThreadCtx(long lTLSIndex)
606{
607 ThreadContext* tip = NULL;
608 ThreadContext* prevt = NULL;
609
610 if (g_tCtxSem)
611 {
612 #ifdef MPK_ON
613 kSemaphoreWait(g_tCtxSem);
614 #else
615 WaitOnLocalSemaphore(g_tCtxSem);
616 #endif //MPK_ON
617 }
618
619 #ifdef MPK_ON
620 lTLSIndex = labs(kCurrentThread());
621 #else
622 lTLSIndex = GetThreadID();
623 #endif //MPK_ON
624
625 tip = g_ThreadCtx;
626 while(tip) {
627 if (tip->tid == lTLSIndex) {
628 if (prevt == NULL)
629 g_ThreadCtx = tip->next;
630 else
631 prevt->next = tip->next;
632
633 free(tip);
634 tip=NULL;
635 if (g_tCtxSem)
636 {
637 #ifdef MPK_ON
638 kSemaphoreSignal(g_tCtxSem);
639 #else
640 SignalLocalSemaphore(g_tCtxSem);
641 #endif //MPK_ON
642 }
643 return TRUE;
644 }
645 prevt = tip;
646 tip = tip->next;
647 }
648
649 if (g_tCtxSem)
650 {
651 #ifdef MPK_ON
652 kSemaphoreSignal(g_tCtxSem);
653 #else
654 SignalLocalSemaphore(g_tCtxSem);
655 #endif //MPK_ON
656 }
657
658 return FALSE; // entry not found
659}
660
661
662/*============================================================================================
663
664 Function : fnGetThreadCtx
665
666 Description : Get a thread context.
667
668 Parameters : lTLSIndex (IN) - Index
669
670 Returns : Nothing.
671
672==============================================================================================*/
673
674void* fnGetThreadCtx(long lTLSIndex)
675{
676 ThreadContext* tip;
677
678 if (g_tCtxSem)
679 {
680 #ifdef MPK_ON
681 kSemaphoreWait(g_tCtxSem);
682 #else
683 WaitOnLocalSemaphore(g_tCtxSem);
684 #endif //MPK_ON
685 }
686
687 #ifdef MPK_ON
688 lTLSIndex = labs(kCurrentThread());
689 #else
690 lTLSIndex = GetThreadID();
691 #endif //MPK_ON
692
693 tip = g_ThreadCtx;
694 while(tip) {
695 if (tip->tid == lTLSIndex) {
696 if (g_tCtxSem)
697 {
698 #ifdef MPK_ON
699 kSemaphoreSignal(g_tCtxSem);
700 #else
701 SignalLocalSemaphore(g_tCtxSem);
702 #endif //MPK_ON
703 }
704 return (tip->tInfo);
705 }
706 tip=tip->next;
707 }
708
709 if (g_tCtxSem)
710 {
711 #ifdef MPK_ON
712 kSemaphoreSignal(g_tCtxSem);
713 #else
714 SignalLocalSemaphore(g_tCtxSem);
715 #endif //MPK_ON
716 }
717
718 return NULL;
719}
720