ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libcoro/coro.c
Revision: 1.1
Committed: Mon Jul 23 17:13:08 2001 UTC (22 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * Copyright (c) 2001 Marc Alexander Lehmann <pcg@goof.com>
3 *
4 * Redistribution and use in source and binary forms, with or without modifica-
5 * tion, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19 * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
21 * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
25 * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26 * OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * This library is modelled strictly after Ralf S. Engelschalls article at
29 * http://www.gnu.org/software/pth/rse-pmt.ps. So most of the credit must
30 * go to Ralf S. Engelschall <rse@engelschall.com>.
31 */
32
33 #include "coro.h"
34
35 #if CORO_LOOSE || CORO_SJLJ
36
37 #include <signal.h>
38
39 static volatile coro_func coro_init_func;
40 static volatile void *coro_init_arg;
41 static volatile coro_context *new_coro, *create_coro;
42
43 static void
44 coro_init (void)
45 {
46 volatile coro_func func = coro_init_func;
47 volatile void *arg = coro_init_arg;
48
49 coro_transfer (new_coro, create_coro);
50
51 func (arg);
52
53 /* the new coro returned. bad. just abort() for now */
54 abort ();
55 }
56
57 # if CORO_SJLJ
58 # define coro_save(ctx) (void)setjmp((ctx)->env)
59
60 static volatile int trampoline_count;
61
62 /* trampoline signal handler */
63 static void
64 trampoline(int sig)
65 {
66 if (setjmp (&(new_coro->env)))
67 coro_init (); /* start it */
68 else
69 trampoline_count++;
70 }
71
72 # endif
73
74 #elif CORO_UCONTEXT
75 # define coro_save(ctx) getcontext(&((ctx)->uc))
76 #endif
77
78 /* initialize a machine state */
79 void coro_create(coro_context *ctx,
80 coro_func coro, void *arg,
81 void *sptr, long ssize)
82 {
83 #if CORO_UCONTEXT
84
85 getcontext (&(ctx->uc));
86
87 ctx->uc.uc_link = 0;
88 ctx->uc.uc_stack.ss_sp = sptr;
89 ctx->uc.uc_stack.ss_size = (size_t) ssize;
90 ctx->uc.uc_stack.ss_flags = 0;
91
92 makecontext (&(ctx->uc), (void (*)()) coro, 1, arg);
93
94 #elif CORO_SJLJ || CORO_LOOSE
95
96 # if CORO_SJLJ
97 stack_t ostk, nstk;
98 struct sigaction osa, nsa;
99 sigset_t nsig, osig;
100 # endif
101 coro_context nctx;
102
103 coro_init_func = coro;
104 coro_init_arg = arg;
105
106 new_coro = ctx;
107 create_coro = &nctx;
108
109 # if CORO_SJLJ
110 /* we use SIGUSR2. first block it, then fiddle with it. */
111
112 sigemptyset (&nsig);
113 sigaddset (&nsig, SIGUSR2);
114 sigprocmask (SIG_BLOCK, &nsig, &osig);
115
116 nsa.sa_handler = trampoline;
117 sigemptyset (&nsa.sa_mask);
118 nsa.sa_flags = SA_ONSTACK;
119
120 if (sigaction (SIGUSR2, &nsa, &osa))
121 perror ("sigaction");
122
123 /* set the new stack */
124 nstk.ss_sp = sptr;
125 nstk.ss_size = ssize;
126 nstk.ss_flags = 0;
127
128 if (sigaltstack (&nstk, &ostk) < 0)
129 perror ("sigaltstack");
130
131 trampoline_count = 0;
132 kill (getpid (), SIGUSR2);
133 sigfillset (&nsig); sigdelset (&nsig, SIGUSR2);
134
135 while (!trampoline_count)
136 sigsuspend (&nsig);
137
138 sigaltstack (0, &nstk);
139 nstk.ss_flags = SS_DISABLE;
140 if (sigaltstack (&nstk, 0) < 0)
141 perror ("sigaltstack");
142
143 sigaltstack (0, &nstk);
144 if (~nstk.ss_flags & SS_DISABLE)
145 abort ();
146
147 if (~ostk.ss_flags & SS_DISABLE)
148 sigaltstack (&ostk, 0);
149
150 sigaction (SIGUSR1, &osa, 0);
151
152 sigprocmask (SIG_SETMASK, &osig, 0);
153
154 # elif MS_LOOSE
155
156 coro_save (ctx);
157 ctx->env[7] = (int)((char *)sptr + ssize);
158 ctx->env[8] = (int)coro;
159
160 # endif
161
162 coro_transfer (create_coro, new_coro);
163
164 #else
165 error unsupported architecture
166 #endif
167 }
168