Implement lazy contexts for file systems using puffs_mainloop().

Previously each request was executed on its own callcontext and
switched to every time the request was being processed.  Now requests
borrow the mainloop context and switch only if/when they yield.
This takes two context switches away from a file system request
bringing down the typical amounts 2->0 (e.g. dtfs) and 4->2 (e.g.
psshfs).

The interfaces for manually executing requests changed a bit:
puffs_dispatch_create() and puffs_dispatch_exec() must now be used.
They are not tested, as nothing in-tree wants them and I doubt
anyone else is really interested in them either.

Also do some misc code cleanup related to execution contexts.  The
"work-in-progress checkpoint" committed over a year ago was starting
to look slightly weed-infested.
This commit is contained in:
pooka 2008-01-28 18:35:49 +00:00
parent f3b8aacb17
commit d1d05d65b9
9 changed files with 428 additions and 538 deletions

View File

@ -1,7 +1,10 @@
/* $NetBSD: callcontext.c,v 1.19 2008/01/17 17:43:14 pooka Exp $ */
/* $NetBSD: callcontext.c,v 1.20 2008/01/28 18:35:49 pooka Exp $ */
/*
* Copyright (c) 2006 Antti Kantee. All Rights Reserved.
* Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved.
*
* Development of this software was supported by the
* Research Foundation of Helsinki University of Technology
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -27,7 +30,7 @@
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: callcontext.c,v 1.19 2008/01/17 17:43:14 pooka Exp $");
__RCSID("$NetBSD: callcontext.c,v 1.20 2008/01/28 18:35:49 pooka Exp $");
#endif /* !lint */
#include <sys/types.h>
@ -35,9 +38,6 @@ __RCSID("$NetBSD: callcontext.c,v 1.19 2008/01/17 17:43:14 pooka Exp $");
#include <assert.h>
#include <errno.h>
#ifdef PUFFS_WITH_THREADS
#include <pthread.h>
#endif
#include <puffs.h>
#include <stdio.h>
#include <stdlib.h>
@ -47,29 +47,75 @@ __RCSID("$NetBSD: callcontext.c,v 1.19 2008/01/17 17:43:14 pooka Exp $");
#include "puffs_priv.h"
/*
* Set the following to 1 to not handle each request on a separate
* stack. This is highly volatile kludge, therefore no external
* interface.
*/
int puffs_fakecc;
/*
* user stuff
*/
/*
* So, we need to get back to where we came from. This can happen in two
* different ways:
* 1) PCC_MLCONT is set, in which case we need to go to the mainloop
* 2) It is not set, and we simply jump to pcc_uc_ret.
*/
void
puffs_cc_yield(struct puffs_cc *pcc)
{
struct puffs_cc *jumpcc;
int rv;
assert(puffs_fakecc == 0);
assert(pcc->pcc_flags & PCC_REALCC);
pcc->pcc_flags &= ~PCC_BORROWED;
/* romanes eunt domus */
swapcontext(&pcc->pcc_uc, &pcc->pcc_uc_ret);
if ((pcc->pcc_flags & PCC_MLCONT) == 0) {
swapcontext(&pcc->pcc_uc, &pcc->pcc_uc_ret);
} else {
pcc->pcc_flags &= ~PCC_MLCONT;
rv = puffs__cc_create(pcc->pcc_pu, puffs__theloop, &jumpcc);
if (rv)
abort(); /* p-p-p-pa-pa-panic (XXX: fixme) */
swapcontext(&pcc->pcc_uc, &jumpcc->pcc_uc);
}
}
/*
* Internal continue routine. This has slightly different semantics.
* We simply make our cc available in the freelist and jump to the
* indicated pcc.
*/
void
puffs__cc_cont(struct puffs_cc *pcc)
{
struct puffs_cc *mycc;
mycc = puffs_cc_getcc(pcc->pcc_pu);
/*
* XXX: race between setcontenxt() and recycle if
* we go multithreaded
*/
puffs__cc_destroy(mycc, 1);
pcc->pcc_flags |= PCC_MLCONT;
setcontext(&pcc->pcc_uc);
}
void
puffs_cc_continue(struct puffs_cc *pcc)
{
assert(pcc->pcc_flags & PCC_REALCC);
/* ramble on */
swapcontext(&pcc->pcc_uc_ret, &pcc->pcc_uc);
if (puffs_fakecc)
pcc->pcc_func(pcc->pcc_farg);
else
swapcontext(&pcc->pcc_uc_ret, &pcc->pcc_uc);
}
/*
@ -80,10 +126,9 @@ puffs_cc_continue(struct puffs_cc *pcc)
* yield again).
*/
void
puffs_goto(struct puffs_cc *loanpcc)
puffs__goto(struct puffs_cc *loanpcc)
{
assert(loanpcc->pcc_flags & PCC_REALCC);
loanpcc->pcc_flags |= PCC_BORROWED;
swapcontext(&loanpcc->pcc_uc_ret, &loanpcc->pcc_uc);
@ -114,126 +159,100 @@ puffs_cc_getcaller(struct puffs_cc *pcc, pid_t *pid, lwpid_t *lid)
return 0;
}
#ifdef PUFFS_WITH_THREADS
int pthread__stackid_setup(void *, size_t, pthread_t *);
#endif
/* for fakecc-users, need only one */
static struct puffs_cc fakecc;
int
puffs_cc_create(struct puffs_usermount *pu, struct puffs_framebuf *pb,
int type, struct puffs_cc **pccp)
static struct puffs_cc *
slowccalloc(struct puffs_usermount *pu)
{
struct puffs_cc *volatile pcc;
void *sp;
size_t stacksize = 1<<pu->pu_cc_stackshift;
long psize = sysconf(_SC_PAGESIZE);
stack_t *st;
void *volatile sp;
#ifdef PUFFS_WITH_THREADS
extern size_t pthread__stacksize;
stacksize = pthread__stacksize;
#endif
if (puffs_fakecc)
return &fakecc;
sp = mmap(NULL, stacksize, PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE|MAP_ALIGNED(pu->pu_cc_stackshift), -1, 0);
if (sp == MAP_FAILED)
return NULL;
pcc = sp;
memset(pcc, 0, sizeof(struct puffs_cc));
mprotect((uint8_t *)sp + psize, (size_t)psize, PROT_NONE);
/* initialize both ucontext's */
if (getcontext(&pcc->pcc_uc) == -1) {
munmap(pcc, stacksize);
return NULL;
}
if (getcontext(&pcc->pcc_uc_ret) == -1) {
munmap(pcc, stacksize);
return NULL;
}
return pcc;
}
int
puffs__cc_create(struct puffs_usermount *pu, puffs_ccfunc func,
struct puffs_cc **pccp)
{
struct puffs_cc *pcc;
size_t stacksize = 1<<pu->pu_cc_stackshift;
stack_t *st;
/* Do we have a cached copy? */
if (pu->pu_cc_nstored) {
if (pu->pu_cc_nstored == 0) {
pcc = slowccalloc(pu);
if (pcc == NULL)
return -1;
pcc->pcc_pu = pu;
} else {
pcc = LIST_FIRST(&pu->pu_ccmagazin);
assert(pcc != NULL);
LIST_REMOVE(pcc, pcc_rope);
pu->pu_cc_nstored--;
goto finalize;
}
/*
* There are two paths and in the long run we don't have time to
* change the one we're on. For non-real cc's, we just simply use
* a static copy. For the other cases, we mmap the stack and
* manually reserve a bit from the top for the data structure
* (or, well, the bottom).
*
* XXX: threaded mode doesn't work very well now. Not that it's
* supported anyhow.
*/
if (type == PCC_FAKECC) {
pcc = &fakecc;
sp = NULL;
} else {
sp = mmap(NULL, stacksize, PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE|MAP_ALIGNED(pu->pu_cc_stackshift),
-1, 0);
if (sp == MAP_FAILED)
return -1;
pcc = sp;
mprotect((uint8_t *)sp + psize, (size_t)psize, PROT_NONE);
}
memset(pcc, 0, sizeof(struct puffs_cc));
pcc->pcc_pu = pu;
/* Not a real cc? Don't need to init more */
if (type != PCC_REALCC)
goto out;
/* initialize both ucontext's */
if (getcontext(&pcc->pcc_uc) == -1) {
munmap(pcc, stacksize);
return -1;
}
if (getcontext(&pcc->pcc_uc_ret) == -1) {
munmap(pcc, stacksize);
return -1;
}
#ifdef PUFFS_WITH_THREADS
{
pthread_t pt;
extern int __isthreaded;
if (__isthreaded)
pthread__stackid_setup(sp, stacksize /* XXXb0rked */, &pt);
}
#endif
finalize:
assert(pcc->pcc_pu == pu);
/* return here. it won't actually be "here" due to swapcontext() */
pcc->pcc_uc.uc_link = &pcc->pcc_uc_ret;
if (puffs_fakecc) {
pcc->pcc_func = func;
pcc->pcc_farg = pcc;
} else {
/* link context */
pcc->pcc_uc.uc_link = &pcc->pcc_uc_ret;
/* setup stack
*
* XXX: I guess this should theoretically be preserved by
* swapcontext(). However, it gets lost. So reinit it.
*/
st = &pcc->pcc_uc.uc_stack;
st->ss_sp = pcc;
st->ss_size = stacksize;
st->ss_flags = 0;
/* setup stack
*
* XXX: I guess this should theoretically be preserved by
* swapcontext(). However, it gets lost. So reinit it.
*/
st = &pcc->pcc_uc.uc_stack;
st->ss_sp = pcc;
st->ss_size = stacksize;
st->ss_flags = 0;
/*
* Give us an initial context to jump to.
*
* XXX: Our manual page says that portable code shouldn't rely on
* being able to pass pointers through makecontext(). kjk says
* that NetBSD code doesn't need to worry about this. uwe says
* it would be like putting a "keep away from children" sign on a
* box of toys.
*/
makecontext(&pcc->pcc_uc, (void *)puffs_calldispatcher,
1, (uintptr_t)pcc);
out:
pcc->pcc_pb = pb;
pcc->pcc_flags = type;
/*
* Give us an initial context to jump to.
*
* Our manual page says that portable code shouldn't
* rely on being able to pass pointers through makecontext().
* kjk says that NetBSD code doesn't need to worry about this.
* uwe says it would be like putting a "keep away from
* children" sign on a box of toys.
*/
makecontext(&pcc->pcc_uc, (void *)func, 1, (uintptr_t)pcc);
}
*pccp = pcc;
return 0;
}
void
puffs_cc_setcaller(struct puffs_cc *pcc, pid_t pid, lwpid_t lid)
puffs__cc_setcaller(struct puffs_cc *pcc, pid_t pid, lwpid_t lid)
{
pcc->pcc_pid = pid;
@ -242,44 +261,32 @@ puffs_cc_setcaller(struct puffs_cc *pcc, pid_t pid, lwpid_t lid)
}
void
puffs_cc_destroy(struct puffs_cc *pcc)
puffs__cc_destroy(struct puffs_cc *pcc, int nonuke)
{
struct puffs_usermount *pu = pcc->pcc_pu;
size_t stacksize = 1<<pu->pu_cc_stackshift;
/* not over limit? stuff away in the store */
if (pu->pu_cc_nstored < PUFFS_CCMAXSTORE
&& pcc->pcc_flags & PCC_REALCC) {
pcc->pcc_flags &= ~PCC_DONE;
assert(pcc->pcc_flags = 0);
/* not over limit? stuff away in the store, otherwise nuke */
if (nonuke || pu->pu_cc_nstored < PUFFS_CCMAXSTORE) {
pcc->pcc_pb = NULL;
LIST_INSERT_HEAD(&pu->pu_ccmagazin, pcc, pcc_rope);
pu->pu_cc_nstored++;
return;
}
/* else: just dump it */
#ifdef PUFFS_WITH_THREADS
extern size_t pthread__stacksize;
stacksize = pthread__stacksize;
#endif
if ((pcc->pcc_flags & PCC_FAKECC) == 0)
} else {
assert(!puffs_fakecc);
munmap(pcc, stacksize);
}
}
struct puffs_cc *
puffs_cc_getcc(struct puffs_usermount *pu)
{
extern int puffs_fakecc, puffs_usethreads;
size_t stacksize = 1<<pu->pu_cc_stackshift;
uintptr_t bottom;
if (puffs_fakecc)
return &fakecc;
#ifndef PUFFS_WITH_THREADS
if (puffs_usethreads)
return &fakecc;
#endif
bottom = ((uintptr_t)&bottom) & ~(stacksize-1);
return (struct puffs_cc *)bottom;

View File

@ -1,10 +1,11 @@
/* $NetBSD: dispatcher.c,v 1.29 2008/01/16 23:17:43 pooka Exp $ */
/* $NetBSD: dispatcher.c,v 1.30 2008/01/28 18:35:50 pooka Exp $ */
/*
* Copyright (c) 2006, 2007 Antti Kantee. All Rights Reserved.
* Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved.
*
* Development of this software was supported by the
* Ulla Tuominen Foundation and the Finnish Cultural Foundation.
* Ulla Tuominen Foundation, the Finnish Cultural Foundation and
* Research Foundation of Helsinki University of Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -30,7 +31,7 @@
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: dispatcher.c,v 1.29 2008/01/16 23:17:43 pooka Exp $");
__RCSID("$NetBSD: dispatcher.c,v 1.30 2008/01/28 18:35:50 pooka Exp $");
#endif /* !lint */
#include <sys/types.h>
@ -49,15 +50,7 @@ __RCSID("$NetBSD: dispatcher.c,v 1.29 2008/01/16 23:17:43 pooka Exp $");
#include "puffs_priv.h"
static void processresult(struct puffs_usermount *, int);
/*
* Set the following to 1 to not handle each request on a separate
* stack. This is highly volatile kludge, therefore no external
* interface.
*/
int puffs_fakecc;
#if 0 /* me not worka now */
/*
* Set the following to 1 to handle each request in a separate pthread.
* This is not exported as it should not be used yet unless having a
@ -65,219 +58,100 @@ int puffs_fakecc;
* threadsafe).
*/
int puffs_usethreads;
#endif
static int
dopufbuf2(struct puffs_usermount *pu, struct puffs_framebuf *pb)
static void dispatch(struct puffs_cc *);
/* for our eyes only */
void
puffs__ml_dispatch(struct puffs_usermount *pu, struct puffs_framebuf *pb)
{
struct puffs_req *preq = puffs__framebuf_getdataptr(pb);
struct puffs_cc *pcc;
int type;
struct puffs_cc *pcc = puffs_cc_getcc(pu);
struct puffs_req *preq;
if (puffs_fakecc) {
type = PCC_FAKECC;
} else if (puffs_usethreads) {
type = PCC_THREADED;
#ifndef PUFFS_WITH_THREADS
type = PCC_FAKECC;
#endif
pcc->pcc_pb = pb;
pcc->pcc_flags |= PCC_MLCONT;
dispatch(pcc);
/* Put result to kernel sendqueue if necessary */
preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
if (PUFFSOP_WANTREPLY(preq->preq_opclass)) {
if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
puffsdump_rv(preq);
puffs_framev_enqueue_justsend(pu, pu->pu_fd,
pcc->pcc_pb, 0, 0);
} else {
type = PCC_REALCC;
puffs_framebuf_destroy(pcc->pcc_pb);
}
if (puffs_cc_create(pu, pb, type, &pcc) == -1)
return errno;
puffs_cc_setcaller(pcc, preq->preq_pid, preq->preq_lid);
#ifdef PUFFS_WITH_THREADS
if (puffs_usethreads) {
pthread_attr_t pattr;
pthread_t ptid;
int rv;
pthread_attr_init(&pattr);
pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
pthread_attr_destroy(&pattr);
ap->pwa_pcc = pcc;
rv = pthread_create(&ptid, &pattr, puffs_docc, pcc);
return rv;
/* who needs information when you're living on borrowed time? */
if (pcc->pcc_flags & PCC_BORROWED) {
puffs_cc_yield(pcc); /* back to borrow source */
}
#endif
puffs_docc(pcc);
pcc->pcc_flags = 0;
}
/* public, but not really tested and only semi-supported */
int
puffs_dispatch_create(struct puffs_usermount *pu, struct puffs_framebuf *pb,
struct puffs_cc **pccp)
{
struct puffs_cc *pcc;
if (puffs__cc_create(pu, dispatch, &pcc) == -1)
return -1;
pcc->pcc_pb = pb;
*pccp = pcc;
return 0;
}
/*
* User-visible point to handle a request from.
*
* <insert text here>
*/
int
puffs_dopufbuf(struct puffs_usermount *pu, struct puffs_framebuf *pb)
puffs_dispatch_exec(struct puffs_cc *pcc, struct puffs_framebuf **pbp)
{
struct puffs_req *preq = puffs__framebuf_getdataptr(pb);
int rv;
/*
* XXX: the structure is currently a mess. anyway, trap
* the cacheops here already, since they don't need a cc.
* I really should get around to revamping the operation
* dispatching code one of these days.
*
* Do the same for error notifications.
*/
if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_CACHE) {
struct puffs_cacheinfo *pci = (void *)preq;
puffs_cc_continue(pcc);
if (pu->pu_ops.puffs_cache_write == NULL)
return 0;
pu->pu_ops.puffs_cache_write(pu, preq->preq_cookie,
pci->pcache_nruns, pci->pcache_runs);
return 0;
} else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_ERROR) {
struct puffs_error *perr = (void *)preq;
pu->pu_errnotify(pu, preq->preq_optype,
perr->perr_error, perr->perr_str, preq->preq_cookie);
return 0;
if (pcc->pcc_flags & PCC_DONE) {
rv = 1;
*pbp = pcc->pcc_pb;
pcc->pcc_flags = 0;
puffs__cc_destroy(pcc, 0);
} else {
rv = 0;
}
if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
puffsdump_req(preq);
#if 0
XXX: we can't trust to hide preq in pufbuf
struct puffs_executor *pex;
/*
* Check if we are already processing an operation from the same
* caller. If so, queue this operation until the previous one
* finishes. This prevents us from executing certain operations
* out-of-order (e.g. fsync and reclaim).
*
* Each preq will only remove its own pex from the tailq.
* See puffs_docc() for the details on other-end removal
* and dispatching.
*/
pex = malloc(sizeof(struct puffs_executor));
pex->pex_pufbuf = pb;
PU_LOCK();
TAILQ_INSERT_TAIL(&pu->pu_exq, pex, pex_entries);
TAILQ_FOREACH(pex, &pu->pu_exq, pex_entries) {
struct puffs_req *pb_preq;
pb_preq = puffs__framebuf_getdataptr(pex->pex_pufbuf);
if (pb_preq->preq_pid == preq->preq_pid
&& pb_preq->preq_lid == preq->preq_lid) {
if (pb_preq != preq) {
PU_UNLOCK();
return 0;
}
}
}
PU_UNLOCK();
#endif
return dopufbuf2(pu, pb);
return rv;
}
enum {PUFFCALL_ANSWER, PUFFCALL_IGNORE, PUFFCALL_AGAIN};
void *
puffs_docc(void *arg)
{
struct puffs_cc *pcc = arg;
struct puffs_usermount *pu = pcc->pcc_pu;
struct puffs_req *preq;
struct puffs_cc *pcc_iter;
assert((pcc->pcc_flags & PCC_DONE) == 0);
if (pcc->pcc_flags & PCC_REALCC)
puffs_cc_continue(pcc);
else
puffs_calldispatcher(pcc);
if ((pcc->pcc_flags & PCC_DONE) == 0) {
assert(pcc->pcc_flags & PCC_REALCC);
return NULL;
}
preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
#if 0
XXX: see above, needs more thought
struct puffs_executor *pex, *pex_n;
int found;
/* check if we need to schedule FAFs which were stalled */
found = 0;
PU_LOCK();
for (pex = TAILQ_FIRST(&pu->pu_exq); pex; pex = pex_n) {
struct puffs_req *pb_preq;
pb_preq = puffs__framebuf_getdataptr(pex->pex_pufbuf);
pex_n = TAILQ_NEXT(pex, pex_entries);
if (pb_preq->preq_pid == preq->preq_pid
&& pb_preq->preq_lid == preq->preq_lid) {
if (found == 0) {
/* this is us */
assert(pb_preq == preq);
TAILQ_REMOVE(&pu->pu_exq, pex, pex_entries);
free(pex);
found = 1;
} else {
/* down at the mardi gras */
PU_UNLOCK();
dopufbuf2(pu, pex->pex_pufbuf);
PU_LOCK();
break;
}
}
}
#endif
if (!PUFFSOP_WANTREPLY(preq->preq_opclass))
puffs_framebuf_destroy(pcc->pcc_pb);
/* can't do this above due to PCC_BORROWED */
while ((pcc_iter = LIST_FIRST(&pu->pu_ccnukelst)) != NULL) {
LIST_REMOVE(pcc_iter, pcc_rope);
puffs_cc_destroy(pcc_iter);
}
PU_UNLOCK();
return NULL;
}
/* library private, but linked from callcontext.c */
void
puffs_calldispatcher(struct puffs_cc *pcc)
static void
dispatch(struct puffs_cc *pcc)
{
struct puffs_usermount *pu = pcc->pcc_pu;
struct puffs_ops *pops = &pu->pu_ops;
struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
void *auxbuf = preq; /* help with typecasting */
void *opcookie = preq->preq_cookie;
int error, rv, buildpath;
int error, buildpath;
assert(pcc->pcc_flags & (PCC_FAKECC | PCC_REALCC | PCC_THREADED));
assert(pcc == puffs_cc_getcc(pu)); /* remove me soon */
if (PUFFSOP_WANTREPLY(preq->preq_opclass))
rv = PUFFCALL_ANSWER;
else
rv = PUFFCALL_IGNORE;
assert((pcc->pcc_flags & PCC_DONE) == 0);
buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH;
preq->preq_setbacks = 0;
if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
puffsdump_req(preq);
puffs__cc_setcaller(pcc, preq->preq_pid, preq->preq_lid);
/* pre-operation */
if (pu->pu_oppre)
pu->pu_oppre(pu);
/* Execute actual operation */
if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) {
switch (preq->preq_optype) {
case PUFFS_VFS_UNMOUNT:
@ -1003,62 +877,32 @@ puffs_calldispatcher(struct puffs_cc *pcc)
error = EINVAL;
break;
}
} else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_CACHE) {
struct puffs_cacheinfo *pci = (void *)preq;
if (pu->pu_ops.puffs_cache_write) {
pu->pu_ops.puffs_cache_write(pu, preq->preq_cookie,
pci->pcache_nruns, pci->pcache_runs);
}
error = 0;
} else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_ERROR) {
struct puffs_error *perr = (void *)preq;
pu->pu_errnotify(pu, preq->preq_optype,
perr->perr_error, perr->perr_str, preq->preq_cookie);
error = 0;
} else {
/*
* this one also
* I guess the kernel sees this one coming also
*/
error = EINVAL;
}
preq->preq_rv = error;
pcc->pcc_flags |= PCC_DONE;
if (pu->pu_oppost)
pu->pu_oppost(pu);
/*
* Note, we are calling this from here so that we can run it
* off of the continuation stack. Otherwise puffs_goto() would
* not work.
*/
processresult(pu, rv);
}
static void
processresult(struct puffs_usermount *pu, int how)
{
struct puffs_cc *pcc = puffs_cc_getcc(pu);
struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
int pccflags = pcc->pcc_flags;
/* check if we need to store this reply */
switch (how) {
case PUFFCALL_ANSWER:
if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
puffsdump_rv(preq);
puffs_framev_enqueue_justsend(pu, pu->pu_fd,
pcc->pcc_pb, 0, 0);
/*FALLTHROUGH*/
case PUFFCALL_IGNORE:
PU_LOCK();
LIST_INSERT_HEAD(&pu->pu_ccnukelst, pcc, pcc_rope);
PU_UNLOCK();
break;
case PUFFCALL_AGAIN:
if ((pcc->pcc_flags & PCC_REALCC) == 0)
assert(pcc->pcc_flags & PCC_DONE);
break;
default:
assert(/*CONSTCOND*/0);
}
/* who needs information when you're living on borrowed time? */
if (pccflags & PCC_BORROWED) {
assert((pccflags & PCC_THREADED) == 0);
puffs_cc_yield(pcc); /* back to borrow source */
}
pcc->pcc_flags |= PCC_DONE;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: framebuf.c,v 1.26 2007/12/16 20:02:57 pooka Exp $ */
/* $NetBSD: framebuf.c,v 1.27 2008/01/28 18:35:50 pooka Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
@ -35,7 +35,7 @@
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: framebuf.c,v 1.26 2007/12/16 20:02:57 pooka Exp $");
__RCSID("$NetBSD: framebuf.c,v 1.27 2008/01/28 18:35:50 pooka Exp $");
#endif /* !lint */
#include <sys/types.h>
@ -328,7 +328,7 @@ errnotify(struct puffs_usermount *pu, struct puffs_framebuf *pufbuf, int error)
pufbuf->rv = error;
if (pufbuf->pcc) {
puffs_goto(pufbuf->pcc);
puffs__goto(pufbuf->pcc);
} else if (pufbuf->fcb) {
pufbuf->istat &= ~ISTAT_NODESTROY;
pufbuf->fcb(pu, pufbuf, pufbuf->fcb_arg, error);
@ -597,7 +597,7 @@ puffs_framev_enqueue_waitevent(struct puffs_cc *pcc, int fd, int *what)
}
void
puffs_framev_notify(struct puffs_fctrl_io *fio, int what)
puffs__framev_notify(struct puffs_fctrl_io *fio, int what)
{
struct puffs_fbevent *fbevp;
@ -652,7 +652,7 @@ puffs__framebuf_moveinfo(struct puffs_framebuf *from, struct puffs_framebuf *to)
}
void
puffs_framev_input(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
puffs__framev_input(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
struct puffs_fctrl_io *fio)
{
struct puffs_framebuf *pufbuf, *appbuf;
@ -672,7 +672,7 @@ puffs_framev_input(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
/* error */
if (rv) {
puffs_framev_readclose(pu, fio, rv);
puffs__framev_readclose(pu, fio, rv);
fio->cur_in = NULL;
if ((pufbuf->istat & ISTAT_DIRECT) == 0) {
assert((pufbuf->istat & ISTAT_NODESTROY) == 0);
@ -712,7 +712,7 @@ puffs_framev_input(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
appbuf->istat &= ~ISTAT_NODESTROY;
if (appbuf->pcc) {
puffs_docc(appbuf->pcc);
puffs__cc_cont(appbuf->pcc);
} else if (appbuf->fcb) {
appbuf->fcb(pu, appbuf, appbuf->fcb_arg, 0);
} else {
@ -724,7 +724,7 @@ puffs_framev_input(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
}
int
puffs_framev_output(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
puffs__framev_output(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
struct puffs_fctrl_io *fio)
{
struct puffs_framebuf *pufbuf;
@ -740,7 +740,7 @@ puffs_framev_output(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
rv = fctrl->wfb(pu, pufbuf, fio->io_fd, &complete);
if (rv) {
puffs_framev_writeclose(pu, fio, rv);
puffs__framev_writeclose(pu, fio, rv);
done = 1;
break;
}
@ -758,8 +758,8 @@ puffs_framev_output(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
done = 1;
} else if ((pufbuf->istat & ISTAT_DIRECT)) {
pufbuf->istat &= ~ISTAT_NODESTROY;
puffs_docc(pufbuf->pcc);
done = 1;
puffs__cc_cont(pufbuf->pcc);
} else if ((pufbuf->istat & ISTAT_NOREPLY) == 0) {
TAILQ_INSERT_TAIL(&fio->res_qing, pufbuf,
pfb_entries);
@ -915,7 +915,7 @@ puffs_framev_disablefd(struct puffs_usermount *pu, int fd, int what)
}
void
puffs_framev_readclose(struct puffs_usermount *pu,
puffs__framev_readclose(struct puffs_usermount *pu,
struct puffs_fctrl_io *fio, int error)
{
struct puffs_framebuf *pufbuf;
@ -952,7 +952,7 @@ puffs_framev_readclose(struct puffs_usermount *pu,
}
void
puffs_framev_writeclose(struct puffs_usermount *pu,
puffs__framev_writeclose(struct puffs_usermount *pu,
struct puffs_fctrl_io *fio, int error)
{
struct puffs_framebuf *pufbuf;
@ -986,14 +986,14 @@ removefio(struct puffs_usermount *pu, struct puffs_fctrl_io *fio, int error)
LIST_REMOVE(fio, fio_entries);
if (pu->pu_state & PU_INLOOP) {
puffs_framev_readclose(pu, fio, error);
puffs_framev_writeclose(pu, fio, error);
puffs__framev_readclose(pu, fio, error);
puffs__framev_writeclose(pu, fio, error);
}
while ((fbevp = LIST_FIRST(&fio->ev_qing)) != NULL) {
fbevp->rv = error;
LIST_REMOVE(fbevp, pfe_entries);
puffs_goto(fbevp->pcc);
puffs__goto(fbevp->pcc);
}
/* don't bother with realloc */
@ -1056,7 +1056,7 @@ puffs_framev_init(struct puffs_usermount *pu,
}
void
puffs_framev_exit(struct puffs_usermount *pu)
puffs__framev_exit(struct puffs_usermount *pu)
{
struct puffs_fctrl_io *fio;

View File

@ -1,4 +1,4 @@
.\" $NetBSD: puffs.3,v 1.38 2008/01/14 13:57:26 pooka Exp $
.\" $NetBSD: puffs.3,v 1.39 2008/01/28 18:35:50 pooka Exp $
.\"
.\" Copyright (c) 2006, 2007, 2008 Antti Kantee. All rights reserved.
.\"
@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd January 14, 2008
.Dd January 28, 2008
.Dt PUFFS 3
.Os
.Sh NAME
@ -80,7 +80,12 @@
.Ft int
.Fn puffs_mainloop "struct puffs_usermount *pu"
.Ft int
.Fn puffs_dopufbuf "struct puffs_usermount *pu" "struct puffs_framebuf *pb"
.Fo puffs_dispatch_create
.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pb"
.Fa "struct puffs_cc **pccp"
.Fc
.Ft int
.Fn puffs_dispatch_exec .Fa "struct puffs_cc *pcc" "struct puffs_framebuf **pbp"
.Sh DESCRIPTION
.Em IMPORTANT NOTE!
This document describes interfaces which are not yet guaranteed to be
@ -434,13 +439,39 @@ In case
.Xr puffs_framebuf 3
has been initialized, I/O from the relevant descriptors is processed
automatically by the eventloop.
.It Fn puffs_dopufbuf pu pb
Decode and dispatch the file system request in
.Ar pb .
The contents of
.It Fn puffs_dispatch_create pu pb pccp
.It Fn puffs_dispatch_exec pcc pbp
In case the use of
.Fn puffs_mainloop
is not possible, requests may be dispatched manually.
However, as this is less efficient than using the mainloop,
it should never be the first preference.
.Pp
Calling
.Fn puffs_dispatch_create
creates a dispatch request.
The argument
.Ar pb
must be of type
.Vt "struct puffs_req" .
should contains a valid request and upon success
.Ar pccp
will contain a valid request context.
This context is passed to
.Fn puffs_dispatch_exec
to execute the request.
If the request yielded before completing, the routine returns 0,
otherwise 1.
When the routine completes,
.Ar pcc
is made invalid and a pointer to the processed buffer is placed in
.Ar pbp .
It is the responsibility of the caller to send the response (if
necessary) and destroy the buffer.
.Pp
See
.Xr puffs_cc 3
and
.Xr puffs_framebuf 3
for further information.
.El
.Ss Cookies
Every file (regular file, directory, device node, ...) instance is

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs.c,v 1.88 2008/01/16 21:30:00 pooka Exp $ */
/* $NetBSD: puffs.c,v 1.89 2008/01/28 18:35:50 pooka Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: puffs.c,v 1.88 2008/01/16 21:30:00 pooka Exp $");
__RCSID("$NetBSD: puffs.c,v 1.89 2008/01/28 18:35:50 pooka Exp $");
#endif /* !lint */
#include <sys/param.h>
@ -115,7 +115,7 @@ finalpush(struct puffs_usermount *pu)
if (fio->stat & FIO_WRGONE)
continue;
puffs_framev_output(pu, fio->fctrl, fio);
puffs__framev_output(pu, fio->fctrl, fio);
}
}
@ -620,14 +620,12 @@ _puffs_init(int develv, struct puffs_ops *pops, const char *mntfromname,
LIST_INIT(&pu->pu_ios);
LIST_INIT(&pu->pu_ios_rmlist);
LIST_INIT(&pu->pu_ccmagazin);
LIST_INIT(&pu->pu_ccnukelst);
TAILQ_INIT(&pu->pu_sched);
TAILQ_INIT(&pu->pu_exq);
pu->pu_framectrl[PU_FRAMECTRL_FS].rfb = puffs_fsframe_read;
pu->pu_framectrl[PU_FRAMECTRL_FS].wfb = puffs_fsframe_write;
pu->pu_framectrl[PU_FRAMECTRL_FS].cmpfb = puffs_fsframe_cmp;
pu->pu_framectrl[PU_FRAMECTRL_FS].gotfb = puffs_fsframe_gotframe;
pu->pu_framectrl[PU_FRAMECTRL_FS].rfb = puffs__fsframe_read;
pu->pu_framectrl[PU_FRAMECTRL_FS].wfb = puffs__fsframe_write;
pu->pu_framectrl[PU_FRAMECTRL_FS].cmpfb = puffs__fsframe_cmp;
pu->pu_framectrl[PU_FRAMECTRL_FS].gotfb = puffs__fsframe_gotframe;
pu->pu_framectrl[PU_FRAMECTRL_FS].fdnotfn = puffs_framev_unmountonclose;
/* defaults for some user-settable translation functions */
@ -672,7 +670,7 @@ puffs_exit(struct puffs_usermount *pu, int force)
puffs_pn_put(pn);
finalpush(pu);
puffs_framev_exit(pu);
puffs__framev_exit(pu);
if (pu->pu_state & PU_HASKQ)
close(pu->pu_kq);
free(pu);
@ -680,48 +678,30 @@ puffs_exit(struct puffs_usermount *pu, int force)
return 0; /* always succesful for now, WILL CHANGE */
}
int
puffs_mainloop(struct puffs_usermount *pu)
/*
* Actual mainloop. This is called from a context which can block.
* It is called either from puffs_mainloop (indirectly, via
* puffs_cc_continue() or from puffs_cc_yield()).
*/
void
puffs__theloop(struct puffs_cc *pcc)
{
struct puffs_usermount *pu = pcc->pcc_pu;
struct puffs_framectrl *pfctrl;
struct puffs_fctrl_io *fio;
struct puffs_cc *pcc;
struct kevent *curev;
size_t nchanges;
int ndone, sverrno;
assert(puffs_getstate(pu) >= PUFFS_STATE_RUNNING);
pu->pu_kq = kqueue();
if (pu->pu_kq == -1)
goto out;
pu->pu_state |= PU_HASKQ;
puffs_setblockingmode(pu, PUFFSDEV_NONBLOCK);
if (puffs__framev_addfd_ctrl(pu, puffs_getselectable(pu),
PUFFS_FBIO_READ | PUFFS_FBIO_WRITE,
&pu->pu_framectrl[PU_FRAMECTRL_FS]) == -1)
goto out;
curev = realloc(pu->pu_evs, (2*pu->pu_nfds)*sizeof(struct kevent));
if (curev == NULL)
goto out;
pu->pu_evs = curev;
LIST_FOREACH(fio, &pu->pu_ios, fio_entries) {
EV_SET(curev, fio->io_fd, EVFILT_READ, EV_ADD,
0, 0, (uintptr_t)fio);
curev++;
EV_SET(curev, fio->io_fd, EVFILT_WRITE, EV_ADD | EV_DISABLE,
0, 0, (uintptr_t)fio);
curev++;
}
if (kevent(pu->pu_kq, pu->pu_evs, 2*pu->pu_nfds, NULL, 0, NULL) == -1)
goto out;
pu->pu_state |= PU_INLOOP;
int ndone;
while (puffs_getstate(pu) != PUFFS_STATE_UNMOUNTED) {
/*
* Schedule existing requests.
*/
while ((pcc = TAILQ_FIRST(&pu->pu_sched)) != NULL) {
TAILQ_REMOVE(&pu->pu_sched, pcc, pcc_schedent);
puffs__goto(pcc);
}
if (pu->pu_ml_lfn)
pu->pu_ml_lfn(pu);
@ -759,7 +739,7 @@ puffs_mainloop(struct puffs_usermount *pu)
* case is that we can fit everything into the
* socket buffer.
*/
puffs_framev_output(pu, pfctrl, fio);
puffs__framev_output(pu, pfctrl, fio);
}
/*
@ -794,7 +774,7 @@ puffs_mainloop(struct puffs_usermount *pu)
if (ndone == -1) {
if (errno != EINTR)
goto out;
break;
else
continue;
}
@ -823,32 +803,24 @@ puffs_mainloop(struct puffs_usermount *pu)
fio->stat &= ~FIO_WR;
/* XXX: how to know if it's a transient error */
puffs_framev_writeclose(pu, fio,
puffs__framev_writeclose(pu, fio,
(int)curev->data);
puffs_framev_notify(fio, PUFFS_FBIO_ERROR);
puffs__framev_notify(fio, PUFFS_FBIO_ERROR);
continue;
}
what = 0;
if (curev->filter == EVFILT_READ) {
puffs_framev_input(pu, pfctrl, fio);
puffs__framev_input(pu, pfctrl, fio);
what |= PUFFS_FBIO_READ;
}
else if (curev->filter == EVFILT_WRITE) {
puffs_framev_output(pu, pfctrl, fio);
puffs__framev_output(pu, pfctrl, fio);
what |= PUFFS_FBIO_WRITE;
}
if (what)
puffs_framev_notify(fio, what);
}
/*
* Schedule continuations.
*/
while ((pcc = TAILQ_FIRST(&pu->pu_sched)) != NULL) {
TAILQ_REMOVE(&pu->pu_sched, pcc, pcc_schedent);
puffs_goto(pcc);
puffs__framev_notify(fio, what);
}
/*
@ -860,6 +832,53 @@ puffs_mainloop(struct puffs_usermount *pu)
free(fio);
}
}
}
int
puffs_mainloop(struct puffs_usermount *pu)
{
struct puffs_fctrl_io *fio;
struct puffs_cc *pcc;
struct kevent *curev;
int sverrno, rv;
assert(puffs_getstate(pu) >= PUFFS_STATE_RUNNING);
pu->pu_kq = kqueue();
if (pu->pu_kq == -1)
goto out;
pu->pu_state |= PU_HASKQ;
puffs_setblockingmode(pu, PUFFSDEV_NONBLOCK);
if (puffs__framev_addfd_ctrl(pu, puffs_getselectable(pu),
PUFFS_FBIO_READ | PUFFS_FBIO_WRITE,
&pu->pu_framectrl[PU_FRAMECTRL_FS]) == -1)
goto out;
curev = realloc(pu->pu_evs, (2*pu->pu_nfds)*sizeof(struct kevent));
if (curev == NULL)
goto out;
pu->pu_evs = curev;
LIST_FOREACH(fio, &pu->pu_ios, fio_entries) {
EV_SET(curev, fio->io_fd, EVFILT_READ, EV_ADD,
0, 0, (uintptr_t)fio);
curev++;
EV_SET(curev, fio->io_fd, EVFILT_WRITE, EV_ADD | EV_DISABLE,
0, 0, (uintptr_t)fio);
curev++;
}
if (kevent(pu->pu_kq, pu->pu_evs, 2*pu->pu_nfds, NULL, 0, NULL) == -1)
goto out;
pu->pu_state |= PU_INLOOP;
/* Create alternate execution context and jump to it */
rv = puffs__cc_create(pu, puffs__theloop, &pcc);
if (rv)
goto out;
puffs_cc_continue(pcc);
finalpush(pu);
errno = 0;

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs.h,v 1.104 2008/01/14 13:57:27 pooka Exp $ */
/* $NetBSD: puffs.h,v 1.105 2008/01/28 18:35:50 pooka Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@ -465,8 +465,11 @@ void puffs_vattr_null(struct vattr *);
void puffs_null_setops(struct puffs_ops *);
int puffs_dopufbuf(struct puffs_usermount *,
struct puffs_framebuf *);
int puffs_dispatch_create(struct puffs_usermount *,
struct puffs_framebuf *,
struct puffs_cc **);
int puffs_dispatch_exec(struct puffs_cc *,
struct puffs_framebuf **);
/*
* generic/dummy routines applicable for some file systems
@ -531,7 +534,6 @@ void puffs_cc_continue(struct puffs_cc *);
void puffs_cc_schedule(struct puffs_cc *);
int puffs_cc_getcaller(struct puffs_cc *,pid_t *,lwpid_t *);
struct puffs_cc *puffs_cc_getcc(struct puffs_usermount *);
void *puffs_docc(void *);
/*
* Flushing / invalidation routines

View File

@ -1,6 +1,6 @@
.\" $NetBSD: puffs_cc.3,v 1.10 2007/12/15 20:08:06 pooka Exp $
.\" $NetBSD: puffs_cc.3,v 1.11 2008/01/28 18:35:50 pooka Exp $
.\"
.\" Copyright (c) 2007 Antti Kantee. All rights reserved.
.\" Copyright (c) 2007, 2008 Antti Kantee. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd December 15, 2007
.Dd January 28, 2008
.Dt PUFFS_CC 3
.Os
.Sh NAME
@ -41,8 +41,6 @@
.Fn puffs_cc_schedule "struct puffs_cc *pcc"
.Ft struct puffs_cc *
.Fn puffs_cc_getcc "struct puffs_usermount *pu"
.Ft void *
.Fn puffs_docc "void *arg"
.Sh DESCRIPTION
.Em IMPORTANT NOTE!
This document describes interfaces which are not yet guaranteed to be
@ -61,17 +59,15 @@ in puffs.
Suspend and save the current execution context and return control
to the previous point.
In practice, from the file system author perspective, control returns
back to where either
.Fn puffs_dopufbuf
or
.Fn puffs_docc
was called.
back to where either the mainloop or where
.Fn puffs_dispatch_exec
was called from.
.It Fn puffs_cc_continue pcc
Will suspend current execution and return control to where it was
before before calling
.Fn puffs_cc_yield .
This is rarely called directly but rather through
.Fn puffs_docc .
.Fn puffs_dispatch_exec .
.It Fn puffs_cc_schedule "pcc"
Schedule a continuation.
As opposed to
@ -87,19 +83,6 @@ if this is the main thread.
The argument
.Ar pu
will most likely disappear at some point.
.It Fn puffs_docc "arg"
Continues request suspended with
.Fn puffs_cc_yield .
If the request completes without yielding again, the result is put
into the file server response queue.
.Pp
The argument must be of type
.Vt "struct puffs_cc *" .
The return value is ignored.
The signature of this function is intended to match
.Fn start_routine
of
.Fn pthread_create .
.El
.Pp
Before calling
@ -111,7 +94,9 @@ This cookie should be hooked to the
so that the correct continuation can be continued when the event it
was waiting for triggers. Alternatively, the
.Xr puffs_framebuf 3
framework can be used for handling this automatically.
framework and
.Fn puffs_mainloop
can be used for handling this automatically.
.Sh SEE ALSO
.Xr puffs 3 ,
.Xr puffs_framebuf 3

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs_priv.h,v 1.38 2008/01/16 21:30:00 pooka Exp $ */
/* $NetBSD: puffs_priv.h,v 1.39 2008/01/28 18:35:50 pooka Exp $ */
/*
* Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved.
@ -91,10 +91,6 @@ struct puffs_fctrl_io {
|| (fio->stat & FIO_ENABLE_W) == 0)) \
&& (fio->wwait == 0)))
struct puffs_executor {
struct puffs_framebuf *pex_pufbuf;
TAILQ_ENTRY(puffs_executor) pex_entries;
};
/*
* usermount: describes one file system instance
@ -108,6 +104,7 @@ struct puffs_usermount {
uint32_t pu_flags;
int pu_cc_stackshift;
struct puffs_cc *pu_cc_main;
#define PUFFS_CCMAXSTORE 32
int pu_cc_nstored;
@ -126,11 +123,9 @@ struct puffs_usermount {
LIST_HEAD(, puffs_node) pu_pnodelst;
LIST_HEAD(, puffs_cc) pu_ccmagazin;
LIST_HEAD(, puffs_cc) pu_ccnukelst;
TAILQ_HEAD(, puffs_cc) pu_lazyctx;
TAILQ_HEAD(, puffs_cc) pu_sched;
TAILQ_HEAD(, puffs_executor) pu_exq;
pu_cmap_fn pu_cmap;
pu_pathbuild_fn pu_pathbuild;
@ -164,12 +159,24 @@ struct puffs_usermount {
/* call context */
struct puffs_cc;
typedef void (*puffs_ccfunc)(struct puffs_cc *);
struct puffs_cc {
struct puffs_usermount *pcc_pu;
struct puffs_framebuf *pcc_pb;
ucontext_t pcc_uc; /* "continue" */
ucontext_t pcc_uc_ret; /* "yield" */
/* real cc */
union {
struct {
ucontext_t uc; /* "continue" */
ucontext_t uc_ret; /* "yield" */
} real;
struct {
puffs_ccfunc func;
void *farg;
} fake;
} pcc_u;
pid_t pcc_pid;
lwpid_t pcc_lid;
@ -179,21 +186,14 @@ struct puffs_cc {
TAILQ_ENTRY(puffs_cc) pcc_schedent;
LIST_ENTRY(puffs_cc) pcc_rope;
};
#define PCC_FAKECC 0x01
#define PCC_REALCC 0x02
#define PCC_DONE 0x04
#define PCC_BORROWED 0x08
#define PCC_HASCALLER 0x10
#define PCC_THREADED 0x20
#define pcc_callstat(a) (a->pcc_flags & PCC_CALL_MASK)
#define pcc_callset(a, b) (a->pcc_flags = (a->pcc_flags & ~PCC_CALL_MASK) | b)
#define pcc_init_unreal(ap, type) \
do { \
memset(ap, 0, sizeof(*ap)); \
(ap)->pcc_flags = type; \
} while (/*CONSTCOND*/0)
#define pcc_uc pcc_u.real.uc
#define pcc_uc_ret pcc_u.real.uc_ret
#define pcc_func pcc_u.fake.func
#define pcc_farg pcc_u.fake.farg
#define PCC_DONE 0x01
#define PCC_BORROWED 0x02
#define PCC_HASCALLER 0x04
#define PCC_MLCONT 0x08
struct puffs_newinfo {
void **pni_cookie;
@ -214,38 +214,40 @@ struct puffs_newinfo {
__BEGIN_DECLS
void puffs_calldispatcher(struct puffs_cc *);
void puffs_framev_input(struct puffs_usermount *, struct puffs_framectrl *,
void puffs__framev_input(struct puffs_usermount *, struct puffs_framectrl *,
struct puffs_fctrl_io *);
int puffs_framev_output(struct puffs_usermount *, struct puffs_framectrl*,
int puffs__framev_output(struct puffs_usermount *, struct puffs_framectrl*,
struct puffs_fctrl_io *);
void puffs_framev_exit(struct puffs_usermount *);
void puffs_framev_readclose(struct puffs_usermount *,
void puffs__framev_exit(struct puffs_usermount *);
void puffs__framev_readclose(struct puffs_usermount *,
struct puffs_fctrl_io *, int);
void puffs_framev_writeclose(struct puffs_usermount *,
void puffs__framev_writeclose(struct puffs_usermount *,
struct puffs_fctrl_io *, int);
void puffs_framev_notify(struct puffs_fctrl_io *, int);
void puffs__framev_notify(struct puffs_fctrl_io *, int);
void *puffs__framebuf_getdataptr(struct puffs_framebuf *);
int puffs__framev_addfd_ctrl(struct puffs_usermount *, int, int,
struct puffs_framectrl *);
void puffs__framebuf_moveinfo(struct puffs_framebuf *,
struct puffs_framebuf *);
int puffs_cc_create(struct puffs_usermount *, struct puffs_framebuf *,
int, struct puffs_cc **);
void puffs_cc_destroy(struct puffs_cc *);
void puffs_cc_setcaller(struct puffs_cc *, pid_t, lwpid_t);
void puffs_goto(struct puffs_cc *);
void puffs__theloop(struct puffs_cc *);
void puffs__ml_dispatch(struct puffs_usermount *, struct puffs_framebuf *);
int puffs_fsframe_read(struct puffs_usermount *, struct puffs_framebuf *,
int, int *);
int puffs_fsframe_write(struct puffs_usermount *, struct puffs_framebuf *,
int, int *);
int puffs_fsframe_cmp(struct puffs_usermount *, struct puffs_framebuf *,
struct puffs_framebuf *, int *);
void puffs_fsframe_gotframe(struct puffs_usermount *,
struct puffs_framebuf *);
int puffs__cc_create(struct puffs_usermount *, puffs_ccfunc,
struct puffs_cc **);
void puffs__cc_cont(struct puffs_cc *);
void puffs__cc_destroy(struct puffs_cc *, int);
void puffs__cc_setcaller(struct puffs_cc *, pid_t, lwpid_t);
void puffs__goto(struct puffs_cc *);
int puffs__fsframe_read(struct puffs_usermount *, struct puffs_framebuf *,
int, int *);
int puffs__fsframe_write(struct puffs_usermount *, struct puffs_framebuf *,
int, int *);
int puffs__fsframe_cmp(struct puffs_usermount *, struct puffs_framebuf *,
struct puffs_framebuf *, int *);
void puffs__fsframe_gotframe(struct puffs_usermount *,
struct puffs_framebuf *);
uint64_t puffs__nextreq(struct puffs_usermount *pu);

View File

@ -1,4 +1,4 @@
/* $NetBSD: requests.c,v 1.20 2007/12/05 11:06:05 pooka Exp $ */
/* $NetBSD: requests.c,v 1.21 2008/01/28 18:35:51 pooka Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
@ -30,7 +30,7 @@
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: requests.c,v 1.20 2007/12/05 11:06:05 pooka Exp $");
__RCSID("$NetBSD: requests.c,v 1.21 2008/01/28 18:35:51 pooka Exp $");
#endif /* !lint */
#include <sys/types.h>
@ -56,7 +56,7 @@ __RCSID("$NetBSD: requests.c,v 1.20 2007/12/05 11:06:05 pooka Exp $");
*/
/*ARGSUSED*/
int
puffs_fsframe_read(struct puffs_usermount *pu, struct puffs_framebuf *pb,
puffs__fsframe_read(struct puffs_usermount *pu, struct puffs_framebuf *pb,
int fd, int *done)
{
struct putter_hdr phdr;
@ -117,7 +117,7 @@ puffs_fsframe_read(struct puffs_usermount *pu, struct puffs_framebuf *pb,
*/
/*ARGSUSED*/
int
puffs_fsframe_write(struct puffs_usermount *pu, struct puffs_framebuf *pb,
puffs__fsframe_write(struct puffs_usermount *pu, struct puffs_framebuf *pb,
int fd, int *done)
{
void *win;
@ -200,7 +200,7 @@ puffs_fsframe_write(struct puffs_usermount *pu, struct puffs_framebuf *pb,
*/
/*ARGSUSED*/
int
puffs_fsframe_cmp(struct puffs_usermount *pu,
puffs__fsframe_cmp(struct puffs_usermount *pu,
struct puffs_framebuf *pb1, struct puffs_framebuf *pb2, int *notresp)
{
struct puffs_req *preq1, *preq2;
@ -233,7 +233,7 @@ puffs_fsframe_cmp(struct puffs_usermount *pu,
}
void
puffs_fsframe_gotframe(struct puffs_usermount *pu, struct puffs_framebuf *pb)
puffs__fsframe_gotframe(struct puffs_usermount *pu, struct puffs_framebuf *pb)
{
struct puffs_framebuf *newpb;
@ -245,5 +245,5 @@ puffs_fsframe_gotframe(struct puffs_usermount *pu, struct puffs_framebuf *pb)
if (puffs_framebuf_reserve_space(newpb, PUFFS_MSG_MAXSIZE) == -1)
abort();
puffs_dopufbuf(pu, newpb);
puffs__ml_dispatch(pu, newpb);
}