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