@@ -1,4 +1,15 @@
2015-10-07 Adhemerval Zanella <adhemerval.zanella@linaro.org>
+ Stefan Liebler <stli@linux.vnet.ibm.com>
+
+ * sysdeps/unix/sysv/linux/s390/s390-32/syscall_cancel.S: New file.
+ * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Redefine
+ to call __syscall_cancel function for cancellable syscalls.
+ (__pthread_get_ip): Add implementation.
+ * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h (SYSCALL_CANCEL_ERROR): Add
+ definition.
+ (SYSCALL_CANCEL_ERRNO): Likewise.
+
+2015-10-07 Adhemerval Zanella <adhemerval.zanella@linaro.org>
* sysdeps/unix/sysv/linux/arm/syscall_cancel.S: New file.
* sysdeps/unix/sysv/linux/arm/sysdep-cancel.h (PSEUDO): Redefine
new file mode 100644
@@ -0,0 +1,85 @@
+/* Cancellable syscall wrapper - s390 version.
+ Copyright (C) 2015 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* long int [r2] __syscall_cancel_arch (int *cancelhandling [r2],
+ long int nr [r3],
+ long int arg1 [r4],
+ long int arg2 [r5],
+ long int arg3 [r6],
+ long int arg4 [SP+96],
+ long int arg5 [SP+100],
+ long int arg6 [SP+104]) */
+
+ENTRY (__syscall_cancel_arch)
+ /* Save registers and setup stack. */
+ stm %r6,%r15,24(%r15) /* Save registers */
+ cfi_offset (%r15, -36)
+ cfi_offset (%r14, -40)
+ cfi_offset (%r13, -44)
+ cfi_offset (%r12, -48)
+ cfi_offset (%r11, -52)
+ cfi_offset (%r10, -56)
+ cfi_offset (%r9, -60)
+ cfi_offset (%r8, -64)
+ cfi_offset (%r7, -68)
+ cfi_offset (%r6, -72)
+ lr %r1,%r15
+ l %r0,4(0,%r15) /* Load eos */
+ ahi %r15,-96 /* Buy stack space */
+ cfi_adjust_cfa_offset (96)
+ st %r1,0(0,%r15) /* Store back chain */
+ st %r0,4(0,%r15) /* Store eos */
+
+ .globl __syscall_cancel_arch_start
+ .type __syscall_cancel_arch_start,@function
+__syscall_cancel_arch_start:
+
+ /* if (*cancelhandling & CANCELED_BITMASK)
+ __syscall_do_cancel() */
+ tm 3(%r2),4
+ jne 1f
+
+ /* Issue a 6 argument syscall */
+ lr %r1,%r3 /* Move syscall number. */
+ lr %r2,%r4 /* First parameter. */
+ lr %r3,%r5 /* Second parameter. */
+ lr %r4,%r6 /* Third parameter. */
+ l %r5,192(%r15) /* Fourth parameter. */
+ l %r6,196(%r15) /* Fifth parameter. */
+ l %r7,200(%r15) /* Sixth parameter. */
+
+ svc 0 /* svc number is always in r1. */
+ .globl __syscall_cancel_arch_end
+ .type __syscall_cancel_arch_end,@function
+__syscall_cancel_arch_end:
+ l %r15,0(%r15) /* Load back chain. */
+ cfi_adjust_cfa_offset (-96)
+ lm %r6,15,24(%r15) /* Load registers. */
+
+ br %r14
+
+ /* Branch to __syscall_do_cancel */
+1:
+ l %r15,0(%r15) /* Load back chain. */
+ cfi_adjust_cfa_offset (-96)
+ lm %r6,%r15,24(%r15) /* Load registers. */
+ jg __syscall_do_cancel
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
@@ -24,97 +24,90 @@
#if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
+# if IS_IN (libc)
+# define PREPARE_CALL
+# define PREPARE_GOT
+# define JMP_SYSCALL_CANCEL HIDDEN_JUMPTARGET(__syscall_cancel)
+# else
+# define PREPARE_CALL l %r12,2f-0b(%r13); \
+ la %r12,0(%r12,%r13);
+# define PREPARE_GOT 2: .long _GLOBAL_OFFSET_TABLE_-0b;
+# define JMP_SYSCALL_CANCEL __syscall_cancel@plt
+# endif
+
+# define STORE_0 /* Nothing */
+# define STORE_1 /* Nothing */
+# define STORE_2 /* Nothing */
+# define STORE_3 /* Nothing */
+# define STORE_4 st %r6,24(%r15); \
+ cfi_offset (%r6,-72);
+# define STORE_5 STORE_4
+# define STORE_6 STORE_4
+
+# define LOAD_0 /* Nothing */
+# define LOAD_1 /* Nothing */
+# define LOAD_2 /* Nothing */
+# define LOAD_3 /* Nothing */
+# define LOAD_4 l %r6,24(%r15);
+# define LOAD_5 LOAD_4
+# define LOAD_6 LOAD_4
+
+# define MOVE_ARGS_0
+# define MOVE_ARGS_1 lr %r3,%r2; \
+ MOVE_ARGS_0
+# define MOVE_ARGS_2 lr %r4,%r3; \
+ MOVE_ARGS_1
+# define MOVE_ARGS_3 lr %r5,%r4; \
+ MOVE_ARGS_2
+# define MOVE_ARGS_4 lr %r6,%r5; \
+ MOVE_ARGS_3
+# define MOVE_ARGS_5 st %r6,96(%r15); \
+ MOVE_ARGS_4
+# define MOVE_ARGS_6 l %r14,96(%r14); \
+ st %r14,100(%r15); \
+ MOVE_ARGS_5
+
# undef PSEUDO
# define PSEUDO(name, syscall_name, args) \
.text; \
L(pseudo_cancel): \
cfi_startproc; \
- STM_##args \
stm %r12,%r15,48(%r15); \
cfi_offset (%r15, -36); \
cfi_offset (%r14, -40); \
cfi_offset (%r13, -44); \
cfi_offset (%r12, -48); \
+ STORE_##args \
lr %r14,%r15; \
- ahi %r15,-96; \
- cfi_adjust_cfa_offset (96); \
+ ahi %r15,-104; \
+ cfi_adjust_cfa_offset (104); \
st %r14,0(%r15); \
+ MOVE_ARGS_##args \
+ lhi %r2,SYS_ify (syscall_name); \
basr %r13,0; \
0: l %r1,1f-0b(%r13); \
+ PREPARE_CALL \
bas %r14,0(%r1,%r13); \
- lr %r0,%r2; \
- LM_##args \
- .if SYS_ify (syscall_name) < 256; \
- svc SYS_ify (syscall_name); \
- .else; \
- lhi %r1,SYS_ify (syscall_name); \
- svc 0; \
- .endif; \
- LR7_##args \
- l %r1,2f-0b(%r13); \
- lr %r12,%r2; \
- lr %r2,%r0; \
- bas %r14,0(%r1,%r13); \
- lr %r2,%r12; \
- lm %r12,%r15,48+96(%r15); \
+ lm %r12,%r15,48+104(%r15); \
+ cfi_restore (%r12); \
+ cfi_restore (%r13); \
+ cfi_restore (%r14); \
+ cfi_restore (%r15); \
+ LOAD_##args \
cfi_endproc; \
j L(pseudo_check); \
-1: .long CENABLE-0b; \
-2: .long CDISABLE-0b; \
+1: .long JMP_SYSCALL_CANCEL-0b; \
+ PREPARE_GOT \
ENTRY(name) \
SINGLE_THREAD_P(%r1) \
jne L(pseudo_cancel); \
-.type __##syscall_name##_nocancel,@function; \
-.globl __##syscall_name##_nocancel; \
-__##syscall_name##_nocancel: \
DO_CALL(syscall_name, args); \
L(pseudo_check): \
lhi %r4,-4095; \
clr %r2,%r4; \
jnl SYSCALL_ERROR_LABEL; \
-.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
L(pseudo_end):
-# if IS_IN (libpthread)
-# define CENABLE __pthread_enable_asynccancel
-# define CDISABLE __pthread_disable_asynccancel
-# elif IS_IN (libc)
-# define CENABLE __libc_enable_asynccancel
-# define CDISABLE __libc_disable_asynccancel
-# elif IS_IN (librt)
-# define CENABLE __librt_enable_asynccancel
-# define CDISABLE __librt_disable_asynccancel
-# else
-# error Unsupported library
-# 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 STM_6 stm %r2,%r7,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);
-#define LM_6 lm %r2,%r5,8+96(%r15); \
- cfi_offset (%r7, -68); \
- l %r7,96+96(%r15);
-
-#define LR7_0 /* Nothing */
-#define LR7_1 /* Nothing */
-#define LR7_2 /* Nothing */
-#define LR7_3 /* Nothing */
-#define LR7_4 /* Nothing */
-#define LR7_5 /* Nothing */
-#define LR7_6 l %r7,28+96(%r15); \
- cfi_restore (%r7);
-
# ifndef __ASSEMBLER__
# define SINGLE_THREAD_P \
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
@@ -136,4 +129,11 @@ L(pseudo_end):
# define RTLD_SINGLE_THREAD_P \
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
header.multiple_threads) == 0, 1)
+
+static inline
+long int __pthread_get_ip (const struct ucontext *uc)
+{
+ /* We have 31bit addresses, remove bit 0. */
+ return uc->uc_mcontext.psw.addr & 0x7FFFFFFF;
+}
#endif
@@ -243,6 +243,14 @@
#undef INTERNAL_SYSCALL_ERRNO
#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
+#undef SYSCALL_CANCEL_ERROR
+#define SYSCALL_CANCEL_ERROR(__val) \
+ ((unsigned int) (__val) >= 0xfffff001u)
+
+#undef SYSCALL_CANCEL_ERRNO
+#define SYSCALL_CANCEL_ERRNO(__val) \
+ (-(__val))
+
#define DECLARGS_0()
#define DECLARGS_1(arg1) \
register unsigned long gpr2 asm ("2") = (unsigned long)(arg1);