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:
parent
f3b8aacb17
commit
d1d05d65b9
@ -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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -27,7 +30,7 @@
|
|||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#if !defined(lint)
|
#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 */
|
#endif /* !lint */
|
||||||
|
|
||||||
#include <sys/types.h>
|
#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 <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#ifdef PUFFS_WITH_THREADS
|
|
||||||
#include <pthread.h>
|
|
||||||
#endif
|
|
||||||
#include <puffs.h>
|
#include <puffs.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.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"
|
#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
|
* 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
|
void
|
||||||
puffs_cc_yield(struct puffs_cc *pcc)
|
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;
|
pcc->pcc_flags &= ~PCC_BORROWED;
|
||||||
|
|
||||||
/* romanes eunt domus */
|
/* 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
|
void
|
||||||
puffs_cc_continue(struct puffs_cc *pcc)
|
puffs_cc_continue(struct puffs_cc *pcc)
|
||||||
{
|
{
|
||||||
|
|
||||||
assert(pcc->pcc_flags & PCC_REALCC);
|
|
||||||
|
|
||||||
/* ramble on */
|
/* 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).
|
* yield again).
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
puffs_goto(struct puffs_cc *loanpcc)
|
puffs__goto(struct puffs_cc *loanpcc)
|
||||||
{
|
{
|
||||||
|
|
||||||
assert(loanpcc->pcc_flags & PCC_REALCC);
|
|
||||||
loanpcc->pcc_flags |= PCC_BORROWED;
|
loanpcc->pcc_flags |= PCC_BORROWED;
|
||||||
|
|
||||||
swapcontext(&loanpcc->pcc_uc_ret, &loanpcc->pcc_uc);
|
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;
|
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;
|
static struct puffs_cc fakecc;
|
||||||
|
|
||||||
int
|
static struct puffs_cc *
|
||||||
puffs_cc_create(struct puffs_usermount *pu, struct puffs_framebuf *pb,
|
slowccalloc(struct puffs_usermount *pu)
|
||||||
int type, struct puffs_cc **pccp)
|
|
||||||
{
|
{
|
||||||
struct puffs_cc *volatile pcc;
|
struct puffs_cc *volatile pcc;
|
||||||
|
void *sp;
|
||||||
size_t stacksize = 1<<pu->pu_cc_stackshift;
|
size_t stacksize = 1<<pu->pu_cc_stackshift;
|
||||||
long psize = sysconf(_SC_PAGESIZE);
|
long psize = sysconf(_SC_PAGESIZE);
|
||||||
stack_t *st;
|
|
||||||
void *volatile sp;
|
|
||||||
|
|
||||||
#ifdef PUFFS_WITH_THREADS
|
if (puffs_fakecc)
|
||||||
extern size_t pthread__stacksize;
|
return &fakecc;
|
||||||
stacksize = pthread__stacksize;
|
|
||||||
#endif
|
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? */
|
/* 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);
|
pcc = LIST_FIRST(&pu->pu_ccmagazin);
|
||||||
assert(pcc != NULL);
|
assert(pcc != NULL);
|
||||||
|
|
||||||
LIST_REMOVE(pcc, pcc_rope);
|
LIST_REMOVE(pcc, pcc_rope);
|
||||||
pu->pu_cc_nstored--;
|
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);
|
assert(pcc->pcc_pu == pu);
|
||||||
|
|
||||||
/* return here. it won't actually be "here" due to swapcontext() */
|
if (puffs_fakecc) {
|
||||||
pcc->pcc_uc.uc_link = &pcc->pcc_uc_ret;
|
pcc->pcc_func = func;
|
||||||
|
pcc->pcc_farg = pcc;
|
||||||
|
} else {
|
||||||
|
/* link context */
|
||||||
|
pcc->pcc_uc.uc_link = &pcc->pcc_uc_ret;
|
||||||
|
|
||||||
/* setup stack
|
/* setup stack
|
||||||
*
|
*
|
||||||
* XXX: I guess this should theoretically be preserved by
|
* XXX: I guess this should theoretically be preserved by
|
||||||
* swapcontext(). However, it gets lost. So reinit it.
|
* swapcontext(). However, it gets lost. So reinit it.
|
||||||
*/
|
*/
|
||||||
st = &pcc->pcc_uc.uc_stack;
|
st = &pcc->pcc_uc.uc_stack;
|
||||||
st->ss_sp = pcc;
|
st->ss_sp = pcc;
|
||||||
st->ss_size = stacksize;
|
st->ss_size = stacksize;
|
||||||
st->ss_flags = 0;
|
st->ss_flags = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Give us an initial context to jump to.
|
* Give us an initial context to jump to.
|
||||||
*
|
*
|
||||||
* XXX: Our manual page says that portable code shouldn't rely on
|
* Our manual page says that portable code shouldn't
|
||||||
* being able to pass pointers through makecontext(). kjk says
|
* rely on being able to pass pointers through makecontext().
|
||||||
* that NetBSD code doesn't need to worry about this. uwe says
|
* kjk says that NetBSD code doesn't need to worry about this.
|
||||||
* it would be like putting a "keep away from children" sign on a
|
* uwe says it would be like putting a "keep away from
|
||||||
* box of toys.
|
* children" sign on a box of toys.
|
||||||
*/
|
*/
|
||||||
makecontext(&pcc->pcc_uc, (void *)puffs_calldispatcher,
|
makecontext(&pcc->pcc_uc, (void *)func, 1, (uintptr_t)pcc);
|
||||||
1, (uintptr_t)pcc);
|
}
|
||||||
|
|
||||||
out:
|
|
||||||
pcc->pcc_pb = pb;
|
|
||||||
pcc->pcc_flags = type;
|
|
||||||
|
|
||||||
*pccp = pcc;
|
*pccp = pcc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
pcc->pcc_pid = pid;
|
||||||
@ -242,44 +261,32 @@ puffs_cc_setcaller(struct puffs_cc *pcc, pid_t pid, lwpid_t lid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
puffs_cc_destroy(struct puffs_cc *pcc)
|
puffs__cc_destroy(struct puffs_cc *pcc, int nonuke)
|
||||||
{
|
{
|
||||||
struct puffs_usermount *pu = pcc->pcc_pu;
|
struct puffs_usermount *pu = pcc->pcc_pu;
|
||||||
size_t stacksize = 1<<pu->pu_cc_stackshift;
|
size_t stacksize = 1<<pu->pu_cc_stackshift;
|
||||||
|
|
||||||
/* not over limit? stuff away in the store */
|
assert(pcc->pcc_flags = 0);
|
||||||
if (pu->pu_cc_nstored < PUFFS_CCMAXSTORE
|
|
||||||
&& pcc->pcc_flags & PCC_REALCC) {
|
/* not over limit? stuff away in the store, otherwise nuke */
|
||||||
pcc->pcc_flags &= ~PCC_DONE;
|
if (nonuke || pu->pu_cc_nstored < PUFFS_CCMAXSTORE) {
|
||||||
|
pcc->pcc_pb = NULL;
|
||||||
LIST_INSERT_HEAD(&pu->pu_ccmagazin, pcc, pcc_rope);
|
LIST_INSERT_HEAD(&pu->pu_ccmagazin, pcc, pcc_rope);
|
||||||
pu->pu_cc_nstored++;
|
pu->pu_cc_nstored++;
|
||||||
return;
|
} else {
|
||||||
}
|
assert(!puffs_fakecc);
|
||||||
|
|
||||||
/* else: just dump it */
|
|
||||||
|
|
||||||
#ifdef PUFFS_WITH_THREADS
|
|
||||||
extern size_t pthread__stacksize;
|
|
||||||
stacksize = pthread__stacksize;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((pcc->pcc_flags & PCC_FAKECC) == 0)
|
|
||||||
munmap(pcc, stacksize);
|
munmap(pcc, stacksize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct puffs_cc *
|
struct puffs_cc *
|
||||||
puffs_cc_getcc(struct puffs_usermount *pu)
|
puffs_cc_getcc(struct puffs_usermount *pu)
|
||||||
{
|
{
|
||||||
extern int puffs_fakecc, puffs_usethreads;
|
|
||||||
size_t stacksize = 1<<pu->pu_cc_stackshift;
|
size_t stacksize = 1<<pu->pu_cc_stackshift;
|
||||||
uintptr_t bottom;
|
uintptr_t bottom;
|
||||||
|
|
||||||
if (puffs_fakecc)
|
if (puffs_fakecc)
|
||||||
return &fakecc;
|
return &fakecc;
|
||||||
#ifndef PUFFS_WITH_THREADS
|
|
||||||
if (puffs_usethreads)
|
|
||||||
return &fakecc;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bottom = ((uintptr_t)&bottom) & ~(stacksize-1);
|
bottom = ((uintptr_t)&bottom) & ~(stacksize-1);
|
||||||
return (struct puffs_cc *)bottom;
|
return (struct puffs_cc *)bottom;
|
||||||
|
@ -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
|
* 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -30,7 +31,7 @@
|
|||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#if !defined(lint)
|
#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 */
|
#endif /* !lint */
|
||||||
|
|
||||||
#include <sys/types.h>
|
#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"
|
#include "puffs_priv.h"
|
||||||
|
|
||||||
static void processresult(struct puffs_usermount *, int);
|
#if 0 /* me not worka now */
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the following to 1 to handle each request in a separate pthread.
|
* 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
|
* This is not exported as it should not be used yet unless having a
|
||||||
@ -65,219 +58,100 @@ int puffs_fakecc;
|
|||||||
* threadsafe).
|
* threadsafe).
|
||||||
*/
|
*/
|
||||||
int puffs_usethreads;
|
int puffs_usethreads;
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static void dispatch(struct puffs_cc *);
|
||||||
dopufbuf2(struct puffs_usermount *pu, struct puffs_framebuf *pb)
|
|
||||||
|
/* 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 = puffs_cc_getcc(pu);
|
||||||
struct puffs_cc *pcc;
|
struct puffs_req *preq;
|
||||||
int type;
|
|
||||||
|
|
||||||
if (puffs_fakecc) {
|
pcc->pcc_pb = pb;
|
||||||
type = PCC_FAKECC;
|
pcc->pcc_flags |= PCC_MLCONT;
|
||||||
} else if (puffs_usethreads) {
|
dispatch(pcc);
|
||||||
type = PCC_THREADED;
|
|
||||||
#ifndef PUFFS_WITH_THREADS
|
/* Put result to kernel sendqueue if necessary */
|
||||||
type = PCC_FAKECC;
|
preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
|
||||||
#endif
|
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 {
|
} else {
|
||||||
type = PCC_REALCC;
|
puffs_framebuf_destroy(pcc->pcc_pb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (puffs_cc_create(pu, pb, type, &pcc) == -1)
|
/* who needs information when you're living on borrowed time? */
|
||||||
return errno;
|
if (pcc->pcc_flags & PCC_BORROWED) {
|
||||||
|
puffs_cc_yield(pcc); /* back to borrow source */
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
#endif
|
pcc->pcc_flags = 0;
|
||||||
puffs_docc(pcc);
|
}
|
||||||
|
|
||||||
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* User-visible point to handle a request from.
|
|
||||||
*
|
|
||||||
* <insert text here>
|
|
||||||
*/
|
|
||||||
int
|
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;
|
||||||
|
|
||||||
/*
|
puffs_cc_continue(pcc);
|
||||||
* 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)
|
if (pcc->pcc_flags & PCC_DONE) {
|
||||||
return 0;
|
rv = 1;
|
||||||
|
*pbp = pcc->pcc_pb;
|
||||||
pu->pu_ops.puffs_cache_write(pu, preq->preq_cookie,
|
pcc->pcc_flags = 0;
|
||||||
pci->pcache_nruns, pci->pcache_runs);
|
puffs__cc_destroy(pcc, 0);
|
||||||
return 0;
|
} else {
|
||||||
} else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_ERROR) {
|
rv = 0;
|
||||||
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 (pu->pu_flags & PUFFS_FLAG_OPDUMP)
|
return rv;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {PUFFCALL_ANSWER, PUFFCALL_IGNORE, PUFFCALL_AGAIN};
|
static void
|
||||||
|
dispatch(struct puffs_cc *pcc)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
struct puffs_usermount *pu = pcc->pcc_pu;
|
struct puffs_usermount *pu = pcc->pcc_pu;
|
||||||
struct puffs_ops *pops = &pu->pu_ops;
|
struct puffs_ops *pops = &pu->pu_ops;
|
||||||
struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
|
struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
|
||||||
void *auxbuf = preq; /* help with typecasting */
|
void *auxbuf = preq; /* help with typecasting */
|
||||||
void *opcookie = preq->preq_cookie;
|
void *opcookie = preq->preq_cookie;
|
||||||
int error, rv, buildpath;
|
int error, buildpath;
|
||||||
|
|
||||||
assert(pcc->pcc_flags & (PCC_FAKECC | PCC_REALCC | PCC_THREADED));
|
assert((pcc->pcc_flags & PCC_DONE) == 0);
|
||||||
assert(pcc == puffs_cc_getcc(pu)); /* remove me soon */
|
|
||||||
|
|
||||||
if (PUFFSOP_WANTREPLY(preq->preq_opclass))
|
|
||||||
rv = PUFFCALL_ANSWER;
|
|
||||||
else
|
|
||||||
rv = PUFFCALL_IGNORE;
|
|
||||||
|
|
||||||
buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH;
|
buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH;
|
||||||
preq->preq_setbacks = 0;
|
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)
|
if (pu->pu_oppre)
|
||||||
pu->pu_oppre(pu);
|
pu->pu_oppre(pu);
|
||||||
|
|
||||||
|
/* Execute actual operation */
|
||||||
if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) {
|
if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) {
|
||||||
switch (preq->preq_optype) {
|
switch (preq->preq_optype) {
|
||||||
case PUFFS_VFS_UNMOUNT:
|
case PUFFS_VFS_UNMOUNT:
|
||||||
@ -1003,62 +877,32 @@ puffs_calldispatcher(struct puffs_cc *pcc)
|
|||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
break;
|
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 {
|
} else {
|
||||||
/*
|
/*
|
||||||
* this one also
|
* I guess the kernel sees this one coming also
|
||||||
*/
|
*/
|
||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
preq->preq_rv = error;
|
preq->preq_rv = error;
|
||||||
pcc->pcc_flags |= PCC_DONE;
|
|
||||||
|
|
||||||
if (pu->pu_oppost)
|
if (pu->pu_oppost)
|
||||||
pu->pu_oppost(pu);
|
pu->pu_oppost(pu);
|
||||||
|
|
||||||
/*
|
pcc->pcc_flags |= PCC_DONE;
|
||||||
* 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 */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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.
|
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
|
||||||
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#if !defined(lint)
|
#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 */
|
#endif /* !lint */
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -328,7 +328,7 @@ errnotify(struct puffs_usermount *pu, struct puffs_framebuf *pufbuf, int error)
|
|||||||
|
|
||||||
pufbuf->rv = error;
|
pufbuf->rv = error;
|
||||||
if (pufbuf->pcc) {
|
if (pufbuf->pcc) {
|
||||||
puffs_goto(pufbuf->pcc);
|
puffs__goto(pufbuf->pcc);
|
||||||
} else if (pufbuf->fcb) {
|
} else if (pufbuf->fcb) {
|
||||||
pufbuf->istat &= ~ISTAT_NODESTROY;
|
pufbuf->istat &= ~ISTAT_NODESTROY;
|
||||||
pufbuf->fcb(pu, pufbuf, pufbuf->fcb_arg, error);
|
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
|
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;
|
struct puffs_fbevent *fbevp;
|
||||||
|
|
||||||
@ -652,7 +652,7 @@ puffs__framebuf_moveinfo(struct puffs_framebuf *from, struct puffs_framebuf *to)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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_fctrl_io *fio)
|
||||||
{
|
{
|
||||||
struct puffs_framebuf *pufbuf, *appbuf;
|
struct puffs_framebuf *pufbuf, *appbuf;
|
||||||
@ -672,7 +672,7 @@ puffs_framev_input(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
|
|||||||
|
|
||||||
/* error */
|
/* error */
|
||||||
if (rv) {
|
if (rv) {
|
||||||
puffs_framev_readclose(pu, fio, rv);
|
puffs__framev_readclose(pu, fio, rv);
|
||||||
fio->cur_in = NULL;
|
fio->cur_in = NULL;
|
||||||
if ((pufbuf->istat & ISTAT_DIRECT) == 0) {
|
if ((pufbuf->istat & ISTAT_DIRECT) == 0) {
|
||||||
assert((pufbuf->istat & ISTAT_NODESTROY) == 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;
|
appbuf->istat &= ~ISTAT_NODESTROY;
|
||||||
|
|
||||||
if (appbuf->pcc) {
|
if (appbuf->pcc) {
|
||||||
puffs_docc(appbuf->pcc);
|
puffs__cc_cont(appbuf->pcc);
|
||||||
} else if (appbuf->fcb) {
|
} else if (appbuf->fcb) {
|
||||||
appbuf->fcb(pu, appbuf, appbuf->fcb_arg, 0);
|
appbuf->fcb(pu, appbuf, appbuf->fcb_arg, 0);
|
||||||
} else {
|
} else {
|
||||||
@ -724,7 +724,7 @@ puffs_framev_input(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
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_fctrl_io *fio)
|
||||||
{
|
{
|
||||||
struct puffs_framebuf *pufbuf;
|
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);
|
rv = fctrl->wfb(pu, pufbuf, fio->io_fd, &complete);
|
||||||
|
|
||||||
if (rv) {
|
if (rv) {
|
||||||
puffs_framev_writeclose(pu, fio, rv);
|
puffs__framev_writeclose(pu, fio, rv);
|
||||||
done = 1;
|
done = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -758,8 +758,8 @@ puffs_framev_output(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
|
|||||||
done = 1;
|
done = 1;
|
||||||
} else if ((pufbuf->istat & ISTAT_DIRECT)) {
|
} else if ((pufbuf->istat & ISTAT_DIRECT)) {
|
||||||
pufbuf->istat &= ~ISTAT_NODESTROY;
|
pufbuf->istat &= ~ISTAT_NODESTROY;
|
||||||
puffs_docc(pufbuf->pcc);
|
|
||||||
done = 1;
|
done = 1;
|
||||||
|
puffs__cc_cont(pufbuf->pcc);
|
||||||
} else if ((pufbuf->istat & ISTAT_NOREPLY) == 0) {
|
} else if ((pufbuf->istat & ISTAT_NOREPLY) == 0) {
|
||||||
TAILQ_INSERT_TAIL(&fio->res_qing, pufbuf,
|
TAILQ_INSERT_TAIL(&fio->res_qing, pufbuf,
|
||||||
pfb_entries);
|
pfb_entries);
|
||||||
@ -915,7 +915,7 @@ puffs_framev_disablefd(struct puffs_usermount *pu, int fd, int what)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
puffs_framev_readclose(struct puffs_usermount *pu,
|
puffs__framev_readclose(struct puffs_usermount *pu,
|
||||||
struct puffs_fctrl_io *fio, int error)
|
struct puffs_fctrl_io *fio, int error)
|
||||||
{
|
{
|
||||||
struct puffs_framebuf *pufbuf;
|
struct puffs_framebuf *pufbuf;
|
||||||
@ -952,7 +952,7 @@ puffs_framev_readclose(struct puffs_usermount *pu,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
puffs_framev_writeclose(struct puffs_usermount *pu,
|
puffs__framev_writeclose(struct puffs_usermount *pu,
|
||||||
struct puffs_fctrl_io *fio, int error)
|
struct puffs_fctrl_io *fio, int error)
|
||||||
{
|
{
|
||||||
struct puffs_framebuf *pufbuf;
|
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);
|
LIST_REMOVE(fio, fio_entries);
|
||||||
if (pu->pu_state & PU_INLOOP) {
|
if (pu->pu_state & PU_INLOOP) {
|
||||||
puffs_framev_readclose(pu, fio, error);
|
puffs__framev_readclose(pu, fio, error);
|
||||||
puffs_framev_writeclose(pu, fio, error);
|
puffs__framev_writeclose(pu, fio, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((fbevp = LIST_FIRST(&fio->ev_qing)) != NULL) {
|
while ((fbevp = LIST_FIRST(&fio->ev_qing)) != NULL) {
|
||||||
fbevp->rv = error;
|
fbevp->rv = error;
|
||||||
LIST_REMOVE(fbevp, pfe_entries);
|
LIST_REMOVE(fbevp, pfe_entries);
|
||||||
puffs_goto(fbevp->pcc);
|
puffs__goto(fbevp->pcc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't bother with realloc */
|
/* don't bother with realloc */
|
||||||
@ -1056,7 +1056,7 @@ puffs_framev_init(struct puffs_usermount *pu,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
puffs_framev_exit(struct puffs_usermount *pu)
|
puffs__framev_exit(struct puffs_usermount *pu)
|
||||||
{
|
{
|
||||||
struct puffs_fctrl_io *fio;
|
struct puffs_fctrl_io *fio;
|
||||||
|
|
||||||
|
@ -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.
|
.\" 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
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd January 14, 2008
|
.Dd January 28, 2008
|
||||||
.Dt PUFFS 3
|
.Dt PUFFS 3
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -80,7 +80,12 @@
|
|||||||
.Ft int
|
.Ft int
|
||||||
.Fn puffs_mainloop "struct puffs_usermount *pu"
|
.Fn puffs_mainloop "struct puffs_usermount *pu"
|
||||||
.Ft int
|
.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
|
.Sh DESCRIPTION
|
||||||
.Em IMPORTANT NOTE!
|
.Em IMPORTANT NOTE!
|
||||||
This document describes interfaces which are not yet guaranteed to be
|
This document describes interfaces which are not yet guaranteed to be
|
||||||
@ -434,13 +439,39 @@ In case
|
|||||||
.Xr puffs_framebuf 3
|
.Xr puffs_framebuf 3
|
||||||
has been initialized, I/O from the relevant descriptors is processed
|
has been initialized, I/O from the relevant descriptors is processed
|
||||||
automatically by the eventloop.
|
automatically by the eventloop.
|
||||||
.It Fn puffs_dopufbuf pu pb
|
.It Fn puffs_dispatch_create pu pb pccp
|
||||||
Decode and dispatch the file system request in
|
.It Fn puffs_dispatch_exec pcc pbp
|
||||||
.Ar pb .
|
In case the use of
|
||||||
The contents 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
|
.Ar pb
|
||||||
must be of type
|
should contains a valid request and upon success
|
||||||
.Vt "struct puffs_req" .
|
.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
|
.El
|
||||||
.Ss Cookies
|
.Ss Cookies
|
||||||
Every file (regular file, directory, device node, ...) instance is
|
Every file (regular file, directory, device node, ...) instance is
|
||||||
|
@ -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.
|
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
|
||||||
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#if !defined(lint)
|
#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 */
|
#endif /* !lint */
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
@ -115,7 +115,7 @@ finalpush(struct puffs_usermount *pu)
|
|||||||
if (fio->stat & FIO_WRGONE)
|
if (fio->stat & FIO_WRGONE)
|
||||||
continue;
|
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);
|
||||||
LIST_INIT(&pu->pu_ios_rmlist);
|
LIST_INIT(&pu->pu_ios_rmlist);
|
||||||
LIST_INIT(&pu->pu_ccmagazin);
|
LIST_INIT(&pu->pu_ccmagazin);
|
||||||
LIST_INIT(&pu->pu_ccnukelst);
|
|
||||||
TAILQ_INIT(&pu->pu_sched);
|
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].rfb = puffs__fsframe_read;
|
||||||
pu->pu_framectrl[PU_FRAMECTRL_FS].wfb = puffs_fsframe_write;
|
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].cmpfb = puffs__fsframe_cmp;
|
||||||
pu->pu_framectrl[PU_FRAMECTRL_FS].gotfb = puffs_fsframe_gotframe;
|
pu->pu_framectrl[PU_FRAMECTRL_FS].gotfb = puffs__fsframe_gotframe;
|
||||||
pu->pu_framectrl[PU_FRAMECTRL_FS].fdnotfn = puffs_framev_unmountonclose;
|
pu->pu_framectrl[PU_FRAMECTRL_FS].fdnotfn = puffs_framev_unmountonclose;
|
||||||
|
|
||||||
/* defaults for some user-settable translation functions */
|
/* defaults for some user-settable translation functions */
|
||||||
@ -672,7 +670,7 @@ puffs_exit(struct puffs_usermount *pu, int force)
|
|||||||
puffs_pn_put(pn);
|
puffs_pn_put(pn);
|
||||||
|
|
||||||
finalpush(pu);
|
finalpush(pu);
|
||||||
puffs_framev_exit(pu);
|
puffs__framev_exit(pu);
|
||||||
if (pu->pu_state & PU_HASKQ)
|
if (pu->pu_state & PU_HASKQ)
|
||||||
close(pu->pu_kq);
|
close(pu->pu_kq);
|
||||||
free(pu);
|
free(pu);
|
||||||
@ -680,48 +678,30 @@ puffs_exit(struct puffs_usermount *pu, int force)
|
|||||||
return 0; /* always succesful for now, WILL CHANGE */
|
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_framectrl *pfctrl;
|
||||||
struct puffs_fctrl_io *fio;
|
struct puffs_fctrl_io *fio;
|
||||||
struct puffs_cc *pcc;
|
|
||||||
struct kevent *curev;
|
struct kevent *curev;
|
||||||
size_t nchanges;
|
size_t nchanges;
|
||||||
int ndone, sverrno;
|
int ndone;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
while (puffs_getstate(pu) != PUFFS_STATE_UNMOUNTED) {
|
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)
|
if (pu->pu_ml_lfn)
|
||||||
pu->pu_ml_lfn(pu);
|
pu->pu_ml_lfn(pu);
|
||||||
|
|
||||||
@ -759,7 +739,7 @@ puffs_mainloop(struct puffs_usermount *pu)
|
|||||||
* case is that we can fit everything into the
|
* case is that we can fit everything into the
|
||||||
* socket buffer.
|
* 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 (ndone == -1) {
|
||||||
if (errno != EINTR)
|
if (errno != EINTR)
|
||||||
goto out;
|
break;
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -823,32 +803,24 @@ puffs_mainloop(struct puffs_usermount *pu)
|
|||||||
fio->stat &= ~FIO_WR;
|
fio->stat &= ~FIO_WR;
|
||||||
|
|
||||||
/* XXX: how to know if it's a transient error */
|
/* XXX: how to know if it's a transient error */
|
||||||
puffs_framev_writeclose(pu, fio,
|
puffs__framev_writeclose(pu, fio,
|
||||||
(int)curev->data);
|
(int)curev->data);
|
||||||
puffs_framev_notify(fio, PUFFS_FBIO_ERROR);
|
puffs__framev_notify(fio, PUFFS_FBIO_ERROR);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
what = 0;
|
what = 0;
|
||||||
if (curev->filter == EVFILT_READ) {
|
if (curev->filter == EVFILT_READ) {
|
||||||
puffs_framev_input(pu, pfctrl, fio);
|
puffs__framev_input(pu, pfctrl, fio);
|
||||||
what |= PUFFS_FBIO_READ;
|
what |= PUFFS_FBIO_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (curev->filter == EVFILT_WRITE) {
|
else if (curev->filter == EVFILT_WRITE) {
|
||||||
puffs_framev_output(pu, pfctrl, fio);
|
puffs__framev_output(pu, pfctrl, fio);
|
||||||
what |= PUFFS_FBIO_WRITE;
|
what |= PUFFS_FBIO_WRITE;
|
||||||
}
|
}
|
||||||
if (what)
|
if (what)
|
||||||
puffs_framev_notify(fio, 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -860,6 +832,53 @@ puffs_mainloop(struct puffs_usermount *pu)
|
|||||||
free(fio);
|
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);
|
finalpush(pu);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
|
@ -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.
|
* 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 *);
|
void puffs_null_setops(struct puffs_ops *);
|
||||||
|
|
||||||
int puffs_dopufbuf(struct puffs_usermount *,
|
int puffs_dispatch_create(struct puffs_usermount *,
|
||||||
struct puffs_framebuf *);
|
struct puffs_framebuf *,
|
||||||
|
struct puffs_cc **);
|
||||||
|
int puffs_dispatch_exec(struct puffs_cc *,
|
||||||
|
struct puffs_framebuf **);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* generic/dummy routines applicable for some file systems
|
* 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 *);
|
void puffs_cc_schedule(struct puffs_cc *);
|
||||||
int puffs_cc_getcaller(struct puffs_cc *,pid_t *,lwpid_t *);
|
int puffs_cc_getcaller(struct puffs_cc *,pid_t *,lwpid_t *);
|
||||||
struct puffs_cc *puffs_cc_getcc(struct puffs_usermount *);
|
struct puffs_cc *puffs_cc_getcc(struct puffs_usermount *);
|
||||||
void *puffs_docc(void *);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flushing / invalidation routines
|
* Flushing / invalidation routines
|
||||||
|
@ -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
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
.\" modification, are permitted provided that the following conditions
|
.\" 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
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd December 15, 2007
|
.Dd January 28, 2008
|
||||||
.Dt PUFFS_CC 3
|
.Dt PUFFS_CC 3
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -41,8 +41,6 @@
|
|||||||
.Fn puffs_cc_schedule "struct puffs_cc *pcc"
|
.Fn puffs_cc_schedule "struct puffs_cc *pcc"
|
||||||
.Ft struct puffs_cc *
|
.Ft struct puffs_cc *
|
||||||
.Fn puffs_cc_getcc "struct puffs_usermount *pu"
|
.Fn puffs_cc_getcc "struct puffs_usermount *pu"
|
||||||
.Ft void *
|
|
||||||
.Fn puffs_docc "void *arg"
|
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Em IMPORTANT NOTE!
|
.Em IMPORTANT NOTE!
|
||||||
This document describes interfaces which are not yet guaranteed to be
|
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
|
Suspend and save the current execution context and return control
|
||||||
to the previous point.
|
to the previous point.
|
||||||
In practice, from the file system author perspective, control returns
|
In practice, from the file system author perspective, control returns
|
||||||
back to where either
|
back to where either the mainloop or where
|
||||||
.Fn puffs_dopufbuf
|
.Fn puffs_dispatch_exec
|
||||||
or
|
was called from.
|
||||||
.Fn puffs_docc
|
|
||||||
was called.
|
|
||||||
.It Fn puffs_cc_continue pcc
|
.It Fn puffs_cc_continue pcc
|
||||||
Will suspend current execution and return control to where it was
|
Will suspend current execution and return control to where it was
|
||||||
before before calling
|
before before calling
|
||||||
.Fn puffs_cc_yield .
|
.Fn puffs_cc_yield .
|
||||||
This is rarely called directly but rather through
|
This is rarely called directly but rather through
|
||||||
.Fn puffs_docc .
|
.Fn puffs_dispatch_exec .
|
||||||
.It Fn puffs_cc_schedule "pcc"
|
.It Fn puffs_cc_schedule "pcc"
|
||||||
Schedule a continuation.
|
Schedule a continuation.
|
||||||
As opposed to
|
As opposed to
|
||||||
@ -87,19 +83,6 @@ if this is the main thread.
|
|||||||
The argument
|
The argument
|
||||||
.Ar pu
|
.Ar pu
|
||||||
will most likely disappear at some point.
|
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
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
Before calling
|
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
|
so that the correct continuation can be continued when the event it
|
||||||
was waiting for triggers. Alternatively, the
|
was waiting for triggers. Alternatively, the
|
||||||
.Xr puffs_framebuf 3
|
.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
|
.Sh SEE ALSO
|
||||||
.Xr puffs 3 ,
|
.Xr puffs 3 ,
|
||||||
.Xr puffs_framebuf 3
|
.Xr puffs_framebuf 3
|
||||||
|
@ -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.
|
* 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->stat & FIO_ENABLE_W) == 0)) \
|
||||||
&& (fio->wwait == 0)))
|
&& (fio->wwait == 0)))
|
||||||
|
|
||||||
struct puffs_executor {
|
|
||||||
struct puffs_framebuf *pex_pufbuf;
|
|
||||||
TAILQ_ENTRY(puffs_executor) pex_entries;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* usermount: describes one file system instance
|
* usermount: describes one file system instance
|
||||||
@ -108,6 +104,7 @@ struct puffs_usermount {
|
|||||||
uint32_t pu_flags;
|
uint32_t pu_flags;
|
||||||
int pu_cc_stackshift;
|
int pu_cc_stackshift;
|
||||||
|
|
||||||
|
struct puffs_cc *pu_cc_main;
|
||||||
#define PUFFS_CCMAXSTORE 32
|
#define PUFFS_CCMAXSTORE 32
|
||||||
int pu_cc_nstored;
|
int pu_cc_nstored;
|
||||||
|
|
||||||
@ -126,11 +123,9 @@ struct puffs_usermount {
|
|||||||
LIST_HEAD(, puffs_node) pu_pnodelst;
|
LIST_HEAD(, puffs_node) pu_pnodelst;
|
||||||
|
|
||||||
LIST_HEAD(, puffs_cc) pu_ccmagazin;
|
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_cc) pu_sched;
|
||||||
|
|
||||||
TAILQ_HEAD(, puffs_executor) pu_exq;
|
|
||||||
|
|
||||||
pu_cmap_fn pu_cmap;
|
pu_cmap_fn pu_cmap;
|
||||||
|
|
||||||
pu_pathbuild_fn pu_pathbuild;
|
pu_pathbuild_fn pu_pathbuild;
|
||||||
@ -164,12 +159,24 @@ struct puffs_usermount {
|
|||||||
|
|
||||||
/* call context */
|
/* call context */
|
||||||
|
|
||||||
|
struct puffs_cc;
|
||||||
|
typedef void (*puffs_ccfunc)(struct puffs_cc *);
|
||||||
|
|
||||||
struct puffs_cc {
|
struct puffs_cc {
|
||||||
struct puffs_usermount *pcc_pu;
|
struct puffs_usermount *pcc_pu;
|
||||||
struct puffs_framebuf *pcc_pb;
|
struct puffs_framebuf *pcc_pb;
|
||||||
|
|
||||||
ucontext_t pcc_uc; /* "continue" */
|
/* real cc */
|
||||||
ucontext_t pcc_uc_ret; /* "yield" */
|
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;
|
pid_t pcc_pid;
|
||||||
lwpid_t pcc_lid;
|
lwpid_t pcc_lid;
|
||||||
@ -179,21 +186,14 @@ struct puffs_cc {
|
|||||||
TAILQ_ENTRY(puffs_cc) pcc_schedent;
|
TAILQ_ENTRY(puffs_cc) pcc_schedent;
|
||||||
LIST_ENTRY(puffs_cc) pcc_rope;
|
LIST_ENTRY(puffs_cc) pcc_rope;
|
||||||
};
|
};
|
||||||
#define PCC_FAKECC 0x01
|
#define pcc_uc pcc_u.real.uc
|
||||||
#define PCC_REALCC 0x02
|
#define pcc_uc_ret pcc_u.real.uc_ret
|
||||||
#define PCC_DONE 0x04
|
#define pcc_func pcc_u.fake.func
|
||||||
#define PCC_BORROWED 0x08
|
#define pcc_farg pcc_u.fake.farg
|
||||||
#define PCC_HASCALLER 0x10
|
#define PCC_DONE 0x01
|
||||||
#define PCC_THREADED 0x20
|
#define PCC_BORROWED 0x02
|
||||||
|
#define PCC_HASCALLER 0x04
|
||||||
#define pcc_callstat(a) (a->pcc_flags & PCC_CALL_MASK)
|
#define PCC_MLCONT 0x08
|
||||||
#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)
|
|
||||||
|
|
||||||
struct puffs_newinfo {
|
struct puffs_newinfo {
|
||||||
void **pni_cookie;
|
void **pni_cookie;
|
||||||
@ -214,38 +214,40 @@ struct puffs_newinfo {
|
|||||||
|
|
||||||
__BEGIN_DECLS
|
__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 *);
|
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 *);
|
struct puffs_fctrl_io *);
|
||||||
void puffs_framev_exit(struct puffs_usermount *);
|
void puffs__framev_exit(struct puffs_usermount *);
|
||||||
void puffs_framev_readclose(struct puffs_usermount *,
|
void puffs__framev_readclose(struct puffs_usermount *,
|
||||||
struct puffs_fctrl_io *, int);
|
struct puffs_fctrl_io *, int);
|
||||||
void puffs_framev_writeclose(struct puffs_usermount *,
|
void puffs__framev_writeclose(struct puffs_usermount *,
|
||||||
struct puffs_fctrl_io *, int);
|
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 *);
|
void *puffs__framebuf_getdataptr(struct puffs_framebuf *);
|
||||||
int puffs__framev_addfd_ctrl(struct puffs_usermount *, int, int,
|
int puffs__framev_addfd_ctrl(struct puffs_usermount *, int, int,
|
||||||
struct puffs_framectrl *);
|
struct puffs_framectrl *);
|
||||||
void puffs__framebuf_moveinfo(struct puffs_framebuf *,
|
void puffs__framebuf_moveinfo(struct puffs_framebuf *,
|
||||||
struct puffs_framebuf *);
|
struct puffs_framebuf *);
|
||||||
|
|
||||||
int puffs_cc_create(struct puffs_usermount *, struct puffs_framebuf *,
|
void puffs__theloop(struct puffs_cc *);
|
||||||
int, struct puffs_cc **);
|
void puffs__ml_dispatch(struct puffs_usermount *, struct puffs_framebuf *);
|
||||||
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 puffs__cc_create(struct puffs_usermount *, puffs_ccfunc,
|
||||||
int, int *);
|
struct puffs_cc **);
|
||||||
int puffs_fsframe_write(struct puffs_usermount *, struct puffs_framebuf *,
|
void puffs__cc_cont(struct puffs_cc *);
|
||||||
int, int *);
|
void puffs__cc_destroy(struct puffs_cc *, int);
|
||||||
int puffs_fsframe_cmp(struct puffs_usermount *, struct puffs_framebuf *,
|
void puffs__cc_setcaller(struct puffs_cc *, pid_t, lwpid_t);
|
||||||
struct puffs_framebuf *, int *);
|
void puffs__goto(struct puffs_cc *);
|
||||||
void puffs_fsframe_gotframe(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 *);
|
||||||
|
|
||||||
uint64_t puffs__nextreq(struct puffs_usermount *pu);
|
uint64_t puffs__nextreq(struct puffs_usermount *pu);
|
||||||
|
|
||||||
|
@ -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.
|
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
|
||||||
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#if !defined(lint)
|
#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 */
|
#endif /* !lint */
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -56,7 +56,7 @@ __RCSID("$NetBSD: requests.c,v 1.20 2007/12/05 11:06:05 pooka Exp $");
|
|||||||
*/
|
*/
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
int
|
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)
|
int fd, int *done)
|
||||||
{
|
{
|
||||||
struct putter_hdr phdr;
|
struct putter_hdr phdr;
|
||||||
@ -117,7 +117,7 @@ puffs_fsframe_read(struct puffs_usermount *pu, struct puffs_framebuf *pb,
|
|||||||
*/
|
*/
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
int
|
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)
|
int fd, int *done)
|
||||||
{
|
{
|
||||||
void *win;
|
void *win;
|
||||||
@ -200,7 +200,7 @@ puffs_fsframe_write(struct puffs_usermount *pu, struct puffs_framebuf *pb,
|
|||||||
*/
|
*/
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
int
|
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_framebuf *pb1, struct puffs_framebuf *pb2, int *notresp)
|
||||||
{
|
{
|
||||||
struct puffs_req *preq1, *preq2;
|
struct puffs_req *preq1, *preq2;
|
||||||
@ -233,7 +233,7 @@ puffs_fsframe_cmp(struct puffs_usermount *pu,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
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)
|
if (puffs_framebuf_reserve_space(newpb, PUFFS_MSG_MAXSIZE) == -1)
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
puffs_dopufbuf(pu, newpb);
|
puffs__ml_dispatch(pu, newpb);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user