summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorpooka <pooka@NetBSD.org>2008-01-28 18:35:49 +0000
committerpooka <pooka@NetBSD.org>2008-01-28 18:35:49 +0000
commitd1d05d65b94de0b1c74d001d0f98e05b646d538f (patch)
tree7dd80f18258298311bb60954621b95a3c4a2b673 /lib
parentf3b8aacb17bf459faf28a2822562269980f4be59 (diff)
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/libpuffs/callcontext.c255
-rw-r--r--lib/libpuffs/dispatcher.c316
-rw-r--r--lib/libpuffs/framebuf.c32
-rw-r--r--lib/libpuffs/puffs.349
-rw-r--r--lib/libpuffs/puffs.c139
-rw-r--r--lib/libpuffs/puffs.h10
-rw-r--r--lib/libpuffs/puffs_cc.335
-rw-r--r--lib/libpuffs/puffs_priv.h96
-rw-r--r--lib/libpuffs/requests.c14
9 files changed, 418 insertions, 528 deletions
diff --git a/lib/libpuffs/callcontext.c b/lib/libpuffs/callcontext.c
index e3f7db48c84..7aa4a719ce5 100644
--- a/lib/libpuffs/callcontext.c
+++ b/lib/libpuffs/callcontext.c
@@ -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>
@@ -48,28 +48,74 @@ __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_continue(struct puffs_cc *pcc)
+puffs__cc_cont(struct puffs_cc *pcc)
{
+ struct puffs_cc *mycc;
- assert(pcc->pcc_flags & PCC_REALCC);
+ 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)
+{
/* 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
-
- /* Do we have a cached copy? */
- if (pu->pu_cc_nstored) {
- 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;
+ if (puffs_fakecc)
+ return &fakecc;
- pcc = sp;
- mprotect((uint8_t *)sp + psize, (size_t)psize, PROT_NONE);
- }
+ 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));
- pcc->pcc_pu = pu;
- /* Not a real cc? Don't need to init more */
- if (type != PCC_REALCC)
- goto out;
+ mprotect((uint8_t *)sp + psize, (size_t)psize, PROT_NONE);
/* initialize both ucontext's */
if (getcontext(&pcc->pcc_uc) == -1) {
munmap(pcc, stacksize);
- return -1;
+ return NULL;
}
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);
+ return NULL;
}
-#endif
- finalize:
- assert(pcc->pcc_pu == pu);
+ return pcc;
+}
- /* return here. it won't actually be "here" due to swapcontext() */
- pcc->pcc_uc.uc_link = &pcc->pcc_uc_ret;
+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;
- /* 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;
+ /* Do we have a cached copy? */
+ 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);
- /*
- * 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);
+ LIST_REMOVE(pcc, pcc_rope);
+ pu->pu_cc_nstored--;
+ }
+ assert(pcc->pcc_pu == pu);
- out:
- pcc->pcc_pb = pb;
- pcc->pcc_flags = type;
+ 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;
+
+ /*
+ * 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;
diff --git a/lib/libpuffs/dispatcher.c b/lib/libpuffs/dispatcher.c
index 445f1424562..5fec61d4cb8 100644
--- a/lib/libpuffs/dispatcher.c
+++ b/lib/libpuffs/dispatcher.c
@@ -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;
-
-static int
-dopufbuf2(struct puffs_usermount *pu, struct puffs_framebuf *pb)
-{
- struct puffs_req *preq = puffs__framebuf_getdataptr(pb);
- struct puffs_cc *pcc;
- int type;
-
- if (puffs_fakecc) {
- type = PCC_FAKECC;
- } else if (puffs_usethreads) {
- type = PCC_THREADED;
-#ifndef PUFFS_WITH_THREADS
- type = PCC_FAKECC;
#endif
- } else {
- type = PCC_REALCC;
- }
- if (puffs_cc_create(pu, pb, type, &pcc) == -1)
- return errno;
+static void dispatch(struct puffs_cc *);
- 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;
+/* for our eyes only */
+void
+puffs__ml_dispatch(struct puffs_usermount *pu, struct puffs_framebuf *pb)
+{
+ struct puffs_cc *pcc = puffs_cc_getcc(pu);
+ struct puffs_req *preq;
- pthread_attr_init(&pattr);
- pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
- pthread_attr_destroy(&pattr);
+ pcc->pcc_pb = pb;
+ pcc->pcc_flags |= PCC_MLCONT;
+ dispatch(pcc);
- ap->pwa_pcc = 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);
- rv = pthread_create(&ptid, &pattr, puffs_docc, pcc);
+ puffs_framev_enqueue_justsend(pu, pu->pu_fd,
+ pcc->pcc_pb, 0, 0);
+ } else {
+ puffs_framebuf_destroy(pcc->pcc_pb);
+ }
- 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);
- return 0;
+ pcc->pcc_flags = 0;
}
-/*
- * User-visible point to handle a request from.
- *
- * <insert text here>
- */
+/* public, but not really tested and only semi-supported */
int
-puffs_dopufbuf(struct puffs_usermount *pu, struct puffs_framebuf *pb)
+puffs_dispatch_create(struct puffs_usermount *pu, struct puffs_framebuf *pb,
+ struct puffs_cc **pccp)
{
- struct puffs_req *preq = puffs__framebuf_getdataptr(pb);
-
- /*
- * 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;
-
- 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;
+ struct puffs_cc *pcc;
- pu->pu_errnotify(pu, preq->preq_optype,
- perr->perr_error, perr->perr_str, preq->preq_cookie);
- return 0;
- }
+ if (puffs__cc_create(pu, dispatch, &pcc) == -1)
+ return -1;
- if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
- puffsdump_req(preq);
+ pcc->pcc_pb = pb;
+ *pccp = pcc;
-#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 0;
}
-enum {PUFFCALL_ANSWER, PUFFCALL_IGNORE, PUFFCALL_AGAIN};
-
-void *
-puffs_docc(void *arg)
+int
+puffs_dispatch_exec(struct puffs_cc *pcc, struct puffs_framebuf **pbp)
{
- 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);
+ int rv;
- 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);
+ puffs_cc_continue(pcc);
- /* 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);
+ if (pcc->pcc_flags & PCC_DONE) {
+ rv = 1;
+ *pbp = pcc->pcc_pb;
+ pcc->pcc_flags = 0;
+ puffs__cc_destroy(pcc, 0);
+ } else {
+ rv = 0;
}
- PU_UNLOCK();
- return NULL;
+ return rv;
}
-/* 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;
-
- assert(pcc->pcc_flags & (PCC_FAKECC | PCC_REALCC | PCC_THREADED));
- assert(pcc == puffs_cc_getcc(pu)); /* remove me soon */
+ int error, buildpath;
- 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;
}
diff --git a/lib/libpuffs/framebuf.c b/lib/libpuffs/framebuf.c
index c4906fb8bb8..6007b6fc4b5 100644
--- a/lib/libpuffs/framebuf.c
+++ b/lib/libpuffs/framebuf.c
@@ -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;
diff --git a/lib/libpuffs/puffs.3 b/lib/libpuffs/puffs.3
index d28b0f17c11..4b0948c1e43 100644
--- a/lib/libpuffs/puffs.3
+++ b/lib/libpuffs/puffs.3
@@ -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
diff --git a/lib/libpuffs/puffs.c b/lib/libpuffs/puffs.c
index c7666cb3897..34d49fa4a81 100644
--- a/lib/libpuffs/puffs.c
+++ b/lib/libpuffs/puffs.c
@@ -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;
diff --git a/lib/libpuffs/puffs.h b/lib/libpuffs/puffs.h
index 99922f76fbe..53eef7a6a64 100644
--- a/lib/libpuffs/puffs.h
+++ b/lib/libpuffs/puffs.h
@@ -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
diff --git a/lib/libpuffs/puffs_cc.3 b/lib/libpuffs/puffs_cc.3
index 4645584a75e..ade2461b6d7 100644
--- a/lib/libpuffs/puffs_cc.3
+++ b/lib/libpuffs/puffs_cc.3
@@ -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
diff --git a/lib/libpuffs/puffs_priv.h b/lib/libpuffs/puffs_priv.h
index d2db6733c48..2e1cb74e33c 100644
--- a/lib/libpuffs/puffs_priv.h
+++ b/lib/libpuffs/puffs_priv.h
@@ -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 *);
-
-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 *);
+void puffs__theloop(struct puffs_cc *);
+void puffs__ml_dispatch(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);
diff --git a/lib/libpuffs/requests.c b/lib/libpuffs/requests.c
index e3c75aaac68..8b124db178b 100644
--- a/lib/libpuffs/requests.c
+++ b/lib/libpuffs/requests.c
@@ -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);
}