Commit | Line | Data |
---|---|---|
2986a63f JH |
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 | // | |
54 | ThreadInfo* g_ThreadInfo[NUM_ENTRIES]; | |
55 | ThreadContext* 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 | ||
71 | BOOL 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 | ||
120 | void 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 | ||
153 | BOOL 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 | ||
182 | BOOL 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 | ||
204 | ThreadInfo* 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 | ||
266 | BOOL 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 | ||
331 | ThreadInfo* 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 | ||
374 | BOOL 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 | ||
428 | BOOL 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 | ||
495 | long 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 | ||
527 | ThreadContext* 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 | ||
605 | BOOL 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 | ||
674 | void* 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 |