This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] s390 and s390x cancellation support


Hi!

The following patch built and passed make check both on s390 and s390x.

2003-01-05  Jakub Jelinek  <jakub@redhat.com>

	* sysdeps/unix/sysv/linux/s390/s390-32/socket.S: Add support for
	cancellation handling.
	* sysdeps/unix/sysv/linux/s390/s390-64/socket.S: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/sigsuspend.c: Likewise.
linuxthreads/
	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: New file.
	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: New file.
	* sysdeps/s390/Makefile: New file.
	* sysdeps/s390/tcb-offsets.sym: New file.
	* sysdeps/s390/tls.h: New file.

--- libc/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h.jj	2003-01-04 14:40:29.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h	2003-01-04 17:41:08.000000000 +0100
@@ -0,0 +1,106 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   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 <tls.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+	.text;								      \
+ENTRY(name)								      \
+	SINGLE_THREAD_P(%r1)						      \
+	jne	L(pseudo_cancel);					      \
+	DO_CALL(syscall_name, args);					      \
+	lhi	%r4,-4095;						      \
+	clr	%r2,%r4;						      \
+	jnl	SYSCALL_ERROR_LABEL;					      \
+	br	%r14;							      \
+L(pseudo_cancel):							      \
+	STM_##args							      \
+	stm	%r13,%r15,52(%r15);					      \
+	ahi	%r15,-96;						      \
+	basr    %r13,0;							      \
+200301:	l	%r1,200302f-200301b(%r13);				      \
+	bas	%r14,0(%r13,%r1);					      \
+	lr	%r0,%r2;						      \
+	LM_##args							      \
+	DO_CALL(syscall_name, args);					      \
+	l	%r3,200303f-200301b(%r13);				      \
+	lr	%r4,%r13;						      \
+	lr	%r13,%r2;						      \
+	lr	%r2,%r0;						      \
+	bas	%r14,0(%r4,%r3);					      \
+	lr	%r2,%r13;						      \
+	lm	%r13,%r15,52+96(%r15);					      \
+	lhi	%r4,-4095;						      \
+	clr	%r2,%r4;						      \
+	jnl	SYSCALL_ERROR_LABEL;					      \
+L(pseudo_end):
+
+#undef PSEUDO_END
+#define PSEUDO_END(name)						      \
+  SYSCALL_ERROR_HANDLER;						      \
+200302:	.long	CENABLE-200301b;					      \
+200303:	.long	CDISABLE-200301b;					      \
+    END (name)
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	__pthread_enable_asynccancel
+#  define CDISABLE	__pthread_disable_asynccancel
+# else
+#  define CENABLE	__libc_enable_asynccancel
+#  define CDISABLE	__libc_disable_asynccancel
+# endif
+
+#define STM_0		/* Nothing */
+#define STM_1		st %r2,8(%r15);
+#define STM_2		stm %r2,%r3,8(%r15);
+#define STM_3		stm %r2,%r4,8(%r15);
+#define STM_4		stm %r2,%r5,8(%r15);
+#define STM_5		stm %r2,%r5,8(%r15);
+
+#define LM_0		/* Nothing */
+#define LM_1		l %r2,8+96(%r15);
+#define LM_2		lm %r2,%r3,8+96(%r15);
+#define LM_3		lm %r2,%r4,8+96(%r15);
+#define LM_4		lm %r2,%r5,8+96(%r15);
+#define LM_5		lm %r2,%r5,8+96(%r15);
+
+# ifndef __ASSEMBLER__
+#  define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \
+				   p_header.data.multiple_threads) == 0, 1)
+# else
+#  define SINGLE_THREAD_P(reg) \
+	ear	reg,%a0;						      \
+	l	reg,MULTIPLE_THREADS_OFFSET(reg);			      \
+	ltr	reg,reg;
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
--- libc/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h.jj	2003-01-04 14:40:29.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h	2003-01-05 01:40:46.000000000 +0100
@@ -0,0 +1,96 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   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 <tls.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+	.text;								      \
+ENTRY(name)								      \
+	SINGLE_THREAD_P							      \
+	jne	L(pseudo_cancel);					      \
+	DO_CALL(syscall_name, args);					      \
+	lghi	%r4,-4095;						      \
+	clgr	%r2,%r4;						      \
+	jnl	SYSCALL_ERROR_LABEL;					      \
+	br	%r14;							      \
+L(pseudo_cancel):							      \
+	STM_##args							      \
+	stmg	%r13,%r15,104(%r15);					      \
+	aghi	%r15,-192;						      \
+	brasl	%r14,CENABLE;						      \
+	lr	%r0,%r2;						      \
+	LM_##args							      \
+	DO_CALL(syscall_name, args);					      \
+	lgr	%r13,%r2;						      \
+	lr	%r2,%r0;						      \
+	brasl	%r14,CDISABLE;						      \
+	lgr	%r2,%r13;						      \
+	lmg	%r13,%r15,104+192(%r15);				      \
+	lghi	%r4,-4095;						      \
+	clgr	%r2,%r4;						      \
+	jnl	SYSCALL_ERROR_LABEL;					      \
+L(pseudo_end):
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	__pthread_enable_asynccancel
+#  define CDISABLE	__pthread_disable_asynccancel
+#  define __local_multiple_threads	__pthread_multiple_threads
+# else
+#  define CENABLE	__libc_enable_asynccancel
+#  define CDISABLE	__libc_disable_asynccancel
+#  define __local_multiple_threads	__libc_multiple_threads
+# endif
+
+#define STM_0		/* Nothing */
+#define STM_1		stg %r2,16(%r15);
+#define STM_2		stmg %r2,%r3,16(%r15);
+#define STM_3		stmg %r2,%r4,16(%r15);
+#define STM_4		stmg %r2,%r5,16(%r15);
+#define STM_5		stmg %r2,%r5,16(%r15);
+
+#define LM_0		/* Nothing */
+#define LM_1		lg %r2,16+192(%r15);
+#define LM_2		lmg %r2,%r3,16+192(%r15);
+#define LM_3		lmg %r2,%r4,16+192(%r15);
+#define LM_4		lmg %r2,%r5,16+192(%r15);
+#define LM_5		lmg %r2,%r5,16+192(%r15);
+
+# ifndef __ASSEMBLER__
+extern int __local_multiple_threads attribute_hidden;
+#  define SINGLE_THREAD_P \
+  __builtin_expect (__local_multiple_threads == 0, 1)
+# else
+#  define SINGLE_THREAD_P \
+	larl	%r1,__local_multiple_threads;				      \
+	icm	%r0,15,0(%r1);
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
--- libc/linuxthreads/sysdeps/s390/Makefile.jj	2003-01-04 15:26:49.000000000 +0100
+++ libc/linuxthreads/sysdeps/s390/Makefile	2003-01-04 16:30:57.000000000 +0100
@@ -0,0 +1,6 @@
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
+ifeq ($(subdir),linuxthreads)
+libpthread-routines += ptw-sysdep
+endif
--- libc/linuxthreads/sysdeps/s390/tcb-offsets.sym.jj	2003-01-04 15:26:52.000000000 +0100
+++ libc/linuxthreads/sysdeps/s390/tcb-offsets.sym	2002-12-28 23:12:30.000000000 +0100
@@ -0,0 +1,4 @@
+#include <sysdep.h>
+#include <tls.h>
+
+MULTIPLE_THREADS_OFFSET		offsetof (tcbhead_t, multiple_threads)
--- libc/linuxthreads/sysdeps/s390/tls.h.jj	2003-01-04 15:26:58.000000000 +0100
+++ libc/linuxthreads/sysdeps/s390/tls.h	2003-01-04 15:28:14.000000000 +0100
@@ -0,0 +1,63 @@
+/* Definitions for thread-local data handling.  linuxthreads/s390 version.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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.  */
+
+#ifndef _TLS_H
+#define _TLS_H
+
+#ifndef __ASSEMBLER__
+
+# include <pt-machine.h>
+# include <stddef.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+typedef struct
+{
+  void *tcb;		/* Pointer to the TCB.  Not necessary the
+			   thread descriptor used by libpthread.  */
+  dtv_t *dtv;
+  void *self;		/* Pointer to the thread descriptor.  */
+  int multiple_threads;
+} tcbhead_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif /* __ASSEMBLER__ */
+
+#undef USE_TLS
+
+#if USE_TLS
+
+#else
+
+#define NONTLS_INIT_TP \
+  do { 								\
+    static const tcbhead_t nontls_init_tp			\
+      = { .multiple_threads = 0 };				\
+    INIT_THREAD_SELF (&nontls_init_tp, 0);			\
+  } while (0)
+
+#endif /* USE_TLS */
+
+#endif	/* tls.h */
--- libc/sysdeps/unix/sysv/linux/s390/s390-32/socket.S.jj	2001-08-23 18:51:29.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/s390/s390-32/socket.S	2003-01-04 23:39:13.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
    This file is part of the GNU C Library.
 
