Commit | Line | Data |
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 | // |
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 | |