Tue Dec 6 21:15:39 2011 UTC ()
Deal with __MACHINE_STACK_GROWS_UP machines.

constify the other psize while I'm here.

Thanks to Christos for looking.


(skrll)
diff -r1.26 -r1.27 src/lib/libpuffs/callcontext.c

cvs diff -r1.26 -r1.27 src/lib/libpuffs/callcontext.c (switch to unified diff)

--- src/lib/libpuffs/callcontext.c 2011/11/02 16:43:04 1.26
+++ src/lib/libpuffs/callcontext.c 2011/12/06 21:15:39 1.27
@@ -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 */
61int puffs_fakecc; 61int 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 */
73void 73void
74puffs_cc_yield(struct puffs_cc *pcc) 74puffs_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 */
112void 112void
113puffs__cc_cont(struct puffs_cc *pcc) 113puffs__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
129void 129void
130puffs_cc_continue(struct puffs_cc *pcc) 130puffs_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 */
149void 149void
150puffs__goto(struct puffs_cc *loanpcc) 150puffs__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
158void 158void
159puffs_cc_schedule(struct puffs_cc *pcc) 159puffs_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
167int 167int
168puffs_cc_getcaller(struct puffs_cc *pcc, pid_t *pid, lwpid_t *lid) 168puffs_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
183static struct puffs_cc fakecc; 183static struct puffs_cc fakecc;
184 184
185static struct puffs_cc * 185static struct puffs_cc *
186slowccalloc(struct puffs_usermount *pu) 186slowccalloc(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
219int 223int
220puffs__cc_create(struct puffs_usermount *pu, puffs_ccfunc func, 224puffs__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
277void 283void
278puffs__cc_setcaller(struct puffs_cc *pcc, pid_t pid, lwpid_t lid) 284puffs__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
286static void 292static void
287cc_free(struct puffs_cc *pcc) 293cc_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
297void 303void
298puffs__cc_destroy(struct puffs_cc *pcc, int nonuke) 304puffs__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
317void 323void
318puffs__cc_exit(struct puffs_usermount *pu) 324puffs__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
328struct puffs_cc * 334struct puffs_cc *
329puffs_cc_getcc(struct puffs_usermount *pu) 335puffs_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
341int 347int
342puffs__cc_savemain(struct puffs_usermount *pu) 348puffs__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
352int 358int
353puffs__cc_restoremain(struct puffs_usermount *pu) 359puffs__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}