Updated ChangeLog.
[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
29 #ifdef HAVE_VALGRIND
30 #include <valgrind/memcheck.h>
31 #endif
32
33 struct muth *current = NULL;
34 static ucontext_t mainctxt;
35
36 static void freemt(struct muth *muth)
37 {
38     if(muth->running)
39         abort();
40 #ifdef VALGRIND_STACK_DEREGISTER
41     VALGRIND_STACK_DEREGISTER(muth->vgid);
42 #endif
43     free(muth->stack);
44     free(muth);
45 }
46
47 static void muboot(void)
48 {
49     struct muth *muth;
50     
51     muth = current;
52     muth->running = 1;
53     muth->entry(muth, *muth->arglist);
54     muth->running = 0;
55     swapcontext(&muth->ctxt, muth->last);
56 }
57
58 struct muth *mustart(void (*fn)(struct muth *muth, va_list args), ...)
59 {
60     struct muth *muth, *last;
61     va_list args;
62     
63     omalloc(muth);
64     getcontext(&muth->ctxt);
65     muth->ctxt.uc_link = &mainctxt;
66     muth->ctxt.uc_stack.ss_size = 65536;
67     muth->ctxt.uc_stack.ss_sp = muth->stack = smalloc(muth->ctxt.uc_stack.ss_size);
68 #ifdef VALGRIND_STACK_REGISTER
69     muth->vgid = VALGRIND_STACK_REGISTER(muth->stack, muth->stack + 65536);
70 #endif
71     va_start(args, fn);
72     muth->entry = fn;
73     muth->arglist = &args;
74     makecontext(&muth->ctxt, muboot, 0);
75     if(current == NULL)
76         muth->last = &mainctxt;
77     else
78         muth->last = &current->ctxt;
79     last = current;
80     current = muth;
81     swapcontext(muth->last, &muth->ctxt);
82     current = last;
83     va_end(args);
84     if(!muth->running)
85         freemt(muth);
86     return(muth);
87 }
88
89 int yield(void)
90 {
91     ucontext_t *ret;
92     
93     if((current == NULL) || (current->last == NULL))
94         abort();
95     ret = current->last;
96     current->last = NULL;
97     swapcontext(&current->ctxt, ret);
98     return(current->yr);
99 }
100
101 void resume(struct muth *muth, int ret)
102 {
103     struct muth *last;
104     
105     if(muth->last != NULL)
106         abort();
107     if(current == NULL)
108         muth->last = &mainctxt;
109     else
110         muth->last = &current->ctxt;
111     last = current;
112     current = muth;
113     muth->yr = ret;
114     swapcontext(muth->last, &current->ctxt);
115     current = last;
116     if(!muth->running)
117         freemt(muth);
118 }