@@ -17,7 +17,7 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <socketcall.h>
 
 /* &%/$&!! preprocessor */
@@ -73,6 +73,12 @@ ENTRY(__socket)
 	st      %r3,0x64(0,%r15)        /* store into parameter list */
 	st      %r2,0x60(0,%r15)
 #endif
+
+#if defined NEED_CANCELLATION && defined CENABLE
+	SINGLE_THREAD_P (%r4)
+	jne	L(socket_cancel)
+#endif
+
 	/* load subcode for socket syscall */
 	lhi     %r2,P(SOCKOP_,socket)
 	la      %r3,0x60(0,%r15)        /* load address of parameter list */
@@ -80,6 +86,7 @@ ENTRY(__socket)
 	/* Do the system call trap.  */
 	svc     SYS_ify(socketcall)
 
+4:
 	l       %r15,0(0,%r15)          /* load back chain */
 	lm      %r6,15,24(%r15)         /* load registers */
 
@@ -91,7 +98,35 @@ ENTRY(__socket)
 	/* Successful; return the syscall's value.  */
 	br      %r14
 
-PSEUDO_END (__socket)
+#if defined NEED_CANCELLATION && defined CENABLE
+L(socket_cancel):
+	basr	%r13,0
+1:	l	%r1,2f-1b(%r13)
+	/* call CENABLE.  */
+	bas	%r14,0(%r13,%r1)
+	lr	%r0,%r2
+
+	/* load subcode for socket syscall */
+	lhi     %r2,P(SOCKOP_,socket)
+	la      %r3,0x60(0,%r15)        /* load address of parameter list */
+
+	/* Do the system call trap.  */
+	svc     SYS_ify(socketcall)
+
+	l	%r3,3f-1b(%r13)
+	lr	%r12,%r2
+	lr	%r2,%r0
+	/* call CDISABLE.  */
+	bas     %r14,0(%r13,%r3)
+	lr	%r2,%r12
+	j	4b
+
+2:	.long	CENABLE-1b
+3:	.long	CDISABLE-1b
+#endif
+
+	SYSCALL_ERROR_HANDLER
+END (__socket)
 
 #ifndef NO_WEAK_ALIAS
 weak_alias (__socket, socket)
