Blob


1 #include "threadimpl.h"
2 #include "BSD.c"
4 #include <dlfcn.h>
6 struct thread_tag {
7 struct thread_tag *next;
8 spinlock_t l;
9 volatile int key;
10 void *data;
11 };
13 static spinlock_t mlock;
14 static spinlock_t dl_lock;
15 static spinlock_t tag_lock;
16 static struct thread_tag *thread_tag_store = nil;
17 static uint nextkey = 0;
19 void
20 _thread_malloc_lock(void)
21 {
22 _spinlock(&mlock);
23 }
25 void
26 _thread_malloc_unlock(void)
27 {
28 _spinunlock(&mlock);
29 }
31 void
32 _thread_malloc_init(void)
33 {
34 }
36 /*
37 * for ld.so
38 */
39 void
40 _thread_dl_lock(int t)
41 {
42 if(t)
43 _spinunlock(&dl_lock);
44 else
45 _spinlock(&dl_lock);
46 }
48 /*
49 * for libc
50 */
51 static void
52 _thread_tag_init(void **tag)
53 {
54 struct thread_tag *t;
56 _spinlock(&tag_lock);
57 if(*tag == nil) {
58 t = malloc(sizeof (*t));
59 if(t != nil) {
60 memset(&t->l, 0, sizeof(t->l));
61 t->key = nextkey++;
62 *tag = t;
63 }
64 }
65 _spinunlock(&tag_lock);
66 }
68 void
69 _thread_tag_lock(void **tag)
70 {
71 struct thread_tag *t;
73 if(*tag == nil)
74 _thread_tag_init(tag);
75 t = *tag;
76 _spinlock(&t->l);
77 }
79 void
80 _thread_tag_unlock(void **tag)
81 {
82 struct thread_tag *t;
84 if(*tag == nil)
85 _thread_tag_init(tag);
86 t = *tag;
87 _spinunlock(&t->l);
88 }
90 static void *
91 _thread_tag_insert(struct thread_tag *t, void *v)
92 {
93 t->data = v;
94 t->next = thread_tag_store;
95 thread_tag_store = t;
96 return t;
97 }
99 static void *
100 _thread_tag_lookup(struct thread_tag *tag, int size)
102 struct thread_tag *t;
103 void *p;
105 _spinlock(&tag->l);
106 for(t = thread_tag_store; t != nil; t = t->next)
107 if(t->key == tag->key)
108 break;
109 if(t == nil) {
110 p = malloc(size);
111 if(p == nil) {
112 _spinunlock(&tag->l);
113 return nil;
115 _thread_tag_insert(tag, p);
117 _spinunlock(&tag->l);
118 return tag->data;
121 void *
122 _thread_tag_storage(void **tag, void *storage, size_t n, void *err)
124 struct thread_tag *t;
125 void *r;
127 if(*tag == nil)
128 _thread_tag_init(tag);
129 t = *tag;
131 r = _thread_tag_lookup(t, n);
132 if(r == nil)
133 r = err;
134 else
135 memcpy(r, storage, n);
136 return r;
139 void
140 _pthreadinit(void)
142 __isthreaded = 1;
143 dlctl(nil, DL_SETTHREADLCK, _thread_dl_lock);
144 signal(SIGUSR2, sigusr2handler);