X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=lib%2Fmt.c;fp=lib%2Fmt.c;h=db37936bf422d2943b94ff274842f8019ffc1d34;hb=ddf9919274745e46fc8005f8a86d9b58500b628e;hp=0000000000000000000000000000000000000000;hpb=f0bbedf750f1530ec05bf2b8122479c924bbf2fe;p=ashd.git diff --git a/lib/mt.c b/lib/mt.c new file mode 100644 index 0000000..db37936 --- /dev/null +++ b/lib/mt.c @@ -0,0 +1,115 @@ +/* + ashd - A Sane HTTP Daemon + Copyright (C) 2008 Fredrik Tolf + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +struct muth *current = NULL; +static ucontext_t mainctxt; + +static void freemt(struct muth *muth) +{ + if(muth->running) + abort(); +#ifdef VALGRIND_STACK_DEREGISTER + VALGRIND_STACK_DEREGISTER(muth->vgid); +#endif + free(muth->stack); + free(muth); +} + +static void muboot(void) +{ + struct muth *muth; + + muth = current; + muth->running = 1; + muth->entry(muth, *muth->arglist); + muth->running = 0; + swapcontext(&muth->ctxt, muth->last); +} + +struct muth *mustart(void (*fn)(struct muth *muth, va_list args), ...) +{ + struct muth *muth, *last; + va_list args; + + omalloc(muth); + getcontext(&muth->ctxt); + muth->ctxt.uc_link = &mainctxt; + muth->ctxt.uc_stack.ss_size = 65536; + muth->ctxt.uc_stack.ss_sp = muth->stack = smalloc(muth->ctxt.uc_stack.ss_size); +#ifdef VALGRIND_STACK_REGISTER + muth->vgid = VALGRIND_STACK_REGISTER(muth->stack, muth->stack + 65536); +#endif + va_start(args, fn); + muth->entry = fn; + muth->arglist = &args; + makecontext(&muth->ctxt, muboot, 0); + if(current == NULL) + muth->last = &mainctxt; + else + muth->last = ¤t->ctxt; + last = current; + current = muth; + swapcontext(muth->last, &muth->ctxt); + current = last; + va_end(args); + if(!muth->running) + freemt(muth); + return(muth); +} + +int yield(void) +{ + ucontext_t *ret; + + if((current == NULL) || (current->last == NULL)) + abort(); + ret = current->last; + current->last = NULL; + swapcontext(¤t->ctxt, ret); + return(current->yr); +} + +void resume(struct muth *muth, int ret) +{ + struct muth *last; + + if(muth->last != NULL) + abort(); + if(current == NULL) + muth->last = &mainctxt; + else + muth->last = ¤t->ctxt; + last = current; + current = muth; + muth->yr = ret; + swapcontext(muth->last, ¤t->ctxt); + current = last; + if(!muth->running) + freemt(muth); +}