From fe14a904a8a8701111a11343467427f7ac241e4e Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 10 Dec 2005 22:56:52 +0000 Subject: [PATCH] * Implemented [sig]{set,long}jmp() for PPC. No idea, if it is any good, but it compiles at least. :-) * Pulled the architecture specific part out of into /arch_setjmp.h>. * Moved setjmp_save_sigs.c from the x86 specific implementation into a "generic" sibling directory, since it is reusable (and actually used by the PPC implementation). * Added generic/longjmp_return.c containing a function __longjmp_return, which is invoked at the end of siglongjmp(), resetting the signal mask and validating the return value. It is used by the PPC implementation, and should also be used by the x86 implementation, but I'll leave that to someone who's motivated enough to also test it. :-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15479 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/posix/arch/ppc/arch_setjmp.h | 10 ++++ headers/posix/arch/x86/arch_setjmp.h | 10 ++++ headers/posix/setjmp.h | 11 +++-- .../posix/arch/generic/longjmp_return.c | 23 +++++++++ .../arch/{x86 => generic}/setjmp_save_sigs.c | 0 src/system/libroot/posix/arch/ppc/Jamfile | 16 +++++-- src/system/libroot/posix/arch/ppc/setjmp.S | 15 ++++++ .../libroot/posix/arch/ppc/setjmp_internal.h | 47 +++++++++++++++++++ .../libroot/posix/arch/ppc/siglongjmp.S | 45 ++++++++++++++++++ src/system/libroot/posix/arch/ppc/sigsetjmp.S | 42 +++++++++++++++++ src/system/libroot/posix/arch/x86/Jamfile | 12 ++++- 11 files changed, 223 insertions(+), 8 deletions(-) create mode 100644 headers/posix/arch/ppc/arch_setjmp.h create mode 100644 headers/posix/arch/x86/arch_setjmp.h create mode 100644 src/system/libroot/posix/arch/generic/longjmp_return.c rename src/system/libroot/posix/arch/{x86 => generic}/setjmp_save_sigs.c (100%) create mode 100644 src/system/libroot/posix/arch/ppc/setjmp_internal.h create mode 100644 src/system/libroot/posix/arch/ppc/siglongjmp.S create mode 100644 src/system/libroot/posix/arch/ppc/sigsetjmp.S diff --git a/headers/posix/arch/ppc/arch_setjmp.h b/headers/posix/arch/ppc/arch_setjmp.h new file mode 100644 index 0000000000..567e42f7ad --- /dev/null +++ b/headers/posix/arch/ppc/arch_setjmp.h @@ -0,0 +1,10 @@ +/* + * Copyright 2005, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _ARCH_SETJMP_H_ +#define _ARCH_SETJMP_H_ + +typedef int __jmp_buf[23]; + +#endif /* _ARCH_SETJMP_H_ */ diff --git a/headers/posix/arch/x86/arch_setjmp.h b/headers/posix/arch/x86/arch_setjmp.h new file mode 100644 index 0000000000..6ae972b5b7 --- /dev/null +++ b/headers/posix/arch/x86/arch_setjmp.h @@ -0,0 +1,10 @@ +/* + * Copyright 2005, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _ARCH_SETJMP_H_ +#define _ARCH_SETJMP_H_ + +typedef int __jmp_buf[6]; + +#endif /* _ARCH_SETJMP_H_ */ diff --git a/headers/posix/setjmp.h b/headers/posix/setjmp.h index d9a011ad57..65741a1fa2 100644 --- a/headers/posix/setjmp.h +++ b/headers/posix/setjmp.h @@ -5,12 +5,17 @@ #ifndef _SETJMP_H_ #define _SETJMP_H_ - #include +// include architecture specific definitions +#ifdef __INTEL__ + #include +#elif __POWERPC__ + #include +#endif -typedef struct __jmp_buf { - int regs[6]; /* saved registers, stack & program pointer */ +typedef struct __jmp_buf_tag { + __jmp_buf regs; /* saved registers, stack & program pointer */ int mask_was_saved; sigset_t saved_mask; } jmp_buf[1]; diff --git a/src/system/libroot/posix/arch/generic/longjmp_return.c b/src/system/libroot/posix/arch/generic/longjmp_return.c new file mode 100644 index 0000000000..86b97d76b4 --- /dev/null +++ b/src/system/libroot/posix/arch/generic/longjmp_return.c @@ -0,0 +1,23 @@ +/* + * Copyright 2005, Ingo Weinhold . All rights + * reserved. Distributed under the terms of the Haiku License. + */ + +#include + +/** This function is called by [sig]longjmp(). The caller has already + set up the registers and stack, so that returning from the function + will return to the place where [sig]setjmp() was invoked. It resets + the signal mask and validates the value supplied to [sig]longjmp(). + */ + +int __longjmp_return(jmp_buf buffer, int value); + +int +__longjmp_return(jmp_buf buffer, int value) +{ + if (buffer[0].mask_was_saved) + sigprocmask(SIG_SETMASK, &buffer[0].saved_mask, NULL); + + return (value == 0 ? 1 : value); +} diff --git a/src/system/libroot/posix/arch/x86/setjmp_save_sigs.c b/src/system/libroot/posix/arch/generic/setjmp_save_sigs.c similarity index 100% rename from src/system/libroot/posix/arch/x86/setjmp_save_sigs.c rename to src/system/libroot/posix/arch/generic/setjmp_save_sigs.c diff --git a/src/system/libroot/posix/arch/ppc/Jamfile b/src/system/libroot/posix/arch/ppc/Jamfile index 907b84d2f3..0bc7feba66 100644 --- a/src/system/libroot/posix/arch/ppc/Jamfile +++ b/src/system/libroot/posix/arch/ppc/Jamfile @@ -1,9 +1,17 @@ SubDir HAIKU_TOP src system libroot posix arch ppc ; -# TODO: Implement! +local genericSources = + setjmp_save_sigs.c + longjmp_return.c +; + MergeObject posix_arch_$(TARGET_ARCH).o : setjmp.S -# setjmp_save_sigs.c -# sigsetjmp.S -# siglongjmp.S + sigsetjmp.S + siglongjmp.S + + $(genericSources) ; + +SEARCH on [ FGristFiles $(genericSources) ] + = [ FDirName $(SUBDIR) $(DOTDOT) generic ] ; diff --git a/src/system/libroot/posix/arch/ppc/setjmp.S b/src/system/libroot/posix/arch/ppc/setjmp.S index e69de29bb2..ac0d8420b6 100644 --- a/src/system/libroot/posix/arch/ppc/setjmp.S +++ b/src/system/libroot/posix/arch/ppc/setjmp.S @@ -0,0 +1,15 @@ +/* + * Copyright 2005, Ingo Weinhold . All rights + * reserved. Distributed under the terms of the Haiku License. + */ + +#include "setjmp_internal.h" + +/* int setjmp(jmp_buf buffer) */ +FUNCTION(setjmp): + // call __sigsetjmp with saveMask = 0 + addi %r4, 0, 0 + b __sigsetjmp + +#pragma weak _setjmp=setjmp + diff --git a/src/system/libroot/posix/arch/ppc/setjmp_internal.h b/src/system/libroot/posix/arch/ppc/setjmp_internal.h new file mode 100644 index 0000000000..d465609cea --- /dev/null +++ b/src/system/libroot/posix/arch/ppc/setjmp_internal.h @@ -0,0 +1,47 @@ +/* + * Copyright 2005, Ingo Weinhold . All rights + * reserved. Distributed under the terms of the Haiku License. + */ +#ifndef SETJMP_INTERNAL_H +#define SETJMP_INTERNAL_H + +/* PPC function call ABI register use: + r0 - volatile + r1 - stack frame + r2 - reserved + r3-r4 - param passing, return values + r5-r10 - param passing + r11-r12 - volatile + r13 - small data pointer + r14-r30 - local vars + r31 - local vars/environment +*/ + +/* These are the fields of the __jmp_regs structure */ +#define JMP_REGS_R1 0 +#define JMP_REGS_R2 4 +#define JMP_REGS_R13 8 +#define JMP_REGS_R14 12 +#define JMP_REGS_R15 16 +#define JMP_REGS_R16 20 +#define JMP_REGS_R17 24 +#define JMP_REGS_R18 28 +#define JMP_REGS_R19 32 +#define JMP_REGS_R20 36 +#define JMP_REGS_R21 40 +#define JMP_REGS_R22 44 +#define JMP_REGS_R23 48 +#define JMP_REGS_R24 52 +#define JMP_REGS_R25 56 +#define JMP_REGS_R26 60 +#define JMP_REGS_R27 64 +#define JMP_REGS_R28 68 +#define JMP_REGS_R29 72 +#define JMP_REGS_R30 76 +#define JMP_REGS_R31 80 +#define JMP_REGS_LR 84 +#define JMP_REGS_CR 88 + +#define FUNCTION(x) .global x; .type x,@function; x + +#endif /* SETJMP_INTERNAL_H */ diff --git a/src/system/libroot/posix/arch/ppc/siglongjmp.S b/src/system/libroot/posix/arch/ppc/siglongjmp.S new file mode 100644 index 0000000000..f5d5a5bd32 --- /dev/null +++ b/src/system/libroot/posix/arch/ppc/siglongjmp.S @@ -0,0 +1,45 @@ +/* + * Copyright 2005, Ingo Weinhold . All rights + * reserved. Distributed under the terms of the Haiku License. + */ + +#include "setjmp_internal.h" + +/* int __siglongjmp(jmp_buf buffer, int value) */ +FUNCTION(siglongjmp): +FUNCTION(longjmp): +FUNCTION(_longjmp): + // r3: buffer, r4: saveMask + + // restore non-volatile general purpose registers + lwz %r1, JMP_REGS_R1(3) + lwz %r2, JMP_REGS_R2(3) + lwz %r13, JMP_REGS_R13(3) + lwz %r14, JMP_REGS_R14(3) + lwz %r15, JMP_REGS_R15(3) + lwz %r16, JMP_REGS_R16(3) + lwz %r17, JMP_REGS_R17(3) + lwz %r18, JMP_REGS_R18(3) + lwz %r19, JMP_REGS_R19(3) + lwz %r20, JMP_REGS_R20(3) + lwz %r21, JMP_REGS_R21(3) + lwz %r22, JMP_REGS_R22(3) + lwz %r23, JMP_REGS_R23(3) + lwz %r24, JMP_REGS_R24(3) + lwz %r25, JMP_REGS_R25(3) + lwz %r26, JMP_REGS_R26(3) + lwz %r27, JMP_REGS_R27(3) + lwz %r28, JMP_REGS_R28(3) + lwz %r29, JMP_REGS_R29(3) + lwz %r30, JMP_REGS_R30(3) + lwz %r31, JMP_REGS_R31(3) + + // restore special registers (link, condition) + lwz %r0, JMP_REGS_LR(3) + mtlr %r0 + lwz %r0, JMP_REGS_CR(3) + mtcr %r0 + + b __longjmp_return + +#pragma weak longjmp=siglongjmp diff --git a/src/system/libroot/posix/arch/ppc/sigsetjmp.S b/src/system/libroot/posix/arch/ppc/sigsetjmp.S new file mode 100644 index 0000000000..91065ca116 --- /dev/null +++ b/src/system/libroot/posix/arch/ppc/sigsetjmp.S @@ -0,0 +1,42 @@ +/* + * Copyright 2005, Ingo Weinhold . All rights + * reserved. Distributed under the terms of the Haiku License. + */ + +#include "setjmp_internal.h" + +/* int sigsetjmp(jmp_buf buffer, int saveMask) */ +FUNCTION(__sigsetjmp): +FUNCTION(sigsetjmp): + // r3: buffer, r4: saveMask + + // store non-volatile general purpose registers + stw %r1, JMP_REGS_R1(3) + stw %r2, JMP_REGS_R2(3) + stw %r13, JMP_REGS_R13(3) + stw %r14, JMP_REGS_R14(3) + stw %r15, JMP_REGS_R15(3) + stw %r16, JMP_REGS_R16(3) + stw %r17, JMP_REGS_R17(3) + stw %r18, JMP_REGS_R18(3) + stw %r19, JMP_REGS_R19(3) + stw %r20, JMP_REGS_R20(3) + stw %r21, JMP_REGS_R21(3) + stw %r22, JMP_REGS_R22(3) + stw %r23, JMP_REGS_R23(3) + stw %r24, JMP_REGS_R24(3) + stw %r25, JMP_REGS_R25(3) + stw %r26, JMP_REGS_R26(3) + stw %r27, JMP_REGS_R27(3) + stw %r28, JMP_REGS_R28(3) + stw %r29, JMP_REGS_R29(3) + stw %r30, JMP_REGS_R30(3) + stw %r31, JMP_REGS_R31(3) + + // store special registers (link, condition) + mflr %r0 + stw %r0, JMP_REGS_LR(3) + mfcr %r0 + stw %r0, JMP_REGS_CR(3) + + b __setjmp_save_sigs diff --git a/src/system/libroot/posix/arch/x86/Jamfile b/src/system/libroot/posix/arch/x86/Jamfile index b15aa17b83..7d647140f2 100644 --- a/src/system/libroot/posix/arch/x86/Jamfile +++ b/src/system/libroot/posix/arch/x86/Jamfile @@ -1,8 +1,18 @@ SubDir HAIKU_TOP src system libroot posix arch x86 ; +# TODO: siglongjmp.S should use __longjmp_return to restore the signal mask. +local genericSources = + setjmp_save_sigs.c +# longjmp_return.c +; + MergeObject posix_arch_$(TARGET_ARCH).o : setjmp.S - setjmp_save_sigs.c sigsetjmp.S siglongjmp.S + + $(genericSources) ; + +SEARCH on [ FGristFiles $(genericSources) ] + = [ FDirName $(SUBDIR) $(DOTDOT) generic ] ;