db37936bf422d2943b94ff274842f8019ffc1d34
[ashd.git] / lib / mt.c
1 /*
2     ashd - A Sane HTTP Daemon
3     Copyright (C) 2008  Fredrik Tolf <fredrik@dolda2000.com>
4
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <stdlib.h>
20 #include <stdarg.h>
21 #include <string.h>
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 #include <utils.h>
27 #include <mt.h>
28 #include <valgrind/memcheck.h>
29
30 struct muth *current = NULL;
31 static ucontext_t mainctxt;
32
33 static void freemt(struct muth *muth)
34 {
35     if(muth->running)
36         abort();
37 #ifdef VALGRIND_STACK_DEREGISTER
38     VALGRIND_STACK_DEREGISTER(muth->vgid);
39 #endif
40     free(muth->stack);
41     free(muth);
42 }
43
44 static void muboot(void)
45 {
46     struct muth *muth;
47     
48     muth = current;
49     muth->running = 1;
50     muth->entry(muth, *muth->arglist);
51     muth->running = 0;
52     swapcontext(&muth->ctxt, muth->last);
53 }
54
55 struct muth *mustart(void (*fn)(struct muth *muth, va_list args), ...)
56 {
57     struct muth *muth, *last;
58     va_list args;
59     
60     omalloc(muth);
61     getcontext(&muth->ctxt);
62     muth->ctxt.uc_link = &mainctxt;
63     muth->ctxt.uc_stack.ss_size = 65536;
64     muth->ctxt.uc_stack.ss_sp = muth->stack = smalloc(muth->ctxt.uc_stack.ss_size);
65 #ifdef VALGRIND_STACK_REGISTER
66     muth->vgid = VALGRIND_STACK_REGISTER(muth->stack, muth->stack + 65536);
67 #endif
68     va_start(args, fn);
69     muth->entry = fn;
70     muth->arglist = &args;
71     makecontext(&muth->ctxt, muboot, 0);
72     if(current == NULL)
73         muth->last = &mainctxt;
74     else
75         muth->last = &current->ctxt;
76     last = current;
77     current = muth;
78     swapcontext(muth->last, &muth->ctxt);
79     current = last;
80     va_end(args);
81     if(!muth->running)
82         freemt(muth);
83     return(muth);
84 }
85
86 int yield(void)
87 {
88     ucontext_t *ret;
89     
90     if((current == NULL) || (current->last == NULL))
91         abort();
92     ret = current->last;
93     current->last = NULL;
94     swapcontext(&current->ctxt, ret);
95     return(current->yr);
96 }
97
98 void resume(struct muth *muth, int ret)
99 {
100     struct muth *last;
101     
102     if(muth->last != NULL)
103         abort();
104     if(current == NULL)
105         muth->last = &mainctxt;
106     else
107         muth->last = &current->ctxt;
108     last = current;
109     current = muth;
110     muth->yr = ret;
111     swapcontext(muth->last, &current->ctxt);
112     current = last;
113     if(!muth->running)
114         freemt(muth);
115 }