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