amd64-linux-port-20030428
[openafs.git] / src / lwp / process.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* process.c - manage lwp context switches be means of setjmp/longjmp. */
11
12 #include <afsconfig.h>
13 #include <afs/param.h>
14
15 RCSID("$Header$");
16
17 #include <stdio.h>
18 #include <assert.h>
19 #include "lwp.h"
20 #ifdef HAVE_STDLIB_H
21 #include <stdlib.h>
22 #endif
23
24 #if defined(AFS_OSF_ENV) || defined(AFS_S390_LINUX20_ENV)
25 extern int PRE_Block;              /* used in lwp.c and process.s */
26 #else
27 extern char PRE_Block;             /* used in lwp.c and process.s */
28 #endif
29
30 #if defined(USE_UCONTEXT) && defined(HAVE_UCONTEXT_H)
31
32 afs_int32
33 savecontext(ep, savearea, newsp)
34 char    (*ep)();
35 struct lwp_context *savearea;
36 char*   newsp;
37 {
38 #if defined(AFS_IA64_LINUX20_ENV)
39         register unsigned long sp __asm__("r12");
40 #elif defined(AFS_AMD64_LINUX24_ENV)
41         register unsigned long sp __asm__("sp");
42 #elif defined(AFS_HPUX1122_ENV)
43 /* don't need anything special, will use
44  * ucontext.uc_stack.ss_sp as it matches r12.
45  * This should also work for Linux,
46  * but dont have system to test DEE
47  */
48 #else
49 #error  "You need to update stack pointer register for this platform"
50 #endif
51
52         PRE_Block = 1;
53
54         savearea->state = 0;
55         getcontext(&savearea->ucontext);
56 #if defined(AFS_HPUX1122_ENV)
57     savearea->topstack = savearea->ucontext.uc_stack.ss_sp;
58 #else
59         savearea->topstack = sp;
60 #endif
61         switch (savearea->state)
62         {
63                 case 0:
64                         if (newsp)
65                         {
66                                 ucontext_t thread;
67
68                                 getcontext(&thread);
69                                 thread.uc_stack.ss_sp = newsp - AFS_LWP_MINSTACKSIZE + sizeof(void *) + sizeof(void *);
70                                 thread.uc_stack.ss_size = AFS_LWP_MINSTACKSIZE - sizeof(void *);
71                                 makecontext(&thread, ep, 0);
72                                 setcontext(&thread);
73                         }
74                         else
75                                 (*ep)();
76                         break;
77                 case 2:
78                         break;
79         }
80         return 0;
81 }
82
83 void
84 returnto(savearea)
85 struct lwp_context *savearea;
86 {
87         PRE_Block = 0;
88
89         savearea->state = 2;
90         setcontext(&savearea->ucontext);
91 }
92
93 #else
94
95 /*
96  * Magic stack pointer
97  */
98 #if     defined(AFS_SGI64_ENV)
99 # ifdef _BSD_COMPAT
100 #  define LWP_SP 34
101 # else
102 #  define LWP_SP JB_SP
103 # endif
104 #elif   defined(AFS_HPUX_ENV)
105 #define LWP_SP  1
106 #elif   defined(AFS_LINUX20_ENV)
107 #if defined(AFS_PPC_LINUX20_ENV)
108 #define LWP_SP 0
109 #elif   defined(AFS_I386_LINUX20_ENV)
110 #define LWP_SP 4
111 #elif   defined(AFS_S390_LINUX20_ENV)
112 #define LWP_SP 9
113 #define LWP_FP 5
114 #elif   defined(AFS_SPARC_LINUX20_ENV)
115 #define LWP_SP 0
116 #define LWP_FP 1
117 #elif   defined(AFS_SPARC64_LINUX20_ENV) && defined(AFS_32BIT_USR_ENV)
118 #define LWP_SP 0
119 #define LWP_FP 1
120 #elif defined(AFS_ALPHA_LINUX20_ENV)
121 #define LWP_SP 8
122 #define LWP_FP 7
123 #elif defined(AFS_PARISC_LINUX24_ENV)
124 #define LWP_SP 19
125 #else
126 #error Unsupported linux LWP system type.
127 #endif
128 #elif   defined(AFS_X86_FBSD_ENV)
129 #define LWP_SP 4
130 #elif   defined(AFS_DARWIN_ENV)
131 #define LWP_SP 16
132 #else
133      Need offset to SP in jmp_buf for this platform.
134 #endif
135
136 /**
137   * On SGIs the type of the elements of the array passed to setjmp
138   * differs based on the ISA chosen. It is int for mips1 and mips2 and
139   * __uint64_t for mips3 and mips4
140   */
141    
142 #ifdef AFS_SGI64_ENV
143 #if (_MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4)
144 typedef __uint64_t jmp_buf_type;
145 #endif
146 #else
147 #ifdef AFS_ALPHA_LINUX20_ENV
148 typedef long jmp_buf_type;
149 #else
150 typedef int jmp_buf_type;
151 #endif /*AFS_ALPHA_LINUX20_ENV*/
152 #endif /*SGI*/
153
154 static jmp_buf  jmp_tmp;
155 static char     (*EP)();
156 static int      rc;
157 static jmp_buf_type  *jmpBuffer;
158
159 afs_int32 savecontext(ep, savearea, sp)
160 char    (*ep)();
161 struct lwp_context *savearea;
162 char*   sp;
163 {
164         int code;
165
166         PRE_Block = 1;
167         EP = ep;
168
169         code =  setjmp(savearea->setjmp_buffer);
170         jmpBuffer = (jmp_buf_type *)savearea->setjmp_buffer;
171         savearea->topstack = (char*)jmpBuffer[LWP_SP];
172
173 #if     defined(DEBUG)
174         {
175             int i, *ptr = (int*)savearea->setjmp_buffer;
176             printf("savecontext\n");
177             for ( i=0; i < 5; i++)
178                 printf("(%d) 0x%x   ",i, ptr[i]);
179             printf("\n");
180             for ( i=5; i < 10; i++)
181                 printf("(%d) 0x%x   ",i, ptr[i]);
182             printf("\n");
183         }
184 #endif
185         switch ( code )
186         {
187                 case 0: if ( !sp )
188                         (*EP)();
189                         else
190                         {
191                                 rc = setjmp(jmp_tmp);
192                                 switch ( rc )
193                                 {
194                                 case 0: jmpBuffer = (jmp_buf_type *)jmp_tmp;
195                                         jmpBuffer[LWP_SP] = (jmp_buf_type)sp; 
196 #if defined(AFS_S390_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV) || (defined(AFS_SPARC64_LINUX20_ENV) && defined(AFS_32BIT_USR_ENV))
197                                         jmpBuffer[LWP_FP] = (jmp_buf_type)sp; 
198 #endif
199                                         longjmp(jmp_tmp,1);
200                                         break;
201                                 case 1: (*EP)();
202                                         assert(0); /* never returns */
203                                         break;
204                                 default:
205                                         perror("Error in setjmp1\n");
206                                         exit(2);
207                                 }
208                         }
209                         break; 
210                case 2: /* restoring frame */
211                         break;
212         
213                default:
214                         perror("Error in setjmp2 : restoring\n");
215                         exit(3);
216         }
217         return 0;
218 }
219
220 afs_int32 returnto(savearea)
221 struct lwp_context *savearea;
222 {
223 #if     defined(DEBUG)
224         int i, *ptr = savearea->setjmp_buffer;
225
226         printf("Returning to \n");
227         for ( i=0; i < 5; i++)
228                 printf("(%d) 0x%x   ",i, ptr[i]);
229         printf("\n");
230         for ( i=5; i < 10; i++)
231                 printf("(%d) 0x%x   ",i, ptr[i]);
232         printf("\n");
233 #endif
234         PRE_Block = 0;
235         longjmp(savearea->setjmp_buffer, 2);
236         return 0;
237 }
238
239 #endif