I've tried to come up with a patch for glibc on hppa, which implements the *context() functions. Main reason for me to write up those functions was e.g. this bug http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=459567 but I assume a few other bugs might be fixed then as well, if we get those functions integrated into glibc. Below is now my first version. Although it fixes the debian bug 459567 for me (after I rebuilt pth-2.0.7 and telling it to use the *context functions), I'm not sure if I missed anything else. I'm sending it here on the parisc-devel list and would be happy to get feedback, before I plan to send it to the glibc devel list. Current limitations: - only integer parameters allowed (but that's usual on most arches) - 32bit userspace implementation only - do I need to save the FP regs? - maybe more? Any feedback is very much appreciated. (Please be kind, my hppa assembler knowledge isn't that good) Helge
diff -up ports/sysdeps/unix/sysv/linux/hppa/Makefile.org ports/sysdeps/unix/sysv/linux/hppa/Makefile --- ports/sysdeps/unix/sysv/linux/hppa/Makefile.org 2008-07-16 19:41:29.000000000 +0200 +++ ports/sysdeps/unix/sysv/linux/hppa/Makefile 2008-07-16 19:41:37.000000000 +0200 @@ -1,2 +1,7 @@ # linux/hppa does not use -lmilli anymore gnulib := -lgcc + +ifeq ($(subdir),stdlib) +gen-as-const-headers += ucontext_i.sym +endif + diff -up ports/sysdeps/unix/sysv/linux/hppa/getcontext.S.org ports/sysdeps/unix/sysv/linux/hppa/getcontext.S --- ports/sysdeps/unix/sysv/linux/hppa/getcontext.S.org 2008-07-16 19:52:11.000000000 +0200 +++ ports/sysdeps/unix/sysv/linux/hppa/getcontext.S 2008-07-18 23:34:32.000000000 +0200 @@ -0,0 +1,101 @@ +/* Get current user context. + Copyright (C) 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Helge Deller <deller@xxxxxx>, 2008. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + +#include "ucontext_i.h" + +ENTRY(__getcontext) + /* Save the register. */ + stw %r0, oR0(%r26) + stw %r1, oR1(%r26) + stw %r2, oR2(%r26) + stw %r3, oR3(%r26) + stw %r4, oR4(%r26) + stw %r5, oR5(%r26) + stw %r6, oR6(%r26) + stw %r7, oR7(%r26) + stw %r8, oR8(%r26) + stw %r9, oR9(%r26) + stw %r10, oR10(%r26) + stw %r11, oR11(%r26) + stw %r12, oR12(%r26) + stw %r13, oR13(%r26) + stw %r14, oR14(%r26) + stw %r15, oR15(%r26) + stw %r16, oR16(%r26) + stw %r17, oR17(%r26) + stw %r18, oR18(%r26) + stw %r19, oR19(%r26) + stw %r20, oR20(%r26) + stw %r21, oR21(%r26) + stw %r22, oR22(%r26) + stw %r23, oR23(%r26) + stw %r24, oR24(%r26) + stw %r25, oR25(%r26) + stw %r26, oR26(%r26) + stw %r27, oR27(%r26) + stw %r28, oR28(%r26) + stw %r29, oR29(%r26) + ldo -64(%sp), %r1 /* Calculate %sp in %r1. */ + stw %r1, oR30(%r26) /* Save new %sp. */ + stw %r31, oR31(%r26) + + stw %r0, oUC_FLAGS(%r26) + stw %r0, oUC_LINK(%r26) + stw %r1, oSS_SP(%r26) /* New %sp. */ + stw %r0, oSS_FLAGS(%r26) + stw %r0, oSS_SIZE(%r26) + + stw %r0, oSC_FLAGS(%r26) + + stw %r0, oIASQ0(%r26) + stw %r0, oIASQ1(%r26) + stw %r0, oIAOQ0(%r26) + stw %r0, oIAOQ1(%r26) + stw %r0, oSAR(%r26) + + /* Store floating-point regs. */ + /* fstd %fr0, oFP0(%r26) */ + + + /* Prologue */ + stwm %r4, 64(%r30) +#ifdef PIC + stw %r19, -32(%r30) +#endif + + /* Save the current signal mask. */ + /* sigprocmask(SIG_BLOCK, NULL, &ucp->uc_sigmask); */ + ldo oSIGMASK(%r26), %r24 + copy %r0, %r25 + bl sigprocmask, %r2 + ldi SIG_BLOCK, %r26 + + /* Epilogue */ + ldw -84(%r30), %r2 +#ifdef PIC + ldw -96(%r30), %r19 +#endif + bv %r0(%r2) + ldwm -64(%r30), %r4 +END(__getcontext) + +weak_alias (__getcontext, getcontext) diff -up ports/sysdeps/unix/sysv/linux/hppa/makecontext.c.org ports/sysdeps/unix/sysv/linux/hppa/makecontext.c --- ports/sysdeps/unix/sysv/linux/hppa/makecontext.c.org 2008-07-16 21:41:02.000000000 +0200 +++ ports/sysdeps/unix/sysv/linux/hppa/makecontext.c 2008-07-16 22:16:29.000000000 +0200 @@ -0,0 +1,79 @@ +/* Create new context. + Copyright (C) 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Helge Deller <deller@xxxxxx>, 2008. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <libintl.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <sysdep.h> +#include <ucontext.h> + +/* XXX: This implementation only handles integer arguments. */ + +void +__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) +{ + unsigned int *sp; + va_list ap; + int i; + + if (argc > 8) + { + fprintf (stderr, _("\ +makecontext: does not know how to handle more than 8 arguments\n")); + exit (-1); + } + + /* Generate room on stack for parameter if needed and uc_link. */ + sp = (unsigned int *) ucp->uc_stack.ss_sp; + + /* Address to jump to. */ + ucp->uc_mcontext.sc_gr[2] = (unsigned long) func; + + va_start (ap, argc); + /* Handle arguments. */ + for (i = 0; i < argc; ++i) + switch (i) + { + case 0: + case 1: + case 2: + case 3: + ucp->uc_mcontext.sc_gr[26-i] = va_arg (ap, int); + break; + case 4: + case 5: + case 6: + case 7: + if (sizeof(unsigned long) == 4) { + /* 32bit: put arg7-arg4 on stack. */ + sp[7-i] = va_arg (ap, int); + } else { + /* 64bit: r19-r22 are arg7-arg4. */ + ucp->uc_mcontext.sc_gr[22+4-i] = va_arg (ap, int); + } + break; + } + va_end (ap); + +} + + +weak_alias(__makecontext, makecontext) diff -up ports/sysdeps/unix/sysv/linux/hppa/setcontext.S.org ports/sysdeps/unix/sysv/linux/hppa/setcontext.S --- ports/sysdeps/unix/sysv/linux/hppa/setcontext.S.org 2008-07-16 22:29:10.000000000 +0200 +++ ports/sysdeps/unix/sysv/linux/hppa/setcontext.S 2008-07-18 23:34:23.000000000 +0200 @@ -0,0 +1,124 @@ +/* Install given context. + Copyright (C) 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Helge Deller <deller@xxxxxx>, 2008. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + +#include "ucontext_i.h" + + +ENTRY(__setcontext) + /* Prologue */ + stwm %r3, 64(%r30) +#ifdef PIC + stw %r19, -32(%r30) +#endif + + /* Save ucp. */ + copy %r26, %r3 + +L(_again): + /* Set the current signal mask. */ + /* sigprocmask(SIG_BLOCK, &ucp->uc_sigmask, NULL); */ + copy %r0, %r24 + ldo oSIGMASK(%r3), %r25 + bl sigprocmask, %r2 + ldi SIG_SETMASK, %r26 + + comib,<> 0,%ret0,L(_error) + nop + + /* Save %sp, %dp. */ + copy %sp, %r4 + copy %dp, %r5 + copy %r19, %r6 + + /* Get the registers. */ + ldw oR1(%r3), %r1 + ldw oR2(%r3), %r2 + /* ldw oR3(%r3), %r3 - used for ucp pointer. */ + /* ldw oR4(%r3), %r4 - used for original %sp. */ + /* ldw oR5(%r3), %r5 - used for %dp / %r27. */ + /* ldw oR6(%r3), %r6 - used for %r19. */ + ldw oR7(%r3), %r7 + ldw oR8(%r3), %r8 + ldw oR9(%r3), %r9 + ldw oR10(%r3), %r10 + ldw oR11(%r3), %r11 + ldw oR12(%r3), %r12 + ldw oR13(%r3), %r13 + ldw oR14(%r3), %r14 + ldw oR15(%r3), %r15 + ldw oR16(%r3), %r16 + ldw oR17(%r3), %r17 + ldw oR18(%r3), %r18 + ldw oR19(%r3), %r19 + ldw oR20(%r3), %r20 + ldw oR21(%r3), %r21 + /* ldw oR22(%r3), %r22 - dyncall arg. */ + ldw oR23(%r3), %r23 + ldw oR24(%r3), %r24 + ldw oR25(%r3), %r25 + ldw oR26(%r3), %r26 + ldw oR27(%r3), %r27 + ldw oR28(%r3), %r28 + ldw oR29(%r3), %r29 + ldw oR30(%r3), %r30 + ldw oR31(%r3), %r31 + + /* Restore floating-point registers. */ + /* fldd oFP0(%r3),%fr0 */ + + + /* Calculate new stack pointer. */ + ldw oSS_SP(%r3), %sp + ldo 64(%sp), %sp + + /* Call function. */ + copy %r2, %r22 + bl $$dyncall, %r31 + copy %r31, %r2 + + /* We return here. Get new ucp in %r3, reload %sp. */ + ldw oUC_LINK(%r3), %r3 + copy %r4, %sp + copy %r5, %dp + copy %r6, %r19 + + /* If ucp == NULL then exit(). */ + comib,<> 0,%r3,L(_again) + nop + + /* If we looped through all uc_link contexts, exit now. */ + bl _exit, %r2 + ldi -1, %r26 + + +L(_error): + /* Epilogue */ + ldw -84(%r30), %r2 +#ifdef PIC + ldw -96(%r30), %r19 +#endif + bv %r0(%r2) + ldwm -64(%r30), %r3 +L(pseudo_end): +PSEUDO_END(__setcontext) + +weak_alias(__setcontext, setcontext) diff -up ports/sysdeps/unix/sysv/linux/hppa/swapcontext.c.org ports/sysdeps/unix/sysv/linux/hppa/swapcontext.c --- ports/sysdeps/unix/sysv/linux/hppa/swapcontext.c.org 2008-07-17 00:37:11.000000000 +0200 +++ ports/sysdeps/unix/sysv/linux/hppa/swapcontext.c 2008-07-18 23:07:15.000000000 +0200 @@ -0,0 +1,66 @@ +/* swap to new context. + Copyright (C) 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Helge Deller <deller@xxxxxx>, 2008. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <ucontext.h> + +extern int __getcontext (ucontext_t *ucp); +extern int __setcontext (const ucontext_t *ucp); + +int +__swapcontext (ucontext_t *oucp, const ucontext_t *ucp) +{ + extern void __swapcontext_ret (void); + + /* Save the current machine context to oucp. */ + __getcontext (oucp); + + /* uc_flags helps to skip the __setcontext call on reactivation. */ + if (++oucp->uc_flags == 1) { + /* Temporarily save a few registers in r23-r26 which would be + * overwritten by setcontext(). Set up the jump to __swapcontext_ret, + * where the registers will be restored and then returned to the + * above uc_flags == 1 test. */ + oucp->uc_mcontext.sc_gr[20] = oucp->uc_mcontext.sc_gr[2]; + oucp->uc_mcontext.sc_gr[2] = (unsigned long) __swapcontext_ret; + oucp->uc_mcontext.sc_gr[23] = oucp->uc_mcontext.sc_gr[3]; + oucp->uc_mcontext.sc_gr[24] = oucp->uc_mcontext.sc_gr[4]; + oucp->uc_mcontext.sc_gr[25] = oucp->uc_mcontext.sc_gr[5]; + oucp->uc_mcontext.sc_gr[26] = oucp->uc_mcontext.sc_gr[6]; + + /* Restore the machine context in ucp. */ + __setcontext (ucp); + } + return 0; +} + +asm (" \n\ + .text \n\ + .type __swapcontext_ret, #function \n\ +__swapcontext_ret: \n\ + copy %r23, %r3 \n\ + copy %r24, %r4 \n\ + copy %r25, %r5 \n\ + copy %r26, %r6 \n\ + bv 0(%r20) \n\ + copy %r0, %ret0 \n\ + .size __swapcontext_ret, .-__swapcontext_ret \n\ + "); + +weak_alias (__swapcontext, swapcontext) diff -up ports/sysdeps/unix/sysv/linux/hppa/ucontext_i.sym.org ports/sysdeps/unix/sysv/linux/hppa/ucontext_i.sym --- ports/sysdeps/unix/sysv/linux/hppa/ucontext_i.sym.org 2008-07-16 19:27:46.000000000 +0200 +++ ports/sysdeps/unix/sysv/linux/hppa/ucontext_i.sym 2008-07-18 23:17:07.000000000 +0200 @@ -0,0 +1,90 @@ +#include <stddef.h> +#include <signal.h> +#include <sys/ucontext.h> + +-- + +SIG_BLOCK +SIG_SETMASK + +#define ucontext(member) offsetof (ucontext_t, member) +#define mcontext(member) ucontext (uc_mcontext.member) +#define mreg(reg) mcontext (sc_gr[reg]) + +oUC_FLAGS ucontext (uc_flags) +oUC_LINK ucontext (uc_link) +oSS_SP ucontext (uc_stack.ss_sp) +oSS_FLAGS ucontext (uc_stack.ss_flags) +oSS_SIZE ucontext (uc_stack.ss_size) +oSC_FLAGS mcontext (sc_flags) +oR0 mreg (0) +oR1 mreg (1) +oR2 mreg (2) +oR3 mreg (3) +oR4 mreg (4) +oR5 mreg (5) +oR6 mreg (6) +oR7 mreg (7) +oR8 mreg (8) +oR9 mreg (9) +oR10 mreg (10) +oR11 mreg (11) +oR12 mreg (12) +oR13 mreg (13) +oR14 mreg (14) +oR15 mreg (15) +oR16 mreg (16) +oR17 mreg (17) +oR18 mreg (18) +oR19 mreg (19) +oR20 mreg (20) +oR21 mreg (21) +oR22 mreg (22) +oR23 mreg (23) +oR24 mreg (24) +oR25 mreg (25) +oR26 mreg (26) +oR27 mreg (27) +oR28 mreg (28) +oR29 mreg (29) +oR30 mreg (30) +oR31 mreg (31) +oFPREGS mcontext (sc_fr) +oFP0 mcontext (sc_fr[0]) +oFP1 mcontext (sc_fr[1]) +oFP2 mcontext (sc_fr[2]) +oFP3 mcontext (sc_fr[3]) +oFP4 mcontext (sc_fr[4]) +oFP5 mcontext (sc_fr[5]) +oFP6 mcontext (sc_fr[6]) +oFP7 mcontext (sc_fr[7]) +oFP8 mcontext (sc_fr[8]) +oFP9 mcontext (sc_fr[9]) +oFP10 mcontext (sc_fr[10]) +oFP11 mcontext (sc_fr[11]) +oFP12 mcontext (sc_fr[12]) +oFP13 mcontext (sc_fr[13]) +oFP14 mcontext (sc_fr[14]) +oFP15 mcontext (sc_fr[15]) +oFP16 mcontext (sc_fr[16]) +oFP17 mcontext (sc_fr[17]) +oFP18 mcontext (sc_fr[18]) +oFP19 mcontext (sc_fr[19]) +oFP20 mcontext (sc_fr[20]) +oFP21 mcontext (sc_fr[21]) +oFP22 mcontext (sc_fr[22]) +oFP23 mcontext (sc_fr[23]) +oFP24 mcontext (sc_fr[24]) +oFP25 mcontext (sc_fr[25]) +oFP26 mcontext (sc_fr[26]) +oFP27 mcontext (sc_fr[27]) +oFP28 mcontext (sc_fr[28]) +oFP29 mcontext (sc_fr[29]) +oFP30 mcontext (sc_fr[30]) +oFP31 mcontext (sc_fr[31]) +oIASQ0 mcontext (sc_iasq[0]) +oIASQ1 mcontext (sc_iasq[1]) +oIAOQ0 mcontext (sc_iaoq[0]) +oIAOQ1 mcontext (sc_iaoq[1]) +oSAR mcontext (sc_sar) +oSIGMASK ucontext (uc_sigmask)