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>
13 #include <afs/param.h>
21 #if defined(AFS_OSF_ENV) || defined(AFS_S390_LINUX20_ENV)
22 extern int PRE_Block
; /* used in lwp.c and process.s */
24 extern char PRE_Block
; /* used in lwp.c and process.s */
27 #if defined(USE_UCONTEXT) && defined(HAVE_UCONTEXT_H)
30 savecontext(void (*ep
) (void), struct lwp_context
*savearea
, char *newsp
)
32 #if defined(AFS_LINUX20_ENV)
33 /* getcontext does not export stack info */
40 getcontext(&savearea
->ucontext
);
41 #if defined(AFS_LINUX20_ENV)
42 savearea
->topstack
= (char *)&stackvar
;
44 savearea
->topstack
= savearea
->ucontext
.uc_stack
.ss_sp
;
46 switch (savearea
->state
) {
52 thread
.uc_stack
.ss_sp
=
53 newsp
- AFS_LWP_MINSTACKSIZE
+ sizeof(void *) +
55 thread
.uc_stack
.ss_size
= AFS_LWP_MINSTACKSIZE
- sizeof(void *);
56 makecontext(&thread
, ep
, 0);
68 returnto(struct lwp_context
*savearea
)
73 setcontext(&savearea
->ucontext
);
81 #if defined(AFS_SGI64_ENV)
87 #elif defined(AFS_HPUX_ENV) || defined(AFS_PARISC_LINUX24_ENV)
89 #elif defined(AFS_LINUX20_ENV)
90 #if defined(AFS_PPC_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
92 #elif defined(AFS_I386_LINUX20_ENV)
94 #elif defined(AFS_S390_LINUX20_ENV)
97 #elif defined(AFS_SPARC_LINUX20_ENV)
100 #elif defined(AFS_SPARC64_LINUX20_ENV) && defined(AFS_32BIT_USR_ENV)
103 #elif defined(AFS_ALPHA_LINUX20_ENV)
106 #elif defined(AFS_PARISC_LINUX24_ENV)
109 #error Unsupported linux LWP system type.
111 #elif defined(AFS_X86_FBSD_ENV)
113 #elif defined(AFS_DARWIN_ENV)
116 Need offset to SP in
jmp_buf for this platform
.
119 * On SGIs the type of the elements of the array passed to setjmp
120 * differs based on the ISA chosen. It is int for mips1 and mips2 and
121 * __uint64_t for mips3 and mips4
124 #if (_MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4)
125 typedef __uint64_t jmp_buf_type
;
128 #if defined(AFS_ALPHA_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
129 typedef long jmp_buf_type
;
131 typedef int jmp_buf_type
;
132 #endif /*AFS_ALPHA_LINUX20_ENV */
135 static jmp_buf jmp_tmp
;
136 static void (*EP
) (void);
138 static jmp_buf_type
*jmpBuffer
;
140 /** Starting with Glibc 2.4 pointers in jmp_buf are mangled (XOR) for "protection".
141 * On Sparc ucontext functions are not implemented.
143 #define ptr_mangle(x) (x)
144 #ifdef AFS_LINUX20_ENV
147 #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 3)
149 #if defined(AFS_SPARC64_LINUX24_ENV) || defined(AFS_SPARC_LINUX24_ENV)
150 /* technically we should use POINTER_GUARD
151 * ( == offsetof (tcbhead_t, pointer_guard) )
155 static int ptr_mangle(int p
)
157 register char *tls_ptr
__asm__("%g7");
158 return p
^ *(int*)(tls_ptr
+ 0x18);
161 #error need ptr_mangle support or use UCONTEXT
170 savecontext(void (*ep
)(void), struct lwp_context
*savearea
, char *sp
)
177 code
= setjmp(savearea
->setjmp_buffer
);
178 jmpBuffer
= (jmp_buf_type
*) savearea
->setjmp_buffer
;
179 savearea
->topstack
= (char *) ptr_mangle(jmpBuffer
[LWP_SP
]);
183 int i
, *ptr
= (int *)savearea
->setjmp_buffer
;
184 printf("savecontext\n");
185 for (i
= 0; i
< 5; i
++)
186 printf("(%d) 0x%x ", i
, ptr
[i
]);
188 for (i
= 5; i
< 10; i
++)
189 printf("(%d) 0x%x ", i
, ptr
[i
]);
198 rc
= setjmp(jmp_tmp
);
201 jmpBuffer
= (jmp_buf_type
*) jmp_tmp
;
202 jmpBuffer
[LWP_SP
] = ptr_mangle((jmp_buf_type
) sp
);
203 #if defined(AFS_S390_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV) || (defined(AFS_SPARC64_LINUX20_ENV) && defined(AFS_32BIT_USR_ENV))
204 jmpBuffer
[LWP_FP
] = ptr_mangle((jmp_buf_type
) sp
);
210 assert(0); /* never returns */
213 perror("Error in setjmp1\n");
218 case 2: /* restoring frame */
222 perror("Error in setjmp2 : restoring\n");
229 returnto(struct lwp_context
* savearea
)
232 int i
, *ptr
= savearea
->setjmp_buffer
;
234 printf("Returning to \n");
235 for (i
= 0; i
< 5; i
++)
236 printf("(%d) 0x%x ", i
, ptr
[i
]);
238 for (i
= 5; i
< 10; i
++)
239 printf("(%d) 0x%x ", i
, ptr
[i
]);
243 longjmp(savearea
->setjmp_buffer
, 2);