--- /dev/null
+/*
+ ashd - A Sane HTTP Daemon
+ Copyright (C) 2008 Fredrik Tolf <fredrik@dolda2000.com>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <syslog.h>
+
+#include <utils.h>
+
+static int tostderr = 1, tosyslog = 0;
+
+void flog(int level, char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ if(tostderr) {
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ } else if(tosyslog) {
+ vsyslog(level, format, args);
+ }
+ va_end(args);
+}
+
+void opensyslog(void)
+{
+ openlog("ashd", 0, LOG_DAEMON);
+ tostderr = 0;
+ tosyslog = 1;
+}
--- /dev/null
+/*
+ ashd - A Sane HTTP Daemon
+ Copyright (C) 2008 Fredrik Tolf <fredrik@dolda2000.com>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <utils.h>
+#include <mt.h>
+#include <valgrind/memcheck.h>
+
+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);
+}
--- /dev/null
+#ifndef _MUTHREAD_H
+#define _MUTHREAD_H
+
+#include <ucontext.h>
+#include <stdarg.h>
+
+#define vavar(type, name) type name = va_arg(args, type)
+
+struct muth {
+ ucontext_t ctxt, *last;
+ void *stack;
+ void (*entry)(struct muth *muth, va_list args);
+ va_list *arglist;
+ int running;
+ int yr;
+ int freeme;
+ int vgid;
+};
+
+struct muth *mustart(void (*fn)(struct muth *muth, va_list args), ...);
+void resume(struct muth *muth, int ret);
+int yield(void);
+
+extern struct muth *current;
+
+#endif