parisc-linux-lwp-updates-20011025
[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 #ifdef 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*2
113         /* really 19 when structure is double, but requires too many changes
114            below to make a double work */
115 #else
116 #error Unsupported linux LWP system type.
117 #endif
118 #elif   defined(AFS_X86_FBSD_ENV)
119 #define LWP_SP 4
120 #elif   defined(AFS_DARWIN_ENV)
121 #define LWP_SP 16
122 #else
123      Need offset to SP in jmp_buf for this platform.
124 #endif
125
126 /**
127   * On SGIs the type of the elements of the array passed to setjmp
128   * differs based on the ISA chosen. It is int for mips1 and mips2 and
129   * __uint64_t for mips3 and mips4
130   */
131    
132 #ifdef AFS_SGI64_ENV
133 #if (_MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4)
134 typedef __uint64_t jmp_buf_type;
135 #endif
136 #else
137 #ifdef AFS_ALPHA_LINUX20_ENV
138 typedef long jmp_buf_type;
139 #else
140 typedef int jmp_buf_type;
141 #endif /*AFS_ALPHA_LINUX20_ENV*/
142 #endif /*SGI*/
143
144 static jmp_buf  jmp_tmp;
145 static char     (*EP)();
146 static int      rc;
147 static jmp_buf_type  *jmpBuffer;
148
149 afs_int32 savecontext(ep, savearea, sp)
150 char    (*ep)();
151 struct lwp_context *savearea;
152 char*   sp;
153 {
154         int code;
155
156         PRE_Block = 1;
157         EP = ep;
158
159         code =  setjmp(savearea->setjmp_buffer);
160         jmpBuffer = (jmp_buf_type *)savearea->setjmp_buffer;
161         savearea->topstack = (char*)jmpBuffer[LWP_SP];
162
163 #if     defined(DEBUG)
164         {
165             int i, *ptr = (int*)savearea->setjmp_buffer;
166             printf("savecontext\n");
167             for ( i=0; i < 5; i++)
168                 printf("(%d) 0x%x   ",i, ptr[i]);
169             printf("\n");
170             for ( i=5; i < 10; i++)
171                 printf("(%d) 0x%x   ",i, ptr[i]);
172             printf("\n");
173         }
174 #endif
175         switch ( code )
176         {
177                 case 0: if ( !sp )
178                         (*EP)();
179                         else
180                         {
181                                 rc = setjmp(jmp_tmp);
182                                 switch ( rc )
183                                 {
184                                 case 0: jmpBuffer = (jmp_buf_type *)jmp_tmp;
185                                         jmpBuffer[LWP_SP] = (jmp_buf_type)sp; 
186 #if defined(AFS_S390_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV) || (defined(AFS_SPARC64_LINUX20_ENV) && defined(AFS_32BIT_USR_ENV))
187                                         jmpBuffer[LWP_FP] = (jmp_buf_type)sp; 
188 #endif
189                                         longjmp(jmp_tmp,1);
190                                         break;
191                                 case 1: (*EP)();
192                                         assert(0); /* never returns */
193                                         break;
194                                 default:
195                                         perror("Error in setjmp1\n");
196                                         exit(2);
197                                 }
198                         }
199                         break; 
200                case 2: /* restoring frame */
201                         break;
202         
203                default:
204                         perror("Error in setjmp2 : restoring\n");
205                         exit(3);
206         }
207         return 0;
208 }
209
210 afs_int32 returnto(savearea)
211 struct lwp_context *savearea;
212 {
213 #if     defined(DEBUG)
214         int i, *ptr = savearea->setjmp_buffer;
215
216         printf("Returning to \n");
217         for ( i=0; i < 5; i++)
218                 printf("(%d) 0x%x   ",i, ptr[i]);
219         printf("\n");
220         for ( i=5; i < 10; i++)
221                 printf("(%d) 0x%x   ",i, ptr[i]);
222         printf("\n");
223 #endif
224         PRE_Block = 0;
225         longjmp(savearea->setjmp_buffer, 2);
226         return 0;
227 }
228
229 #endif