]> git.pond.sub.org Git - empserver/blob - src/lib/lwp/arch.c
[UCONTEXT] (lwpInitContext): Failed to initialize context.uc_link as
[empserver] / src / lib / lwp / arch.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  arch.c: architecture-dependant process context code
29  * 
30  *  Known contributors to this file:
31  *     Dave Pare, 1994
32  *     Steve McClure, 1994-2000
33  */
34
35 #include "lwp.h"
36 #include "lwpint.h"
37
38 #if defined(_EMPTH_LWP)
39
40 /*
41  * Implement machine-dependent functions lwpInitContext(), lwpSave(),
42  * lwpRestore().
43  *
44  * If lwpSave() and lwpRestore() are #def'd to setjmp() and longjmp(),
45  * then lwpInitContext() needs to set up the jmp_buf for a longjmp(),
46  * similar to setjmp().  To figure that out for another machine, check
47  * their source or reverse engineer.
48  */
49
50
51 #if defined UCONTEXT
52 /*
53  * Alternate aproach using setcontext and getcontext instead of setjmp and
54  * longjump. This should work on any SVr4 machine independant of
55  * architecture.  Unfortunately some changes are still nessesary in lwp.c.
56  * Tested on IRIX 5.3
57  */
58
59 void
60 lwpInitContext(struct lwpProc *newp, stack_t *spp)
61 {
62     getcontext(&newp->context);
63     newp->context.uc_stack.ss_sp = spp->ss_sp;
64     newp->context.uc_stack.ss_size = spp->ss_size;
65     newp->context.uc_link = NULL;
66     makecontext(&newp->context, lwpEntryPoint, 0);
67 }
68
69 #elif defined(hpc)
70
71 static struct lwpProc *tempcontext;
72 static struct lwpProc *initcontext = NULL;
73 static int startpoint;
74
75 static void
76 startcontext(void)
77 {
78     int space[10000];
79     int x;
80
81     startpoint = (void *)&x;
82     if (!setjmp(initcontext->context))
83         longjmp(tempcontext->context, 1);
84
85     if (!setjmp(tempcontext->context))
86         longjmp(LwpCurrent->context, 1);
87
88     lwpEntryPoint();
89 }
90
91 void
92 lwpInitContext(struct lwpProc *newp, void *sp)
93 {
94     struct lwpProc holder;
95     int endpoint;
96
97     if (initcontext == NULL) {
98         initcontext = malloc(sizeof(struct lwpProc));
99         tempcontext = &holder;
100         if (!setjmp(tempcontext->context))
101             startcontext();
102     }
103
104     tempcontext = newp;
105     endpoint = &endpoint;
106     if (endpoint < startpoint) {
107         if (!setjmp(LwpCurrent->context))
108             longjmp(initcontext->context, 1);
109     } else {
110         LwpCurrent->size = endpoint - startpoint;
111         LwpCurrent->sbtm = realloc(LwpCurrent->sbtm, LwpCurrent->size);
112         memcpy(LwpCurrent->sbtm, startpoint, LwpCurrent->size);
113         if (!setjmp(LwpCurrent->context))
114             longjmp(initcontext->context, 1);
115         memcpy(startpoint, LwpCurrent->sbtm, LwpCurrent->size);
116     }
117 }
118
119 int
120 lwpSave(jmp_buf jb)
121 {
122     int endpoint;
123
124     endpoint = &endpoint;
125     if (initcontext == NULL || endpoint < startpoint)
126         return setjmp(jb, 1);
127
128     LwpCurrent->size = endpoint - startpoint;
129     LwpCurrent->sbtm = realloc(LwpCurrent->sbtm, LwpCurrent->size);
130     memcpy(LwpCurrent->sbtm, startpoint, LwpCurrent->size);
131     if (setjmp(jb, 1)) {
132         memcpy(startpoint, LwpCurrent->sbtm, LwpCurrent->size);
133         return 1;
134     }
135     return 0;
136 }
137
138 #elif defined(hpux)
139
140 void
141 lwpInitContext(volatile struct lwpProc *volatile newp, void *sp)
142 {
143     static jmp_buf *cpp;
144
145     if (!lwpSave(LwpCurrent->context)) {
146         cpp = (jmp_buf *) & newp->context;
147         asm volatile ("ldw      %0, %%sp"::"o" (sp));
148         if (!lwpSave(*cpp))
149             lwpRestore(LwpCurrent->context);
150         lwpEntryPoint();
151     }
152 }
153
154 int
155 lwpSave(jmp_buf jb)
156 {
157     /* save stack pointer and return program counter */
158     asm("stw    %sp, 4(%arg0)");
159     asm("stw    %rp, 8(%arg0)");
160
161     /* save "callee save" registers */
162     asm("stw    %r3, 12(%arg0)");
163     asm("stw    %r4, 16(%arg0)");
164     asm("stw    %r5, 20(%arg0)");
165     asm("stw    %r6, 24(%arg0)");
166     asm("stw    %r7, 28(%arg0)");
167     asm("stw    %r8, 32(%arg0)");
168     asm("stw    %r9, 36(%arg0)");
169     asm("stw    %r10, 40(%arg0)");
170     asm("stw    %r11, 44(%arg0)");
171     asm("stw    %r12, 48(%arg0)");
172     asm("stw    %r13, 52(%arg0)");
173     asm("stw    %r14, 56(%arg0)");
174     asm("stw    %r15, 60(%arg0)");
175     asm("stw    %r16, 64(%arg0)");
176     asm("stw    %r17, 68(%arg0)");
177     asm("stw    %r18, 72(%arg0)");
178
179     /* save "callee save" space register */
180     asm volatile ("mfsp %sr3, %r1");
181     asm("stw    %r1, 0(%arg0)");
182
183     /* indicate "true return" from saved() */
184     asm("ldi    0, %ret0");
185
186     asm(".LABEL _comefrom_");
187 }
188
189 void
190 lwpRestore(jmp_buf jb)
191 {
192     /* restore stack pointer and program counter */
193     asm volatile ("ldw  4(%arg0), %sp");
194     asm volatile ("ldw  8(%arg0), %rp");
195
196     /* restore "callee save" space register */
197     asm volatile ("ldw  0(%arg0), %r1");
198     asm volatile ("mtsp %r1, %sr3");
199
200     /* restore "callee save" registers */
201     asm volatile ("ldw  12(%arg0), %r3");
202     asm volatile ("ldw  16(%arg0), %r4");
203     asm volatile ("ldw  20(%arg0), %r5");
204     asm volatile ("ldw  24(%arg0), %r6");
205     asm volatile ("ldw  28(%arg0), %r7");
206     asm volatile ("ldw  32(%arg0), %r8");
207     asm volatile ("ldw  36(%arg0), %r9");
208     asm volatile ("ldw  40(%arg0), %r10");
209     asm volatile ("ldw  44(%arg0), %r11");
210     asm volatile ("ldw  48(%arg0), %r12");
211     asm volatile ("ldw  52(%arg0), %r13");
212     asm volatile ("ldw  56(%arg0), %r14");
213     asm volatile ("ldw  60(%arg0), %r15");
214     asm volatile ("ldw  64(%arg0), %r16");
215     asm volatile ("ldw  68(%arg0), %r17");
216     asm volatile ("ldw  72(%arg0), %r18");
217
218     /* warp to saved() to unwind the frame correctly */
219     asm volatile ("bl   _comefrom_, %r0");
220     asm volatile ("ldi  1, %ret0");
221 }
222
223 #elif defined(FBSD)
224
225 void
226 lwpInitContext(struct lwpProc *newp, void *sp)
227 {
228     setjmp(newp->context);
229     newp->context->_jb[2] = (int)sp;
230     newp->context->_jb[3] = (int)sp;
231     newp->context->_jb[0] = (int)lwpEntryPoint;
232 }
233
234 #elif defined(__linux__)
235
236 void
237 lwpInitContext(struct lwpProc *newp, void *sp)
238 {
239 #if defined(__GLIBC__) && (__GLIBC__ >= 2)
240 #if defined(__PPC__)
241     newp->context->__jmpbuf[JB_GPR1] = (int)sp;
242     newp->context->__jmpbuf[JB_LR] = (int)lwpEntryPoint;
243 #else
244     newp->context->__jmpbuf[JB_SP] = (int)sp;
245     newp->context->__jmpbuf[JB_BP] = (int)sp;
246     newp->context->__jmpbuf[JB_PC] = (int)lwpEntryPoint;
247 #endif
248 #else
249     newp->context->__sp = sp;
250     newp->context->__bp = sp;
251     newp->context->__pc = (void *)lwpEntryPoint;
252 #endif
253 }
254
255 #elif defined(SUN3)
256
257 void
258 lwpInitContext(struct lwpProc *newp, void *sp)
259 {
260     newp->context[2] = (int)sp;
261     newp->context[3] = (int)lwpEntryPoint;
262 }
263
264 #elif defined(SUN4)
265
266 void
267 lwpInitContext(struct lwpProc *newp, void *sp)
268 {
269     static jmp_buf *cpp;
270
271     memset(newp->context, 0, sizeof(newp->context));
272     newp->context[0] = (int)sp;
273     /* preserve cpp for new context */
274     cpp = (jmp_buf *) & newp->context;
275     if (!_setjmp(LwpCurrent->context)) {
276         /* create new context */
277         /* flush registers */
278         asm("ta 0x03");
279         /* %o0 <- newp */
280         asm("ld [%fp+0x44], %o0");
281         /* %o1 <- newp->context[0] */
282         asm("ld [%o0], %o1");
283         /* create min frame on new stack */
284         asm("save       %o1,-96, %sp");
285         if (!_setjmp(*cpp))
286             _longjmp(LwpCurrent->context, 1);
287         lwpEntryPoint();
288     }
289 }
290
291 #elif defined(ALPHA)
292
293 #include <c_asm.h>
294
295 void
296 lwpInitContext(struct lwpProc *newp, void *sp)
297 {
298     extern long *_gp;
299
300     /* register values obtained from setjmp.h */
301     _setjmp(newp->context);
302     newp->context[2] = (long)lwpEntryPoint;     /* program counter */
303     newp->context[30] = (long)lwpEntryPoint;    /* return address */
304     newp->context[31] = (long)lwpEntryPoint;    /* fake program value (!) */
305     newp->context[34] = (long)sp;       /* stack pointer */
306 }
307
308 int
309 lwpSave(jmp_buf jb)
310 {
311     return _setjmp(jb);
312 }
313
314 void
315 lwpRestore(jmp_buf jb)
316 {
317     /* resume, but get the pv from the jmp_buf */
318     asm("ldq    %pv, 248(%a0)");
319     asm("stq    %a0, 16(%sp)");
320     /* generates a warning, but functions just fine */
321     asm("bsr    %ra, __longjump_resume");
322 }
323
324 #elif defined(AIX32)
325 /* Code is in .s files, as compiler doesn't grok asm */
326 #endif
327
328 #endif