--- libc/sysdeps/unix/sysv/linux/s390/s390-64/socket.S.jj	2001-08-23 18:51:29.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/s390/s390-64/socket.S	2003-01-05 00:29:35.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2003 Free Software Foundation, Inc.
    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
    This file is part of the GNU C Library.
 
@@ -17,7 +17,7 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <socketcall.h>
 
 /* &%/$&!! preprocessor */
@@ -73,6 +73,12 @@ ENTRY(__socket)
         stg     %r3,168(%r15)           /* Store into parameter list.  */
 	stg     %r2,160(%r15)
 #endif
+
+#if defined NEED_CANCELLATION && defined CENABLE
+	SINGLE_THREAD_P
+	jne	L(socket_cancel)
+#endif
+
         /* Load subcode for socket syscall.  */
         lghi    %r2,P(SOCKOP_,socket)
 	la      %r3,160(%r15)           /* Load address of parameter list.  */
@@ -80,6 +86,7 @@ ENTRY(__socket)
         /* Do the system call trap.  */
         svc     SYS_ify(socketcall)
 
+4:
         lg      %r15,0(%r15)            /* Load back chain.  */
         lmg     %r6,15,48(%r15)         /* Load registers.  */
 
@@ -91,6 +98,26 @@ ENTRY(__socket)
 	/* Successful; return the syscall's value.  */
 	br      %r14
 
+#if defined NEED_CANCELLATION && defined CENABLE
+L(socket_cancel):
+	brasl	%r14,CENABLE
+	lr	%r0,%r2
+
+	/* Load subcode for socket syscall.  */
+	lghi	%r2,P(SOCKOP_,socket)
+	la	%r3,160(%r15)		/* Load address of parameter list.  */
+
+	/* Do the system call trap.  */
+	svc	SYS_ify(socketcall)
+
+	lgr	%r12,%r2
+	lr	%r2,%r0
+	brasl	%r14,CDISABLE
+
+	lgr	%r2,%r12
+	j	4b
+#endif
+
 PSEUDO_END (__socket)
 
 #ifndef NO_WEAK_ALIAS
--- libc/sysdeps/unix/sysv/linux/s390/s390-64/sigsuspend.c.jj	2002-12-16 00:20:59.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/s390/s390-64/sigsuspend.c	2003-01-05 01:19:54.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -20,7 +20,7 @@
 #include <signal.h>
 #include <unistd.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 
 extern int __syscall_rt_sigsuspend (const sigset_t *, size_t);
@@ -34,7 +34,16 @@ __sigsuspend (set)
 {
   /* XXX The size argument hopefully will have to be changed to the
      real size of the user-level sigset_t.  */
-  return INLINE_SYSCALL (rt_sigsuspend, 2, set, _NSIG / 8);
+  if (SINGLE_THREAD_P)
+    return INLINE_SYSCALL (rt_sigsuspend, 2, set, _NSIG / 8);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = INLINE_SYSCALL (rt_sigsuspend, 2, set, _NSIG / 8);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 }
 libc_hidden_def (__sigsuspend)
 weak_alias (__sigsuspend, sigsuspend)

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]