2 * Copyright 2000, International Business Machines Corporation and others.
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
10 /* process.c - manage lwp context switches be means of setjmp/longjmp. */
12 #include <afsconfig.h>
15 * We must include at least one system header on Linux prior to including
16 * afs/param.h, or the __GLIBC__ and __GLIBC_MINOR__ macros will not yet be
17 * defined and we won't know whether we're using ucontext.
25 #include <afs/param.h>
29 #if defined(AFS_OSF_ENV) || defined(AFS_S390_LINUX20_ENV)
30 extern int PRE_Block; /* used in lwp.c and process.s */
32 extern char PRE_Block; /* used in lwp.c and process.s */
35 #if defined(USE_UCONTEXT) && defined(HAVE_UCONTEXT_H)
38 savecontext(void (*ep) (void), struct lwp_context *savearea, char *newsp)
40 #if defined(AFS_LINUX20_ENV)
41 /* getcontext does not export stack info */
48 getcontext(&savearea->ucontext);
49 #if defined(AFS_LINUX20_ENV)
50 savearea->topstack = (char *)&stackvar;
52 savearea->topstack = savearea->ucontext.uc_stack.ss_sp;
54 switch (savearea->state) {
60 thread.uc_stack.ss_sp =
61 newsp - AFS_LWP_MINSTACKSIZE + sizeof(void *) +
63 thread.uc_stack.ss_size = AFS_LWP_MINSTACKSIZE - sizeof(void *);
64 makecontext(&thread, ep, 0);
76 returnto(struct lwp_context *savearea)
81 setcontext(&savearea->ucontext);
89 #if defined(AFS_SGI64_ENV)
95 #elif defined(AFS_HPUX_ENV) || defined(AFS_PARISC_LINUX24_ENV)
97 #elif defined(AFS_LINUX20_ENV)
98 #if defined(AFS_PPC_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
100 #elif defined(AFS_I386_LINUX20_ENV)
102 #elif defined(AFS_S390_LINUX20_ENV)
105 #elif defined(AFS_SPARC_LINUX20_ENV)
108 #elif defined(AFS_SPARC64_LINUX20_ENV) && defined(AFS_32BIT_USR_ENV)
111 #elif defined(AFS_ALPHA_LINUX20_ENV)
114 #elif defined(AFS_PARISC_LINUX24_ENV)
117 #error Unsupported linux LWP system type.
119 #elif defined(AFS_X86_FBSD_ENV)
121 #elif defined(AFS_DARWIN_ENV)
124 Need offset to SP in jmp_buf for this platform.
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
132 #if (_MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4)
133 typedef __uint64_t jmp_buf_type;
136 #if defined(AFS_ALPHA_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
137 typedef long jmp_buf_type;
139 typedef int jmp_buf_type;
140 #endif /*AFS_ALPHA_LINUX20_ENV */
143 static jmp_buf jmp_tmp;
144 static void (*EP) (void);
146 static jmp_buf_type *jmpBuffer;
148 /** Starting with Glibc 2.4 pointers in jmp_buf are mangled (XOR) for "protection".
149 * On Sparc ucontext functions are not implemented.
151 #define ptr_mangle(x) (x)
152 #ifdef AFS_LINUX20_ENV
155 #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 3)
157 #if defined(AFS_SPARC64_LINUX24_ENV) || defined(AFS_SPARC_LINUX24_ENV)
158 /* technically we should use POINTER_GUARD
159 * ( == offsetof (tcbhead_t, pointer_guard) )
163 static int ptr_mangle(int p)
165 register char *tls_ptr __asm__("%g7");
166 return p ^ *(int*)(tls_ptr + 0x18);
169 #error need ptr_mangle support or use UCONTEXT
178 savecontext(void (*ep)(void), struct lwp_context *savearea, char *sp)
185 code = setjmp(savearea->setjmp_buffer);
186 jmpBuffer = (jmp_buf_type *) savearea->setjmp_buffer;
187 savearea->topstack = (char *) ptr_mangle(jmpBuffer[LWP_SP]);
191 int i, *ptr = (int *)savearea->setjmp_buffer;
192 printf("savecontext\n");
193 for (i = 0; i < 5; i++)
194 printf("(%d) 0x%x ", i, ptr[i]);
196 for (i = 5; i < 10; i++)
197 printf("(%d) 0x%x ", i, ptr[i]);
206 rc = setjmp(jmp_tmp);
209 jmpBuffer = (jmp_buf_type *) jmp_tmp;
210 jmpBuffer[LWP_SP] = ptr_mangle((jmp_buf_type) sp);
211 #if defined(AFS_S390_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV) || (defined(AFS_SPARC64_LINUX20_ENV) && defined(AFS_32BIT_USR_ENV))
212 jmpBuffer[LWP_FP] = ptr_mangle((jmp_buf_type) sp);
218 assert(0); /* never returns */
221 perror("Error in setjmp1\n");
226 case 2: /* restoring frame */
230 perror("Error in setjmp2 : restoring\n");
237 returnto(struct lwp_context * savearea)
240 int i, *ptr = savearea->setjmp_buffer;
242 printf("Returning to \n");
243 for (i = 0; i < 5; i++)
244 printf("(%d) 0x%x ", i, ptr[i]);
246 for (i = 5; i < 10; i++)
247 printf("(%d) 0x%x ", i, ptr[i]);
251 longjmp(savearea->setjmp_buffer, 2);