[RFC] Patch for glibc getcontext()/makecontext()/setcontext()/swapcontext()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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)

[Index of Archives]     [Linux SoC]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux