6ee88e829fe1fbdcdcbe514a9f7c16ff9ce9ac1e
[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_HPUX1122_ENV)
41 /* don't need anything special, will use
42  * ucontext.uc_stack.ss_sp as it matches r12.
43  * This should also work for Linux,
44  * but dont have system to test DEE
45  */
46 #else
47 #error  "You need to update stack pointer register for this platform"
48 #endif
49
50         PRE_Block = 1;
51
52         savearea->state = 0;
53         getcontext(&savearea->ucontext);
54 #if defined(AFS_HPUX1122_ENV)
55     savearea->topstack = savearea->ucontext.uc_stack.ss_sp;
56 #else
57         savearea->topstack = sp;
58 #endif
59         switch (savearea->state)
60         {
61                 case 0:
62                         if (newsp)
63                         {
64                                 ucontext_t thread;
65
66                                 getcontext(&thread);
67                                 thread.uc_stack.ss_sp = newsp - AFS_LWP_MINSTACKSIZE + sizeof(void *) + sizeof(void *);
68                                 thread.uc_stack.ss_size = AFS_LWP_MINSTACKSIZE - sizeof(void *);
69                                 makecontext(&thread, ep, 0);
70                                 setcontext(&thread);
71                         }
72                         else
73                                 (*ep)();
74                         break;
75                 case 2:
76                         break;
77         }
78         return 0;
79 }
80
81 void
82 returnto(savearea)
83 struct lwp_context *savearea;
84 {
85         PRE_Block = 0;
86
87         savearea->state = 2;
88         setcontext(&savearea->ucontext);
89 }
90
91 #else
92
93 /*
94  * Magic stack pointer
95  */
96 #if     defined(AFS_SGI64_ENV)
97 # ifdef _BSD_COMPAT
98 #  define LWP_SP 34
99 # else
100 #  define LWP_SP JB_SP
101 # endif
102 #elif   defined(AFS_HPUX_ENV)
103 #define LWP_SP  1
104 #elif   defined(AFS_LINUX20_ENV)
105 #if defined(AFS_PPC_LINUX20_ENV)
106 #define LWP_SP 0
107 #elif   defined(AFS_I386_LINUX20_ENV)
108 #define LWP_SP 4
109 #elif   defined(AFS_S390_LINUX20_ENV)
110 #define LWP_SP 9
111 #define LWP_FP 5
112 #elif   defined(AFS_SPARC_LINUX20_ENV)
113 #define LWP_SP 0
114 #define LWP_FP 1
115 #elif   defined(AFS_SPARC64_LINUX20_ENV) && defined(AFS_32BIT_USR_ENV)
116 #define LWP_SP 0
117 #define LWP_FP 1
118 #elif defined(AFS_ALPHA_LINUX20_ENV)
119 #define LWP_SP 8
120 #define LWP_FP 7
121 #elif defined(AFS_PARISC_LINUX24_ENV)
122 #define LWP_SP 19
123 #else
124 #error Unsupported linux LWP system type.
125 #endif
126 #elif   defined(AFS_X86_FBSD_ENV)
127 #define LWP_SP 4
128 #elif   defined(AFS_DARWIN_ENV)
129 #define LWP_SP 16
130 #else
131      Need offset to SP in jmp_buf for this platform.
132 #endif
133
134 /**
135   * On SGIs the type of the elements of the array passed to setjmp
136   * differs based on the ISA chosen. It is int for mips1 and mips2 and
137   * __uint64_t for mips3 and mips4
138   */
139    
140 #ifdef AFS_SGI64_ENV
141 #if (_MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4)
142 typedef __uint64_t jmp_buf_type;
143 #endif
144 #else
145 #ifdef AFS_ALPHA_LINUX20_ENV
146 typedef long jmp_buf_type;
147 #else
148 typedef int jmp_buf_type;
149 #endif /*AFS_ALPHA_LINUX20_ENV*/
150 #endif /*SGI*/
151
152 static jmp_buf  jmp_tmp;
153 static char     (*EP)();
154 static int      rc;
155 static jmp_buf_type  *jmpBuffer;
156
157 afs_int32 savecontext(ep, savearea, sp)
158 char    (*ep)();
159 struct lwp_context *savearea;
160 char*   sp;
161 {
162         int code;
163
164         PRE_Block = 1;
165         EP = ep;
166
167         code =  setjmp(savearea->setjmp_buffer);
168         jmpBuffer = (jmp_buf_type *)savearea->setjmp_buffer;
169         savearea->topstack = (char*)jmpBuffer[LWP_SP];
170
171 #if     defined(DEBUG)
172         {
173             int i, *ptr = (int*)savearea->setjmp_buffer;
174             printf("savecontext\n");
175             for ( i=0; i < 5; i++)
176                 printf("(%d) 0x%x   ",i, ptr[i]);
177             printf("\n");
178             for ( i=5; i < 10; i++)
179                 printf("(%d) 0x%x   ",i, ptr[i]);
180             printf("\n");
181         }
182 #endif
183         switch ( code )
184         {
185                 case 0: if ( !sp )
186                         (*EP)();
187                         else
188                         {
189                                 rc = setjmp(jmp_tmp);
190                                 switch ( rc )
191                                 {
192                                 case 0: jmpBuffer = (jmp_buf_type *)jmp_tmp;
193                                         jmpBuffer[LWP_SP] = (jmp_buf_type)sp; 
194 #if defined(AFS_S390_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV) || (defined(AFS_SPARC64_LINUX20_ENV) && defined(AFS_32BIT_USR_ENV))
195                                         jmpBuffer[LWP_FP] = (jmp_buf_type)sp; 
196 #endif
197                                         longjmp(jmp_tmp,1);
198                                         break;
199                                 case 1: (*EP)();
200                                         assert(0); /* never returns */
201                                         break;
202                                 default:
203                                         perror("Error in setjmp1\n");
204                                         exit(2);
205                                 }
206                         }
207                         break; 
208                case 2: /* restoring frame */
209                         break;
210         
211                default:
212                         perror("Error in setjmp2 : restoring\n");
213                         exit(3);
214         }
215         return 0;
216 }
217
218 afs_int32 returnto(savearea)
219 struct lwp_context *savearea;
220 {
221 #if     defined(DEBUG)
222         int i, *ptr = savearea->setjmp_buffer;
223
224         printf("Returning to \n");
225         for ( i=0; i < 5; i++)
226                 printf("(%d) 0x%x   ",i, ptr[i]);
227         printf("\n");
228         for ( i=5; i < 10; i++)
229                 printf("(%d) 0x%x   ",i, ptr[i]);
230         printf("\n");
231 #endif
232         PRE_Block = 0;
233         longjmp(savearea->setjmp_buffer, 2);
234         return 0;
235 }
236
237 #endif