Blame


1 cea10000 2005-05-01 devnull #include "threadimpl.h"
2 cea10000 2005-05-01 devnull #include "BSD.c"
3 cea10000 2005-05-01 devnull
4 b20b42b8 2005-08-10 devnull #include <dlfcn.h>
5 fe8c925e 2005-07-21 devnull
6 b20b42b8 2005-08-10 devnull #define MIN(a,b) ((a) < (b) ? (a) : (b))
7 b20b42b8 2005-08-10 devnull #define MAX(a,b) ((a) > (b) ? (a) : (b))
8 b20b42b8 2005-08-10 devnull
9 b20b42b8 2005-08-10 devnull enum {
10 b20b42b8 2005-08-10 devnull FD_READ = 1,
11 b20b42b8 2005-08-10 devnull FD_WRITE,
12 b20b42b8 2005-08-10 devnull FD_RDWR,
13 b20b42b8 2005-08-10 devnull FDTBL_MAXSIZE = 128
14 b20b42b8 2005-08-10 devnull };
15 b20b42b8 2005-08-10 devnull
16 b20b42b8 2005-08-10 devnull struct fd_entry {
17 b20b42b8 2005-08-10 devnull QLock lock;
18 b20b42b8 2005-08-10 devnull int fd;
19 b20b42b8 2005-08-10 devnull int id;
20 b20b42b8 2005-08-10 devnull short rc;
21 b20b42b8 2005-08-10 devnull short wc;
22 b20b42b8 2005-08-10 devnull short ref;
23 b20b42b8 2005-08-10 devnull };
24 b20b42b8 2005-08-10 devnull
25 b20b42b8 2005-08-10 devnull static struct fd_entry fd_entry1 = { .fd -1 };
26 b20b42b8 2005-08-10 devnull static struct fd_entry *fd_table = nil;
27 b20b42b8 2005-08-10 devnull static spinlock_t fd_table_lock = { 0, 0, nil, 0 };
28 b20b42b8 2005-08-10 devnull static spinlock_t mlock = { 0, 0, nil, 0 };
29 b20b42b8 2005-08-10 devnull static spinlock_t dl_lock = { 0, 0, nil, 0 };
30 b20b42b8 2005-08-10 devnull
31 fe8c925e 2005-07-21 devnull void
32 fe8c925e 2005-07-21 devnull _thread_malloc_lock(void)
33 fe8c925e 2005-07-21 devnull {
34 fe8c925e 2005-07-21 devnull _spinlock(&mlock);
35 fe8c925e 2005-07-21 devnull }
36 fe8c925e 2005-07-21 devnull
37 fe8c925e 2005-07-21 devnull void
38 fe8c925e 2005-07-21 devnull _thread_malloc_unlock(void)
39 fe8c925e 2005-07-21 devnull {
40 fe8c925e 2005-07-21 devnull _spinunlock(&mlock);
41 fe8c925e 2005-07-21 devnull }
42 fe8c925e 2005-07-21 devnull
43 fe8c925e 2005-07-21 devnull void
44 fe8c925e 2005-07-21 devnull _thread_malloc_init(void)
45 fe8c925e 2005-07-21 devnull {
46 fe8c925e 2005-07-21 devnull }
47 b20b42b8 2005-08-10 devnull
48 b20b42b8 2005-08-10 devnull /*
49 b20b42b8 2005-08-10 devnull * Must set errno on failure because the return value
50 b20b42b8 2005-08-10 devnull * of _thread_fd_entry is propagated back to the caller
51 b20b42b8 2005-08-10 devnull * of the thread-wrapped libc function.
52 b20b42b8 2005-08-10 devnull */
53 b20b42b8 2005-08-10 devnull static struct fd_entry *
54 b20b42b8 2005-08-10 devnull _thread_fd_lookup(int fd)
55 b20b42b8 2005-08-10 devnull {
56 b20b42b8 2005-08-10 devnull struct fd_entry *t;
57 b20b42b8 2005-08-10 devnull static int cursize;
58 b20b42b8 2005-08-10 devnull int newsize;
59 b20b42b8 2005-08-10 devnull
60 b20b42b8 2005-08-10 devnull if(fd >= FDTBL_MAXSIZE) {
61 b20b42b8 2005-08-10 devnull errno = EBADF;
62 b20b42b8 2005-08-10 devnull return nil;
63 b20b42b8 2005-08-10 devnull }
64 b20b42b8 2005-08-10 devnull
65 b20b42b8 2005-08-10 devnull /*
66 b20b42b8 2005-08-10 devnull * There are currently only a few libc functions using
67 b20b42b8 2005-08-10 devnull * _thread_fd_*, which are rarely called by P9P programs.
68 b20b42b8 2005-08-10 devnull * So the contention for these locks is very small and so
69 b20b42b8 2005-08-10 devnull * far have usually been limited to a single fd. So
70 b20b42b8 2005-08-10 devnull * rather than malloc the fd_table everytime we just use
71 b20b42b8 2005-08-10 devnull * a single fd_entry until a lock request for another fd
72 b20b42b8 2005-08-10 devnull * comes in.
73 b20b42b8 2005-08-10 devnull */
74 b20b42b8 2005-08-10 devnull if(fd_table == nil)
75 b20b42b8 2005-08-10 devnull if(fd_entry1.fd == -1) {
76 b20b42b8 2005-08-10 devnull fd_entry1.fd = fd;
77 b20b42b8 2005-08-10 devnull return &fd_entry1;
78 b20b42b8 2005-08-10 devnull } else if(fd_entry1.fd == fd)
79 b20b42b8 2005-08-10 devnull return &fd_entry1;
80 b20b42b8 2005-08-10 devnull else {
81 b20b42b8 2005-08-10 devnull cursize = MAX(fd_entry1.fd, 16);
82 b20b42b8 2005-08-10 devnull fd_table = malloc(cursize*sizeof(fd_table[0]));
83 b20b42b8 2005-08-10 devnull if(fd_table == nil) {
84 b20b42b8 2005-08-10 devnull errno = ENOMEM;
85 b20b42b8 2005-08-10 devnull return nil;
86 b20b42b8 2005-08-10 devnull }
87 b20b42b8 2005-08-10 devnull memset(fd_table, 0, cursize*sizeof(fd_table[0]));
88 b20b42b8 2005-08-10 devnull fd_table[fd_entry1.fd] = fd_entry1;
89 b20b42b8 2005-08-10 devnull }
90 b20b42b8 2005-08-10 devnull if(fd > cursize) {
91 b20b42b8 2005-08-10 devnull newsize = MIN(cursize*2, FDTBL_MAXSIZE);
92 b20b42b8 2005-08-10 devnull t = realloc(fd_table, newsize*sizeof(fd_table[0]));
93 b20b42b8 2005-08-10 devnull if(t == nil) {
94 b20b42b8 2005-08-10 devnull errno = ENOMEM;
95 b20b42b8 2005-08-10 devnull return nil;
96 b20b42b8 2005-08-10 devnull }
97 b20b42b8 2005-08-10 devnull fd_table = t;
98 b20b42b8 2005-08-10 devnull cursize = newsize;
99 b20b42b8 2005-08-10 devnull memset(fd_table, 0, cursize*sizeof(fd_table[0]));
100 b20b42b8 2005-08-10 devnull }
101 b20b42b8 2005-08-10 devnull
102 b20b42b8 2005-08-10 devnull return &fd_table[fd];
103 b20b42b8 2005-08-10 devnull }
104 b20b42b8 2005-08-10 devnull
105 b20b42b8 2005-08-10 devnull /*
106 b20b42b8 2005-08-10 devnull * Mutiple readers just share the lock by incrementing the read count.
107 b20b42b8 2005-08-10 devnull * Writers must obtain an exclusive lock.
108 b20b42b8 2005-08-10 devnull */
109 b20b42b8 2005-08-10 devnull int
110 b20b42b8 2005-08-10 devnull _thread_fd_lock(int fd, int type, struct timespec *time)
111 b20b42b8 2005-08-10 devnull {
112 b20b42b8 2005-08-10 devnull struct fd_entry *fde;
113 b20b42b8 2005-08-10 devnull int id;
114 b20b42b8 2005-08-10 devnull
115 b20b42b8 2005-08-10 devnull _spinlock(&fd_table_lock);
116 b20b42b8 2005-08-10 devnull fde = _thread_fd_lookup(fd);
117 b20b42b8 2005-08-10 devnull if(fde == nil)
118 b20b42b8 2005-08-10 devnull return -1;
119 b20b42b8 2005-08-10 devnull
120 b20b42b8 2005-08-10 devnull if(type == FD_READ) {
121 b20b42b8 2005-08-10 devnull if(fde->rc++ >= 1 && fde->wc == 0) {
122 b20b42b8 2005-08-10 devnull _spinunlock(&fd_table_lock);
123 b20b42b8 2005-08-10 devnull return 0;
124 b20b42b8 2005-08-10 devnull }
125 b20b42b8 2005-08-10 devnull } else
126 b20b42b8 2005-08-10 devnull fde->wc++;
127 b20b42b8 2005-08-10 devnull _spinunlock(&fd_table_lock);
128 b20b42b8 2005-08-10 devnull
129 b20b42b8 2005-08-10 devnull /* handle recursion */
130 b20b42b8 2005-08-10 devnull id = proc()->osprocid;
131 b20b42b8 2005-08-10 devnull if(id == fde->id) {
132 b20b42b8 2005-08-10 devnull fde->ref++;
133 b20b42b8 2005-08-10 devnull return 0;
134 b20b42b8 2005-08-10 devnull }
135 b20b42b8 2005-08-10 devnull
136 b20b42b8 2005-08-10 devnull qlock(&fde->lock);
137 b20b42b8 2005-08-10 devnull fde->id = id;
138 b20b42b8 2005-08-10 devnull return 0;
139 b20b42b8 2005-08-10 devnull }
140 b20b42b8 2005-08-10 devnull
141 b20b42b8 2005-08-10 devnull void
142 b20b42b8 2005-08-10 devnull _thread_fd_unlock(int fd, int type)
143 b20b42b8 2005-08-10 devnull {
144 b20b42b8 2005-08-10 devnull struct fd_entry *fde;
145 b20b42b8 2005-08-10 devnull int id;
146 b20b42b8 2005-08-10 devnull
147 b20b42b8 2005-08-10 devnull fde = _thread_fd_lookup(fd);
148 b20b42b8 2005-08-10 devnull if(fde == nil) {
149 b20b42b8 2005-08-10 devnull fprint(2, "_thread_fd_unlock: fd %d not in table!\n", fd);
150 b20b42b8 2005-08-10 devnull return;
151 b20b42b8 2005-08-10 devnull }
152 b20b42b8 2005-08-10 devnull
153 b20b42b8 2005-08-10 devnull if(type == FD_READ && --fde->rc >= 1)
154 b20b42b8 2005-08-10 devnull return;
155 b20b42b8 2005-08-10 devnull else
156 b20b42b8 2005-08-10 devnull fde->wc--;
157 b20b42b8 2005-08-10 devnull
158 b20b42b8 2005-08-10 devnull id = proc()->osprocid;
159 b20b42b8 2005-08-10 devnull if(id == fde->id && fde->ref > 0) {
160 b20b42b8 2005-08-10 devnull fde->ref--;
161 b20b42b8 2005-08-10 devnull return;
162 b20b42b8 2005-08-10 devnull }
163 b20b42b8 2005-08-10 devnull fde->id = 0;
164 b20b42b8 2005-08-10 devnull qunlock(&fde->lock);
165 b20b42b8 2005-08-10 devnull }
166 b20b42b8 2005-08-10 devnull
167 b20b42b8 2005-08-10 devnull void
168 b20b42b8 2005-08-10 devnull _thread_dl_lock(int t)
169 b20b42b8 2005-08-10 devnull {
170 b20b42b8 2005-08-10 devnull if(t)
171 b20b42b8 2005-08-10 devnull _spinunlock(&dl_lock);
172 b20b42b8 2005-08-10 devnull else
173 b20b42b8 2005-08-10 devnull _spinlock(&dl_lock);
174 b20b42b8 2005-08-10 devnull }
175 b20b42b8 2005-08-10 devnull
176 b20b42b8 2005-08-10 devnull void
177 b20b42b8 2005-08-10 devnull _pthreadinit(void)
178 b20b42b8 2005-08-10 devnull {
179 b20b42b8 2005-08-10 devnull __isthreaded = 1;
180 b20b42b8 2005-08-10 devnull dlctl(nil, DL_SETTHREADLCK, _thread_dl_lock);
181 b20b42b8 2005-08-10 devnull signal(SIGUSR2, sigusr2handler);
182 b20b42b8 2005-08-10 devnull }