| @@ -1,362 +1,368 @@ | | | @@ -1,362 +1,368 @@ |
1 | /* $NetBSD: callcontext.c,v 1.26 2011/11/02 16:43:04 yamt Exp $ */ | | 1 | /* $NetBSD: callcontext.c,v 1.27 2011/12/06 21:15:39 skrll Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved. | | 4 | * Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved. |
5 | * | | 5 | * |
6 | * Development of this software was supported by the | | 6 | * Development of this software was supported by the |
7 | * Research Foundation of Helsinki University of Technology | | 7 | * Research Foundation of Helsinki University of Technology |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the | | 15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. | | 16 | * documentation and/or other materials provided with the distribution. |
17 | * | | 17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS | | 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
19 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | | 19 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | | 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
21 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | | 21 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | | 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
28 | * SUCH DAMAGE. | | 28 | * SUCH DAMAGE. |
29 | */ | | 29 | */ |
30 | | | 30 | |
31 | #include <sys/cdefs.h> | | 31 | #include <sys/cdefs.h> |
32 | #if !defined(lint) | | 32 | #if !defined(lint) |
33 | __RCSID("$NetBSD: callcontext.c,v 1.26 2011/11/02 16:43:04 yamt Exp $"); | | 33 | __RCSID("$NetBSD: callcontext.c,v 1.27 2011/12/06 21:15:39 skrll Exp $"); |
34 | #endif /* !lint */ | | 34 | #endif /* !lint */ |
35 | | | 35 | |
36 | #include <sys/types.h> | | 36 | #include <sys/types.h> |
37 | #include <sys/mman.h> | | 37 | #include <sys/mman.h> |
38 | | | 38 | |
39 | #include <assert.h> | | 39 | #include <assert.h> |
40 | #include <errno.h> | | 40 | #include <errno.h> |
41 | #include <puffs.h> | | 41 | #include <puffs.h> |
42 | #include <stdio.h> | | 42 | #include <stdio.h> |
43 | #include <stdlib.h> | | 43 | #include <stdlib.h> |
44 | #include <string.h> | | 44 | #include <string.h> |
45 | #include <ucontext.h> | | 45 | #include <ucontext.h> |
46 | #include <unistd.h> | | 46 | #include <unistd.h> |
47 | | | 47 | |
48 | #include "puffs_priv.h" | | 48 | #include "puffs_priv.h" |
49 | | | 49 | |
50 | #if 0 | | 50 | #if 0 |
51 | #define DPRINTF(x) printf x | | 51 | #define DPRINTF(x) printf x |
52 | #else | | 52 | #else |
53 | #define DPRINTF(x) | | 53 | #define DPRINTF(x) |
54 | #endif | | 54 | #endif |
55 | | | 55 | |
56 | /* | | 56 | /* |
57 | * Set the following to 1 to not handle each request on a separate | | 57 | * Set the following to 1 to not handle each request on a separate |
58 | * stack. This is highly volatile kludge, therefore no external | | 58 | * stack. This is highly volatile kludge, therefore no external |
59 | * interface. | | 59 | * interface. |
60 | */ | | 60 | */ |
61 | int puffs_fakecc; | | 61 | int puffs_fakecc; |
62 | | | 62 | |
63 | /* | | 63 | /* |
64 | * user stuff | | 64 | * user stuff |
65 | */ | | 65 | */ |
66 | | | 66 | |
67 | /* | | 67 | /* |
68 | * So, we need to get back to where we came from. This can happen in two | | 68 | * So, we need to get back to where we came from. This can happen in two |
69 | * different ways: | | 69 | * different ways: |
70 | * 1) PCC_MLCONT is set, in which case we need to go to the mainloop | | 70 | * 1) PCC_MLCONT is set, in which case we need to go to the mainloop |
71 | * 2) It is not set, and we simply jump to pcc_uc_ret. | | 71 | * 2) It is not set, and we simply jump to pcc_uc_ret. |
72 | */ | | 72 | */ |
73 | void | | 73 | void |
74 | puffs_cc_yield(struct puffs_cc *pcc) | | 74 | puffs_cc_yield(struct puffs_cc *pcc) |
75 | { | | 75 | { |
76 | struct puffs_cc *jumpcc; | | 76 | struct puffs_cc *jumpcc; |
77 | int rv; | | 77 | int rv; |
78 | | | 78 | |
79 | assert(puffs_fakecc == 0); | | 79 | assert(puffs_fakecc == 0); |
80 | | | 80 | |
81 | if ((~pcc->pcc_flags & (PCC_BORROWED|PCC_DONE)) == 0) { | | 81 | if ((~pcc->pcc_flags & (PCC_BORROWED|PCC_DONE)) == 0) { |
82 | pcc->pcc_flags &= ~(PCC_BORROWED|PCC_DONE); | | 82 | pcc->pcc_flags &= ~(PCC_BORROWED|PCC_DONE); |
83 | /* | | 83 | /* |
84 | * see the XXX comment in puffs__cc_cont | | 84 | * see the XXX comment in puffs__cc_cont |
85 | */ | | 85 | */ |
86 | puffs__cc_destroy(pcc, 1); | | 86 | puffs__cc_destroy(pcc, 1); |
87 | setcontext(&pcc->pcc_uc_ret); | | 87 | setcontext(&pcc->pcc_uc_ret); |
88 | } | | 88 | } |
89 | pcc->pcc_flags &= ~PCC_BORROWED; | | 89 | pcc->pcc_flags &= ~PCC_BORROWED; |
90 | | | 90 | |
91 | /* romanes eunt domus */ | | 91 | /* romanes eunt domus */ |
92 | DPRINTF(("puffs_cc_yield: ")); | | 92 | DPRINTF(("puffs_cc_yield: ")); |
93 | if ((pcc->pcc_flags & PCC_MLCONT) == 0) { | | 93 | if ((pcc->pcc_flags & PCC_MLCONT) == 0) { |
94 | DPRINTF(("no mlcont, pcc %p\n", pcc)); | | 94 | DPRINTF(("no mlcont, pcc %p\n", pcc)); |
95 | swapcontext(&pcc->pcc_uc, &pcc->pcc_uc_ret); | | 95 | swapcontext(&pcc->pcc_uc, &pcc->pcc_uc_ret); |
96 | } else { | | 96 | } else { |
97 | DPRINTF(("mlcont, pcc %p\n", pcc)); | | 97 | DPRINTF(("mlcont, pcc %p\n", pcc)); |
98 | pcc->pcc_flags &= ~PCC_MLCONT; | | 98 | pcc->pcc_flags &= ~PCC_MLCONT; |
99 | rv = puffs__cc_create(pcc->pcc_pu, puffs__theloop, &jumpcc); | | 99 | rv = puffs__cc_create(pcc->pcc_pu, puffs__theloop, &jumpcc); |
100 | if (rv) | | 100 | if (rv) |
101 | abort(); /* p-p-p-pa-pa-panic (XXX: fixme) */ | | 101 | abort(); /* p-p-p-pa-pa-panic (XXX: fixme) */ |
102 | swapcontext(&pcc->pcc_uc, &jumpcc->pcc_uc); | | 102 | swapcontext(&pcc->pcc_uc, &jumpcc->pcc_uc); |
103 | DPRINTF(("puffs_cc_yield: post swap pcc %p\n", pcc)); | | 103 | DPRINTF(("puffs_cc_yield: post swap pcc %p\n", pcc)); |
104 | } | | 104 | } |
105 | } | | 105 | } |
106 | | | 106 | |
107 | /* | | 107 | /* |
108 | * Internal continue routine. This has slightly different semantics. | | 108 | * Internal continue routine. This has slightly different semantics. |
109 | * We simply make our cc available in the freelist and jump to the | | 109 | * We simply make our cc available in the freelist and jump to the |
110 | * indicated pcc. | | 110 | * indicated pcc. |
111 | */ | | 111 | */ |
112 | void | | 112 | void |
113 | puffs__cc_cont(struct puffs_cc *pcc) | | 113 | puffs__cc_cont(struct puffs_cc *pcc) |
114 | { | | 114 | { |
115 | struct puffs_cc *mycc; | | 115 | struct puffs_cc *mycc; |
116 | | | 116 | |
117 | mycc = puffs_cc_getcc(pcc->pcc_pu); | | 117 | mycc = puffs_cc_getcc(pcc->pcc_pu); |
118 | DPRINTF(("puffs__cc_cont: pcc %p, mycc %p\n", pcc, mycc)); | | 118 | DPRINTF(("puffs__cc_cont: pcc %p, mycc %p\n", pcc, mycc)); |
119 | | | 119 | |
120 | /* | | 120 | /* |
121 | * XXX: race between setcontext() and recycle if | | 121 | * XXX: race between setcontext() and recycle if |
122 | * we go multithreaded | | 122 | * we go multithreaded |
123 | */ | | 123 | */ |
124 | puffs__cc_destroy(mycc, 1); | | 124 | puffs__cc_destroy(mycc, 1); |
125 | pcc->pcc_flags |= PCC_MLCONT; | | 125 | pcc->pcc_flags |= PCC_MLCONT; |
126 | setcontext(&pcc->pcc_uc); | | 126 | setcontext(&pcc->pcc_uc); |
127 | } | | 127 | } |
128 | | | 128 | |
129 | void | | 129 | void |
130 | puffs_cc_continue(struct puffs_cc *pcc) | | 130 | puffs_cc_continue(struct puffs_cc *pcc) |
131 | { | | 131 | { |
132 | | | 132 | |
133 | /* ramble on */ | | 133 | /* ramble on */ |
134 | DPRINTF(("puffs_cc_continue: pcc %p\n", pcc)); | | 134 | DPRINTF(("puffs_cc_continue: pcc %p\n", pcc)); |
135 | if (puffs_fakecc) { | | 135 | if (puffs_fakecc) { |
136 | pcc->pcc_func(pcc->pcc_farg); | | 136 | pcc->pcc_func(pcc->pcc_farg); |
137 | } else { | | 137 | } else { |
138 | swapcontext(&pcc->pcc_uc_ret, &pcc->pcc_uc); | | 138 | swapcontext(&pcc->pcc_uc_ret, &pcc->pcc_uc); |
139 | } | | 139 | } |
140 | } | | 140 | } |
141 | | | 141 | |
142 | /* | | 142 | /* |
143 | * "Borrows" pcc, *NOT* called from pcc owner. Acts like continue. | | 143 | * "Borrows" pcc, *NOT* called from pcc owner. Acts like continue. |
144 | * So the idea is to use this, give something the context back to | | 144 | * So the idea is to use this, give something the context back to |
145 | * run to completion and then jump back to where ever this was called | | 145 | * run to completion and then jump back to where ever this was called |
146 | * from after the op dispatching is complete (or if the pcc decides to | | 146 | * from after the op dispatching is complete (or if the pcc decides to |
147 | * yield again). | | 147 | * yield again). |
148 | */ | | 148 | */ |
149 | void | | 149 | void |
150 | puffs__goto(struct puffs_cc *loanpcc) | | 150 | puffs__goto(struct puffs_cc *loanpcc) |
151 | { | | 151 | { |
152 | | | 152 | |
153 | loanpcc->pcc_flags |= PCC_BORROWED; | | 153 | loanpcc->pcc_flags |= PCC_BORROWED; |
154 | | | 154 | |
155 | swapcontext(&loanpcc->pcc_uc_ret, &loanpcc->pcc_uc); | | 155 | swapcontext(&loanpcc->pcc_uc_ret, &loanpcc->pcc_uc); |
156 | } | | 156 | } |
157 | | | 157 | |
158 | void | | 158 | void |
159 | puffs_cc_schedule(struct puffs_cc *pcc) | | 159 | puffs_cc_schedule(struct puffs_cc *pcc) |
160 | { | | 160 | { |
161 | struct puffs_usermount *pu = pcc->pcc_pu; | | 161 | struct puffs_usermount *pu = pcc->pcc_pu; |
162 | | | 162 | |
163 | assert(pu->pu_state & PU_INLOOP); | | 163 | assert(pu->pu_state & PU_INLOOP); |
164 | TAILQ_INSERT_TAIL(&pu->pu_sched, pcc, pcc_schedent); | | 164 | TAILQ_INSERT_TAIL(&pu->pu_sched, pcc, pcc_schedent); |
165 | } | | 165 | } |
166 | | | 166 | |
167 | int | | 167 | int |
168 | puffs_cc_getcaller(struct puffs_cc *pcc, pid_t *pid, lwpid_t *lid) | | 168 | puffs_cc_getcaller(struct puffs_cc *pcc, pid_t *pid, lwpid_t *lid) |
169 | { | | 169 | { |
170 | | | 170 | |
171 | if ((pcc->pcc_flags & PCC_HASCALLER) == 0) { | | 171 | if ((pcc->pcc_flags & PCC_HASCALLER) == 0) { |
172 | errno = ESRCH; | | 172 | errno = ESRCH; |
173 | return -1; | | 173 | return -1; |
174 | } | | 174 | } |
175 | | | 175 | |
176 | if (pid) | | 176 | if (pid) |
177 | *pid = pcc->pcc_pid; | | 177 | *pid = pcc->pcc_pid; |
178 | if (lid) | | 178 | if (lid) |
179 | *lid = pcc->pcc_lid; | | 179 | *lid = pcc->pcc_lid; |
180 | return 0; | | 180 | return 0; |
181 | } | | 181 | } |
182 | | | 182 | |
183 | static struct puffs_cc fakecc; | | 183 | static struct puffs_cc fakecc; |
184 | | | 184 | |
185 | static struct puffs_cc * | | 185 | static struct puffs_cc * |
186 | slowccalloc(struct puffs_usermount *pu) | | 186 | slowccalloc(struct puffs_usermount *pu) |
187 | { | | 187 | { |
188 | struct puffs_cc *volatile pcc; | | 188 | struct puffs_cc *volatile pcc; |
189 | void *sp; | | 189 | void *sp; |
190 | size_t stacksize = 1<<pu->pu_cc_stackshift; | | 190 | size_t stacksize = 1<<pu->pu_cc_stackshift; |
191 | long psize = sysconf(_SC_PAGESIZE); | | 191 | const long psize = sysconf(_SC_PAGESIZE); |
192 | | | 192 | |
193 | if (puffs_fakecc) | | 193 | if (puffs_fakecc) |
194 | return &fakecc; | | 194 | return &fakecc; |
195 | | | 195 | |
196 | sp = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, | | 196 | sp = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, |
197 | MAP_ANON|MAP_PRIVATE|MAP_ALIGNED(pu->pu_cc_stackshift), -1, 0); | | 197 | MAP_ANON|MAP_PRIVATE|MAP_ALIGNED(pu->pu_cc_stackshift), -1, 0); |
198 | if (sp == MAP_FAILED) | | 198 | if (sp == MAP_FAILED) |
199 | return NULL; | | 199 | return NULL; |
200 | | | 200 | |
201 | pcc = sp; | | 201 | pcc = sp; |
202 | memset(pcc, 0, sizeof(struct puffs_cc)); | | 202 | memset(pcc, 0, sizeof(struct puffs_cc)); |
203 | | | 203 | |
| | | 204 | #ifndef __MACHINE_STACK_GROWS_UP |
204 | mprotect((uint8_t *)sp + psize, (size_t)psize, PROT_NONE); | | 205 | mprotect((uint8_t *)sp + psize, (size_t)psize, PROT_NONE); |
| | | 206 | #else |
| | | 207 | mprotect((uint8_t *)sp + stacksize - psize, (size_t)psize, PROT_NONE); |
| | | 208 | #endif |
205 | | | 209 | |
206 | /* initialize both ucontext's */ | | 210 | /* initialize both ucontext's */ |
207 | if (getcontext(&pcc->pcc_uc) == -1) { | | 211 | if (getcontext(&pcc->pcc_uc) == -1) { |
208 | munmap(pcc, stacksize); | | 212 | munmap(pcc, stacksize); |
209 | return NULL; | | 213 | return NULL; |
210 | } | | 214 | } |
211 | if (getcontext(&pcc->pcc_uc_ret) == -1) { | | 215 | if (getcontext(&pcc->pcc_uc_ret) == -1) { |
212 | munmap(pcc, stacksize); | | 216 | munmap(pcc, stacksize); |
213 | return NULL; | | 217 | return NULL; |
214 | } | | 218 | } |
215 | | | 219 | |
216 | return pcc; | | 220 | return pcc; |
217 | } | | 221 | } |
218 | | | 222 | |
219 | int | | 223 | int |
220 | puffs__cc_create(struct puffs_usermount *pu, puffs_ccfunc func, | | 224 | puffs__cc_create(struct puffs_usermount *pu, puffs_ccfunc func, |
221 | struct puffs_cc **pccp) | | 225 | struct puffs_cc **pccp) |
222 | { | | 226 | { |
223 | struct puffs_cc *pcc; | | 227 | struct puffs_cc *pcc; |
224 | size_t stacksize = 1<<pu->pu_cc_stackshift; | | 228 | size_t stacksize = 1<<pu->pu_cc_stackshift; |
225 | stack_t *st; | | 229 | stack_t *st; |
226 | | | 230 | |
227 | /* Do we have a cached copy? */ | | 231 | /* Do we have a cached copy? */ |
228 | if (pu->pu_cc_nstored == 0) { | | 232 | if (pu->pu_cc_nstored == 0) { |
229 | pcc = slowccalloc(pu); | | 233 | pcc = slowccalloc(pu); |
230 | if (pcc == NULL) | | 234 | if (pcc == NULL) |
231 | return -1; | | 235 | return -1; |
232 | pcc->pcc_pu = pu; | | 236 | pcc->pcc_pu = pu; |
233 | DPRINTF(("puffs__cc_create: allocated pcc %p\n", pcc)); | | 237 | DPRINTF(("puffs__cc_create: allocated pcc %p\n", pcc)); |
234 | } else { | | 238 | } else { |
235 | pcc = LIST_FIRST(&pu->pu_ccmagazin); | | 239 | pcc = LIST_FIRST(&pu->pu_ccmagazin); |
236 | assert(pcc != NULL); | | 240 | assert(pcc != NULL); |
237 | | | 241 | |
238 | LIST_REMOVE(pcc, pcc_rope); | | 242 | LIST_REMOVE(pcc, pcc_rope); |
239 | pu->pu_cc_nstored--; | | 243 | pu->pu_cc_nstored--; |
240 | DPRINTF(("puffs__cc_create: magazin pcc %p\n", pcc)); | | 244 | DPRINTF(("puffs__cc_create: magazin pcc %p\n", pcc)); |
241 | } | | 245 | } |
242 | assert(pcc->pcc_pu == pu); | | 246 | assert(pcc->pcc_pu == pu); |
243 | | | 247 | |
244 | if (puffs_fakecc) { | | 248 | if (puffs_fakecc) { |
245 | pcc->pcc_func = func; | | 249 | pcc->pcc_func = func; |
246 | pcc->pcc_farg = pcc; | | 250 | pcc->pcc_farg = pcc; |
247 | } else { | | 251 | } else { |
| | | 252 | const long psize = sysconf(_SC_PAGESIZE); |
| | | 253 | |
248 | /* link context */ | | 254 | /* link context */ |
249 | pcc->pcc_uc.uc_link = &pcc->pcc_uc_ret; | | 255 | pcc->pcc_uc.uc_link = &pcc->pcc_uc_ret; |
250 | | | 256 | |
251 | /* setup stack | | 257 | /* setup stack |
252 | * | | 258 | * |
253 | * XXX: I guess this should theoretically be preserved by | | 259 | * XXX: I guess this should theoretically be preserved by |
254 | * swapcontext(). However, it gets lost. So reinit it. | | 260 | * swapcontext(). However, it gets lost. So reinit it. |
255 | */ | | 261 | */ |
256 | st = &pcc->pcc_uc.uc_stack; | | 262 | st = &pcc->pcc_uc.uc_stack; |
257 | st->ss_sp = pcc; | | 263 | st->ss_sp = ((uint8_t *)(void *)pcc) + psize; |
258 | st->ss_size = stacksize; | | 264 | st->ss_size = stacksize - psize; |
259 | st->ss_flags = 0; | | 265 | st->ss_flags = 0; |
260 | | | 266 | |
261 | /* | | 267 | /* |
262 | * Give us an initial context to jump to. | | 268 | * Give us an initial context to jump to. |
263 | * | | 269 | * |
264 | * Our manual page says that portable code shouldn't | | 270 | * Our manual page says that portable code shouldn't |
265 | * rely on being able to pass pointers through makecontext(). | | 271 | * rely on being able to pass pointers through makecontext(). |
266 | * kjk says that NetBSD code doesn't need to worry about this. | | 272 | * kjk says that NetBSD code doesn't need to worry about this. |
267 | * uwe says it would be like putting a "keep away from | | 273 | * uwe says it would be like putting a "keep away from |
268 | * children" sign on a box of toys. | | 274 | * children" sign on a box of toys. |
269 | */ | | 275 | */ |
270 | makecontext(&pcc->pcc_uc, (void *)func, 1, (uintptr_t)pcc); | | 276 | makecontext(&pcc->pcc_uc, (void *)func, 1, (uintptr_t)pcc); |
271 | } | | 277 | } |
272 | | | 278 | |
273 | *pccp = pcc; | | 279 | *pccp = pcc; |
274 | return 0; | | 280 | return 0; |
275 | } | | 281 | } |
276 | | | 282 | |
277 | void | | 283 | void |
278 | puffs__cc_setcaller(struct puffs_cc *pcc, pid_t pid, lwpid_t lid) | | 284 | puffs__cc_setcaller(struct puffs_cc *pcc, pid_t pid, lwpid_t lid) |
279 | { | | 285 | { |
280 | | | 286 | |
281 | pcc->pcc_pid = pid; | | 287 | pcc->pcc_pid = pid; |
282 | pcc->pcc_lid = lid; | | 288 | pcc->pcc_lid = lid; |
283 | pcc->pcc_flags |= PCC_HASCALLER; | | 289 | pcc->pcc_flags |= PCC_HASCALLER; |
284 | } | | 290 | } |
285 | | | 291 | |
286 | static void | | 292 | static void |
287 | cc_free(struct puffs_cc *pcc) | | 293 | cc_free(struct puffs_cc *pcc) |
288 | { | | 294 | { |
289 | struct puffs_usermount *pu = pcc->pcc_pu; | | 295 | struct puffs_usermount *pu = pcc->pcc_pu; |
290 | size_t stacksize = 1<<pu->pu_cc_stackshift; | | 296 | size_t stacksize = 1<<pu->pu_cc_stackshift; |
291 | | | 297 | |
292 | DPRINTF(("invalidating pcc %p\n", pcc)); | | 298 | DPRINTF(("invalidating pcc %p\n", pcc)); |
293 | assert(!puffs_fakecc); | | 299 | assert(!puffs_fakecc); |
294 | munmap(pcc, stacksize); | | 300 | munmap(pcc, stacksize); |
295 | } | | 301 | } |
296 | | | 302 | |
297 | void | | 303 | void |
298 | puffs__cc_destroy(struct puffs_cc *pcc, int nonuke) | | 304 | puffs__cc_destroy(struct puffs_cc *pcc, int nonuke) |
299 | { | | 305 | { |
300 | struct puffs_usermount *pu = pcc->pcc_pu; | | 306 | struct puffs_usermount *pu = pcc->pcc_pu; |
301 | | | 307 | |
302 | pcc->pcc_flags &= ~PCC_HASCALLER; | | 308 | pcc->pcc_flags &= ~PCC_HASCALLER; |
303 | assert(pcc->pcc_flags == 0); | | 309 | assert(pcc->pcc_flags == 0); |
304 | assert(!puffs_fakecc); | | 310 | assert(!puffs_fakecc); |
305 | | | 311 | |
306 | /* not over limit? stuff away in the store, otherwise nuke */ | | 312 | /* not over limit? stuff away in the store, otherwise nuke */ |
307 | if (nonuke || pu->pu_cc_nstored < PUFFS_CCMAXSTORE) { | | 313 | if (nonuke || pu->pu_cc_nstored < PUFFS_CCMAXSTORE) { |
308 | pcc->pcc_pb = NULL; | | 314 | pcc->pcc_pb = NULL; |
309 | DPRINTF(("puffs__cc_destroy: storing pcc %p\n", pcc)); | | 315 | DPRINTF(("puffs__cc_destroy: storing pcc %p\n", pcc)); |
310 | LIST_INSERT_HEAD(&pu->pu_ccmagazin, pcc, pcc_rope); | | 316 | LIST_INSERT_HEAD(&pu->pu_ccmagazin, pcc, pcc_rope); |
311 | pu->pu_cc_nstored++; | | 317 | pu->pu_cc_nstored++; |
312 | } else { | | 318 | } else { |
313 | cc_free(pcc); | | 319 | cc_free(pcc); |
314 | } | | 320 | } |
315 | } | | 321 | } |
316 | | | 322 | |
317 | void | | 323 | void |
318 | puffs__cc_exit(struct puffs_usermount *pu) | | 324 | puffs__cc_exit(struct puffs_usermount *pu) |
319 | { | | 325 | { |
320 | struct puffs_cc *pcc; | | 326 | struct puffs_cc *pcc; |
321 | | | 327 | |
322 | while ((pcc = LIST_FIRST(&pu->pu_ccmagazin)) != NULL) { | | 328 | while ((pcc = LIST_FIRST(&pu->pu_ccmagazin)) != NULL) { |
323 | LIST_REMOVE(pcc, pcc_rope); | | 329 | LIST_REMOVE(pcc, pcc_rope); |
324 | cc_free(pcc); | | 330 | cc_free(pcc); |
325 | } | | 331 | } |
326 | } | | 332 | } |
327 | | | 333 | |
328 | struct puffs_cc * | | 334 | struct puffs_cc * |
329 | puffs_cc_getcc(struct puffs_usermount *pu) | | 335 | puffs_cc_getcc(struct puffs_usermount *pu) |
330 | { | | 336 | { |
331 | size_t stacksize = 1<<pu->pu_cc_stackshift; | | 337 | size_t stacksize = 1<<pu->pu_cc_stackshift; |
332 | uintptr_t bottom; | | 338 | uintptr_t bottom; |
333 | | | 339 | |
334 | if (puffs_fakecc) | | 340 | if (puffs_fakecc) |
335 | return &fakecc; | | 341 | return &fakecc; |
336 | | | 342 | |
337 | bottom = ((uintptr_t)&bottom) & ~(stacksize-1); | | 343 | bottom = ((uintptr_t)&bottom) & ~(stacksize-1); |
338 | return (struct puffs_cc *)bottom; | | 344 | return (struct puffs_cc *)bottom; |
339 | } | | 345 | } |
340 | | | 346 | |
341 | int | | 347 | int |
342 | puffs__cc_savemain(struct puffs_usermount *pu) | | 348 | puffs__cc_savemain(struct puffs_usermount *pu) |
343 | { | | 349 | { |
344 | | | 350 | |
345 | if (puffs_fakecc) | | 351 | if (puffs_fakecc) |
346 | return 0; | | 352 | return 0; |
347 | | | 353 | |
348 | PU_CLRSFLAG(pu, PU_MAINRESTORE); | | 354 | PU_CLRSFLAG(pu, PU_MAINRESTORE); |
349 | return getcontext(&pu->pu_mainctx); | | 355 | return getcontext(&pu->pu_mainctx); |
350 | } | | 356 | } |
351 | | | 357 | |
352 | int | | 358 | int |
353 | puffs__cc_restoremain(struct puffs_usermount *pu) | | 359 | puffs__cc_restoremain(struct puffs_usermount *pu) |
354 | { | | 360 | { |
355 | | | 361 | |
356 | if (puffs_fakecc) | | 362 | if (puffs_fakecc) |
357 | return 0; | | 363 | return 0; |
358 | | | 364 | |
359 | puffs__cc_destroy(puffs_cc_getcc(pu), 1); | | 365 | puffs__cc_destroy(puffs_cc_getcc(pu), 1); |
360 | PU_SETSFLAG(pu, PU_MAINRESTORE); | | 366 | PU_SETSFLAG(pu, PU_MAINRESTORE); |
361 | return setcontext(&pu->pu_mainctx); | | 367 | return setcontext(&pu->pu_mainctx); |
362 | } | | 368 | } |