unofficial mirror of libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683)
@ 2018-02-26 21:03 Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 01/21] powerpc: Create stackframe information on syscall Adhemerval Zanella
                   ` (20 more replies)
  0 siblings, 21 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

Changes from previous version [1]:

  * Rebase againt master to incorporate the pthread_join consolidation.

  * Remove ARM syscall_cancel.S implementation and make it use default
    one instead.

  * Move the powerpc syscall stackframe to its own patch.

  * Added a RISCV port using generic syscall_cancel implementation.

I currently tested on x86_64-linux-gnu, x86_64-linux-gnu-x32, i686-linux-gnu,
arm-linux-gnueabihf, aarch64-linux-gnu, sparcv9-linux-gnu, sparc64-linux-gnu,
alpha-linux-gnu, and hppa-linux-gnu.  I also did some simple tests on
ia64-linux-gnu and mips{64}-linux-gnu (to check for the correctness in the
syscall wrapper implementation).  For the rest of support architectures
I just did a cross build/check.

[1] https://sourceware.org/ml/libc-alpha/2017-12/msg00314.html

Adhemerval Zanella (21):
  powerpc: Create stackframe information on syscall
  nptl: Fix testcases for new pthread cancellation mechanism
  nptl: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: x86_64: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: x32: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: i386: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: powerpc: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: aarch64: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: arm: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: s390: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: ia64: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: alpha: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: m68k: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: microblaze: Fix Race conditions in pthread cancellation
    (BZ#12683)
  nptl: tile: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: sparc: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: nios2: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: sh: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: mips: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: hppa: Fix Race conditions in pthread cancellation (BZ#12683)
  nptl: riscv: Fix Race conditions in pthread cancellation (BZ#12683)

 ChangeLog                                          | 216 +++++++++++++++++++++
 debug/tst-backtrace5.c                             |  28 +--
 include/libc-pointer-arith.h                       |  16 +-
 io/creat.c                                         |   3 -
 io/ppoll.c                                         |   2 -
 manual/llio.texi                                   |   4 +-
 misc/pselect.c                                     |   2 -
 nptl/Makefile                                      |  25 +--
 nptl/Versions                                      |   3 +
 nptl/cancellation.c                                | 101 ----------
 nptl/descr.h                                       |  15 +-
 nptl/libc-cancellation.c                           |  48 ++++-
 nptl/lll_timedlock_wait.c                          |   2 +-
 nptl/lll_timedwait_tid.c                           |   3 +-
 nptl/nptl-init.c                                   |  78 +++++---
 nptl/pthreadP.h                                    |  74 +++----
 nptl/pthread_cancel.c                              |  68 ++-----
 nptl/pthread_create.c                              |   7 +-
 nptl/pthread_exit.c                                |   9 +-
 nptl/pthread_join_common.c                         |   7 +-
 nptl/sem_wait.c                                    |   8 +-
 nptl/tst-cancel-wrappers.sh                        |  92 ---------
 nptl/tst-cancel2.c                                 |   3 -
 nptl/tst-cancel28.c                                |  94 +++++++++
 nptl/tst-cancel3.c                                 |   3 -
 nptl/tst-cancel4.c                                 |   8 +
 rt/Makefile                                        |   1 -
 support/temp_file.c                                |  23 +++
 support/temp_file.h                                |   6 +
 sysdeps/generic/sigcontextinfo.h                   |  15 ++
 sysdeps/generic/sysdep-cancel.h                    |   3 -
 sysdeps/i386/nptl/tls.h                            |  11 --
 sysdeps/mips/nptl/tls.h                            |   2 +-
 sysdeps/nptl/Makefile                              |   3 +-
 sysdeps/nptl/aio_misc.h                            |  13 +-
 sysdeps/nptl/gai_misc.h                            |  13 +-
 sysdeps/nptl/lowlevellock.h                        |   5 +-
 sysdeps/posix/open64.c                             |  12 +-
 sysdeps/posix/pause.c                              |   2 -
 sysdeps/posix/sigpause.c                           |   3 -
 sysdeps/posix/sigwait.c                            |   9 +-
 sysdeps/posix/waitid.c                             |  11 +-
 sysdeps/sh/sysdep.h                                |   1 +
 sysdeps/sparc/sparc32/lowlevellock.c               |   3 +-
 sysdeps/unix/sysdep.h                              | 118 +++++++++--
 sysdeps/unix/sysv/linux/aarch64/sigcontextinfo.h   |  11 ++
 sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h     |  13 ++
 sysdeps/unix/sysv/linux/arm/Makefile               |   3 +
 sysdeps/unix/sysv/linux/arm/sigcontextinfo.h       |  12 ++
 sysdeps/unix/sysv/linux/clock_nanosleep.c          |  20 +-
 sysdeps/unix/sysv/linux/creat.c                    |   2 -
 sysdeps/unix/sysv/linux/creat64.c                  |   2 -
 sysdeps/unix/sysv/linux/futex-internal.h           |  18 +-
 .../sysv/linux/hppa/sigcontextinfo.h}              |  26 ++-
 sysdeps/unix/sysv/linux/hppa/syscall_cancel.S      |  82 ++++++++
 sysdeps/unix/sysv/linux/i386/Makefile              |   2 +-
 sysdeps/unix/sysv/linux/i386/lowlevellock.h        |   2 +-
 sysdeps/unix/sysv/linux/i386/sigcontextinfo.h      |  13 ++
 sysdeps/unix/sysv/linux/i386/syscall_cancel.S      | 107 ++++++++++
 sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h      |  24 +++
 sysdeps/unix/sysv/linux/ia64/syscall_cancel.S      |  94 +++++++++
 sysdeps/unix/sysv/linux/lowlevellock-futex.h       |  34 +++-
 sysdeps/unix/sysv/linux/m68k/sigcontextinfo.h      |  13 ++
 .../unix/sysv/linux/microblaze/sigcontextinfo.h    |  13 ++
 .../unix/sysv/linux/microblaze/syscall_cancel.S    |  62 ++++++
 .../unix/sysv/linux/mips/mips32/syscall_cancel.S   | 128 ++++++++++++
 sysdeps/unix/sysv/linux/mips/mips32/sysdep.h       |   4 +
 sysdeps/unix/sysv/linux/mips/sigcontextinfo.h      |  13 +-
 sysdeps/unix/sysv/linux/nios2/sigcontextinfo.h     |  16 ++
 sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h   |  16 ++
 sysdeps/unix/sysv/linux/powerpc/syscall.S          |  14 ++
 sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S   |  64 ++++++
 sysdeps/unix/sysv/linux/pthread_kill.c             |   5 +-
 sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h     |  12 ++
 sysdeps/unix/sysv/linux/s390/sigcontextinfo.h      |  17 ++
 sysdeps/unix/sysv/linux/sh/sigcontextinfo.h        |  11 ++
 sysdeps/unix/sysv/linux/sh/syscall_cancel.S        | 125 ++++++++++++
 sysdeps/unix/sysv/linux/sigwait.c                  |   3 -
 sysdeps/unix/sysv/linux/sigwaitinfo.c              |   3 -
 sysdeps/unix/sysv/linux/socketcall.h               |  37 +++-
 sysdeps/unix/sysv/linux/sparc/lowlevellock.h       |   2 +-
 .../unix/sysv/linux/sparc/sparc32/sigcontextinfo.h |  52 +++++
 .../unix/sysv/linux/sparc/sparc32/syscall_cancel.S |  74 +++++++
 .../libc-cancellation.S => sparc/sparc64/pause.c}  |  14 +-
 .../unix/sysv/linux/sparc/sparc64/sigcontextinfo.h |  40 ++++
 .../unix/sysv/linux/sparc/sparc64/syscall_cancel.S |  74 +++++++
 sysdeps/unix/sysv/linux/syscall_cancel.c           |  64 ++++++
 sysdeps/unix/sysv/linux/sysdep.h                   |  17 ++
 sysdeps/unix/sysv/linux/tile/sigcontextinfo.h      |  12 ++
 sysdeps/unix/sysv/linux/x86_64/cancellation.S      | 115 -----------
 .../unix/sysv/linux/x86_64/librt-cancellation.S    |  21 --
 sysdeps/unix/sysv/linux/x86_64/lowlevellock.h      |   8 +-
 sysdeps/unix/sysv/linux/x86_64/sigcontextinfo.h    |  11 ++
 sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h        |  13 ++
 sysdeps/x86_64/nptl/tcb-offsets.sym                |   1 -
 sysdeps/x86_64/nptl/tls.h                          |  11 --
 96 files changed, 2014 insertions(+), 709 deletions(-)
 delete mode 100644 nptl/cancellation.c
 delete mode 100644 nptl/tst-cancel-wrappers.sh
 create mode 100644 nptl/tst-cancel28.c
 rename sysdeps/{nptl/librt-cancellation.c => unix/sysv/linux/hppa/sigcontextinfo.h} (55%)
 create mode 100644 sysdeps/unix/sysv/linux/hppa/syscall_cancel.S
 create mode 100644 sysdeps/unix/sysv/linux/i386/syscall_cancel.S
 create mode 100644 sysdeps/unix/sysv/linux/ia64/syscall_cancel.S
 create mode 100644 sysdeps/unix/sysv/linux/microblaze/syscall_cancel.S
 create mode 100644 sysdeps/unix/sysv/linux/mips/mips32/syscall_cancel.S
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S
 create mode 100644 sysdeps/unix/sysv/linux/sh/syscall_cancel.S
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/syscall_cancel.S
 rename sysdeps/unix/sysv/linux/{x86_64/libc-cancellation.S => sparc/sparc64/pause.c} (66%)
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc64/syscall_cancel.S
 create mode 100644 sysdeps/unix/sysv/linux/syscall_cancel.c
 delete mode 100644 sysdeps/unix/sysv/linux/x86_64/cancellation.S
 delete mode 100644 sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S

-- 
2.7.4



^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v2 01/21] powerpc: Create stackframe information on syscall
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:41   ` Andreas Schwab
  2018-05-07  2:49   ` Zack Weinberg
  2018-02-26 21:03 ` [PATCH v2 02/21] nptl: Fix testcases for new pthread cancellation mechanism Adhemerval Zanella
                   ` (19 subsequent siblings)
  20 siblings, 2 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds a minimal stackframe creation on powerpc syscall
implementation so backtrace works correctly on a signal handler.

Checked on powerpc64le-linux-gnu.

	* sysdeps/unix/sysv/linux/powerpc/syscall.S (syscall): Create stack
	frame.
---
 ChangeLog                                 |  3 +++
 sysdeps/unix/sysv/linux/powerpc/syscall.S | 14 ++++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S
index 2da9172..fae0fe8 100644
--- a/sysdeps/unix/sysv/linux/powerpc/syscall.S
+++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S
@@ -19,6 +19,14 @@
 
 ENTRY (syscall)
 	ABORT_TRANSACTION
+	/* Creates a minimum stack frame so backtrace works.  */
+#ifdef __powerpc64__
+	stdu r1, -FRAME_MIN_SIZE (r1)
+	cfi_adjust_cfa_offset (FRAME_MIN_SIZE)
+#else
+	stwu r1,-16(1)
+	cfi_def_cfa_offset (16)
+#endif
 	mr   r0,r3
 	mr   r3,r4
 	mr   r4,r5
@@ -26,6 +34,12 @@ ENTRY (syscall)
 	mr   r6,r7
 	mr   r7,r8
 	mr   r8,r9
+#ifdef __powerpc64__
+	addi r1, r1, FRAME_MIN_SIZE
+#else
+	addi r1,r1,16
+#endif
+	cfi_def_cfa_offset (0)
 	sc
 	PSEUDO_RET
 PSEUDO_END (syscall)
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 02/21] nptl: Fix testcases for new pthread cancellation mechanism
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 01/21] powerpc: Create stackframe information on syscall Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:43   ` Andreas Schwab
  2018-05-07  2:49   ` Zack Weinberg
  2018-02-26 21:03 ` [PATCH v2 03/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (18 subsequent siblings)
  20 siblings, 2 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha; +Cc: Adhemerval Zanella

From: Adhemerval Zanella <adhemerval.zanella@linaro.com>

With upcoming fix for BZ#12683, pthread cancellation does not act for:

  1. If syscall is blocked but with some side effects already having
     taken place (e.g. a partial read or write).
  2. After the syscall has returned.

The main change is due the fact programs need to act in syscalls with
side-effects (for instance, to avoid leak of allocated resources or
handle partial read/write).

This patch changes the NPTL testcase that assumes the old behavior and
also remove the tst-cancel-wrappers.sh test (which checks for symbols
that will not exist anymore).  For tst-cancel{2,3} case it remove the
pipe close because it might cause the write syscall to return with
side effects if the close is executed before the pthread cancel.

It also changes how to call the read syscall on tst-backtrace{5,6}
to use syscall instead of read cancelable syscall to avoid need to
handle the cancelable bridge function calls.  It requires a change
on powerpc syscall implementation to create a stackframe, since
powerpc backtrace rely on such information.

Checked on i686-linux-gnu, x86_64-linux-gnu, x86_64-linux-gnux32,
aarch64-linux-gnu, arm-linux-gnueabihf, powerpc64le-linux-gnu,
powerpc-linux-gnu, sparcv9-linux-gnu, and sparc64-linux-gnu.

	* debug/tst-backtrace5.c (handle_signal): Check for syscall
	instead of read.
	(fn): Issue the read syscall instead of call the cancellable
	syscall.
	* nptl/Makefile [$(run-built-tests) = yes] (tests-special): Remove
	tst-cancel-wrappers.sh.
	* nptl/tst-cancel-wrappers.sh: Remove file.
	* nptl/tst-cancel2.c (do_test): Do not close pipe.
	* nptl/tst-cancel3.c (do_test): Likewise.
	* nptl/tst-cancel4.c (tf_write): Handle cancelled syscall with
	side-effects.
	(tf_send): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/syscall.S (syscall): Create stack
	frame.
---
 ChangeLog                   | 14 ++++++-
 debug/tst-backtrace5.c      | 28 ++++++++------
 nptl/Makefile               | 17 +--------
 nptl/tst-cancel-wrappers.sh | 92 ---------------------------------------------
 nptl/tst-cancel2.c          |  3 --
 nptl/tst-cancel3.c          |  3 --
 nptl/tst-cancel4.c          |  8 ++++
 7 files changed, 39 insertions(+), 126 deletions(-)
 delete mode 100644 nptl/tst-cancel-wrappers.sh

diff --git a/debug/tst-backtrace5.c b/debug/tst-backtrace5.c
index 0e6fb1a..a6d66c8 100644
--- a/debug/tst-backtrace5.c
+++ b/debug/tst-backtrace5.c
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
+#include <sys/syscall.h>
 #include <signal.h>
 #include <unistd.h>
 
@@ -33,7 +34,7 @@
 #endif
 
 /* The backtrace should include at least handle_signal, a signal
-   trampoline, read, 3 * fn, and do_test.  */
+   trampoline, syscall, 3 * fn, and do_test.  */
 #define NUM_FUNCTIONS 7
 
 void
@@ -71,16 +72,18 @@ handle_signal (int signum)
     }
   /* Do not check name for signal trampoline.  */
   i = 2;
-  if (!match (symbols[i++], "read"))
+
+  if (match (symbols[i], "__kernel_vsyscall"))
+    i++;
+
+  /* We are using syscall(...) instead of read.  */
+  if (!match (symbols[i++], "syscall"))
     {
-      /* Perhaps symbols[2] is __kernel_vsyscall?  */
-      if (!match (symbols[i++], "read"))
-	{
-	  FAIL ();
-	  return;
-	}
+      FAIL ();
+      return;
     }
-  for (; i < n - 1; i++)
+
+  for (; i < n - 2; i++)
     if (!match (symbols[i], "fn"))
       {
 	FAIL ();
@@ -123,8 +126,11 @@ fn (int c, int flags)
       _exit (0);
     }
 
-  /* In the parent.  */
-  read (pipefd[0], r, 1);
+  /* To avoid need to handle cancellation syscall backtrace (which call
+     the function using both the generic bridge (__syscall_cancel) and
+     the architecture defined one (__syscall_cancel_arch), issue the
+     syscall directly.  */
+  syscall (__NR_read, pipefd[0], r, 1);
 
   return 0;
 }
diff --git a/nptl/Makefile b/nptl/Makefile
index de37fb4..76ecf6c 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -452,8 +452,7 @@ tests-reverse += tst-cancel5 tst-cancel23 tst-vfork1x tst-vfork2x
 ifeq ($(run-built-tests),yes)
 tests-special += $(objpfx)tst-stack3-mem.out $(objpfx)tst-oddstacklimit.out
 ifeq ($(build-shared),yes)
-tests-special += $(objpfx)tst-tls6.out $(objpfx)tst-cleanup0-cmp.out \
-		 $(objpfx)tst-cancel-wrappers.out
+tests-special += $(objpfx)tst-tls6.out $(objpfx)tst-cleanup0-cmp.out
 endif
 endif
 
@@ -682,7 +681,7 @@ $(objpfx)$(multidir)/crtn.o: $(objpfx)crtn.o $(objpfx)$(multidir)/
 endif
 
 generated += libpthread_nonshared.a \
-	     multidir.mk tst-atfork2.mtrace tst-cancel-wrappers.out \
+	     multidir.mk tst-atfork2.mtrace \
 	     tst-tls6.out
 
 generated += $(objpfx)tst-atfork2.mtrace \
@@ -694,18 +693,6 @@ LDFLAGS-pthread.so += -e __nptl_main
 $(objpfx)pt-interp.os: $(common-objpfx)runtime-linker.h
 endif
 
-ifeq ($(run-built-tests),yes)
-ifeq (yes,$(build-shared))
-$(objpfx)tst-cancel-wrappers.out: tst-cancel-wrappers.sh
-	$(SHELL) $< '$(NM)' \
-		    $(common-objpfx)libc_pic.a \
-		    $(common-objpfx)libc.a \
-		    $(objpfx)libpthread_pic.a \
-		    $(objpfx)libpthread.a > $@; \
-	$(evaluate-test)
-endif
-endif
-
 tst-exec4-ARGS = $(host-test-program-cmd)
 
 $(objpfx)tst-execstack: $(libdl)
diff --git a/nptl/tst-cancel-wrappers.sh b/nptl/tst-cancel-wrappers.sh
deleted file mode 100644
index 0c5b614..0000000
--- a/nptl/tst-cancel-wrappers.sh
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/bin/sh
-# Test whether all cancelable functions are cancelable.
-# Copyright (C) 2002-2018 Free Software Foundation, Inc.
-# This file is part of the GNU C Library.
-# Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
-
-# 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/>.
-
-NM="$1"; shift
-while [ $# -gt 0 ]; do
-  ( $NM -P $1; echo 'end[end]:' ) | gawk ' BEGIN {
-C["accept"]=1
-C["close"]=1
-C["connect"]=1
-C["creat"]=1
-C["fcntl"]=1
-C["fdatasync"]=1
-C["fsync"]=1
-C["msgrcv"]=1
-C["msgsnd"]=1
-C["msync"]=1
-C["nanosleep"]=1
-C["open"]=1
-C["open64"]=1
-C["pause"]=1
-C["poll"]=1
-C["pread"]=1
-C["pread64"]=1
-C["pselect"]=1
-C["pwrite"]=1
-C["pwrite64"]=1
-C["read"]=1
-C["readv"]=1
-C["recv"]=1
-C["recvfrom"]=1
-C["recvmsg"]=1
-C["select"]=1
-C["send"]=1
-C["sendmsg"]=1
-C["sendto"]=1
-C["sigpause"]=1
-C["sigsuspend"]=1
-C["sigwait"]=1
-C["sigwaitinfo"]=1
-C["tcdrain"]=1
-C["wait"]=1
-C["waitid"]=1
-C["waitpid"]=1
-C["write"]=1
-C["writev"]=1
-C["__xpg_sigpause"]=1
-}
-/:$/ {
-  if (seen)
-    {
-      if (!seen_enable || !seen_disable)
-	{
-	  printf "in '$1'(%s) %s'\''s cancellation missing\n", object, seen
-	  ret = 1
-	}
-    }
-  seen=""
-  seen_enable=""
-  seen_disable=""
-  object=gensub(/^.*\[(.*)\]:$/, "\\1", 1, $0)
-  next
-}
-{
-  if (C[$1] && $2 ~ /^[TW]$/)
-    seen=$1
-  else if ($1 ~ /^([.]|)__(libc|pthread)_enable_asynccancel$/ && $2 == "U")
-    seen_enable=1
-  else if ($1 ~ /^([.]|)__(libc|pthread)_disable_asynccancel$/ && $2 == "U")
-    seen_disable=1
-}
-END {
-  exit ret
-}' || exit
-  shift
-done
diff --git a/nptl/tst-cancel2.c b/nptl/tst-cancel2.c
index e2926bd..45e9a61 100644
--- a/nptl/tst-cancel2.c
+++ b/nptl/tst-cancel2.c
@@ -73,9 +73,6 @@ do_test (void)
       return 1;
     }
 
-  /* This will cause the write in the child to return.  */
-  close (fd[0]);
-
   if (pthread_join (th, &r) != 0)
     {
       puts ("join failed");
diff --git a/nptl/tst-cancel3.c b/nptl/tst-cancel3.c
index a82c8f2..67f6543 100644
--- a/nptl/tst-cancel3.c
+++ b/nptl/tst-cancel3.c
@@ -75,9 +75,6 @@ do_test (void)
       return 1;
     }
 
-  /* This will cause the read in the child to return.  */
-  close (fd[0]);
-
   if (pthread_join (th, &r) != 0)
     {
       puts ("join failed");
diff --git a/nptl/tst-cancel4.c b/nptl/tst-cancel4.c
index 0532538..2614f9a 100644
--- a/nptl/tst-cancel4.c
+++ b/nptl/tst-cancel4.c
@@ -166,6 +166,10 @@ tf_write  (void *arg)
   char buf[WRITE_BUFFER_SIZE];
   memset (buf, '\0', sizeof (buf));
   s = write (fd, buf, sizeof (buf));
+  /* The write can return a value higher than 0 (meaning partial write)
+     due to the SIGCANCEL, but the thread may still be pending
+     cancellation.  */
+  pthread_testcancel ();
 
   pthread_cleanup_pop (0);
 
@@ -743,6 +747,10 @@ tf_send (void *arg)
   char mem[WRITE_BUFFER_SIZE];
 
   send (tempfd2, mem, arg == NULL ? sizeof (mem) : 1, 0);
+  /* Thez send can return a value higher than 0 (meaning partial send)
+     due to the SIGCANCEL, but the thread may still be pending
+     cancellation.  */
+  pthread_testcancel ();
 
   pthread_cleanup_pop (0);
 
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 03/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 01/21] powerpc: Create stackframe information on syscall Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 02/21] nptl: Fix testcases for new pthread cancellation mechanism Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-04-27 12:20   ` Zack Weinberg
  2018-05-07  2:49   ` Zack Weinberg
  2018-02-26 21:03 ` [PATCH v2 04/21] nptl: x86_64: " Adhemerval Zanella
                   ` (17 subsequent siblings)
  20 siblings, 2 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patches fixes some race conditions in NPTL cancellation code by
redefining how cancellable syscalls are defined and handled.  Current
approach is to enable asynchronous cancellation prior to making the syscall
and restore the previous cancellation type once the syscall returns.

As decribed in BZ#12683, this approach shows 2 important problems:

  1. Cancellation can act after the syscall has returned from kernel, but
     before userspace saves the return value.  It might result in a resource
     leak if the syscall allocated a resource or a side effect (partial
     read/write), and there is no way to program handle it with cancellation
     handlers.

  2. If a signal is handled while the thread is blocked at a cancellable
     syscall, the entire signal handler runs with asynchronous cancellation
     enabled.  This can lead to issues if the signal handler call functions
     which are async-signal-safe but not async-cancel-safe.

For cancellation to work correctly, there are 5 points at which the
cancellation signal could arrive:

  1. Before the final "testcancel" and before the syscall is made.
  2. Between the "testcancel" and the syscall.
  3. While the syscall is blocked and no side effects have yet taken place.
  4. While the syscall is blocked but with some side effects already having
     taken place (e.g. a partial read or write).
  5. After the syscall has returned.

And GLIBC wants to act on cancellation in cases 1, 2, and 3 but not in case
4 or 5.  The proposed solution follows:

  * Handling case 1 is trivial: do a conditional branch based on whether the
    thread has received a cancellation request;
  * Case 2 can be caught by the signal handler determining that the saved
    program counter (from the ucontext_t) is in some address range beginning
    just before the "testcancel" and ending with the syscall instruction.
  * In this case, except for certain syscalls that ALWAYS fail with EINTR
    even for non-interrupting signals, the kernel will reset the program
    counter to point at the syscall instruction during signal handling, so
    that the syscall is restarted when the signal handler returns. So, from
    the signal handler's standpoint, this looks the same as case 2, and thus
    it's taken care of.
  * In this case, the kernel cannot restart the syscall; when it's
    interrupted by a signal, the kernel must cause the syscall to return
    with whatever partial result it obtained (e.g. partial read or write).
  * In this case, the saved program counter points just after the syscall
    instruction, so the signal handler won't act on cancellation.
    This one is equal to 4. since the program counter is past the syscall
    instruction already.

Another case that needs handling is syscalls that fail with EINTR even
when the signal handler is non-interrupting. In this case, the syscall
wrapper code can just check the cancellation flag when the errno result
is EINTR, and act on cancellation if it's set.

The proposed GLIBC adjustments are:

  1. Remove the enable_asynccancel/disable_asynccancel function usage in
     syscall definition and instead make them call a common symbol that will
     check if cancellation is enabled (__syscall_cancel at
     nptl/libc-cancellation.c), call the arch-specific cancellable
     entry-point (__syscall_cancel_arch) and cancel the thread when required.

  2. Provide a arch-specific symbol that contains global markers. These
     markers will be used in SIGCANCEL handler to check if the interruption
     has been called in a valid syscall and if the syscalls has been
     completed or not.
     A default version is provided (sysdeps/unix/sysv/linux/syscall_cancel.c),
     however the markers may not be set on correct expected places depeding
     of how INTERNAL_SYSCALL_NCS is implemented by the underlying architecture.
     In this case arch-specific implementation should be provided.

  3. Rewrite SIGCANCEL asynchronous handler to check for both cancelling type
     and if current IP from signal handler falls between the global markes
     and act accordingly (sigcancel_handler at nptl/nptl-init.c).

  4. Adjust nptl/pthread_cancel.c to send an signal instead of acting
     directly. This avoid synchronization issues when updating the
     cancellation status and also focus the logic on signal handler and
     cancellation syscall code.

  5. Adjust pthread code to replace CANCEL_ASYNC/CANCEL_RESET calls to
     appropriated cancelable futex syscalls.

  6. Adjust libc code to replace LIBC_CANCEL_ASYNC/LIBC_CANCEL_RESET to
     appropriated cancelable syscalls.

  7. Adjust 'lowlevellock-futex.h' arch-specific implementations to provide
     cancelable futex calls (used in libpthread code).

This patch adds the proposed changes to NPTL.  The code leaves all the ports
broken without further patches in the list.

	[BZ #12683]
	* nptl/Makefile [routines]: Add syscall_cancel object.
	[libpthread-routines]: Remove cancellation object.
	(CFLAGS-cancellation.c): Remove rule.
	(CFLAGS-syscall_cancel.c): New rule.
	(tests): Add tst-cancel28.
	* nptl/Versions [GLIBC_PRIVATE] (libc): Add __syscall_cancel,
	__syscall_cancel_arch_start, and __syscall_cancel_arch_end.
	* nptl/cancellation.c: Remove file.
	* nptl/descr.h (CANCELING_BIT): Remove define.
	(CANCELING_BITMASK): Likewise.
	(CANCEL_RESTMASK): Adjust value with CANCELED_BIT remove.
	* nptl/libc-cancellation.c (__syscall_cancel): Add non-cancellable
	implementation for loader and cancellable one for libc.
	(__syscall_do_cancel): New function: cancel call for syscall wrappers.
	* nptl/lll_timedlock_wait.c (__lll_timedlock_wait): Use cancellable
	futex operation.
	(__lll_timedwait_tid): Likewise.
	* nptl/nptl-init.c (sigcancel_handler): Rewrite function to avoid race
	conditions.
	(__pthread_initialize_minimal_internal): Add SA_RESTART to SIGCANCEL
	handler.
	* nptl/pt-system.c [LIBC_CANCEL_HANDLED]: Remove definition.
	* io/creat.c (LIBC_CANCEL_HANDLED): Likewise.
	* io/ppoll.c [ppoll] (LIBC_CANCEL_HANDLED): Likewise.
	* misc/pselect [__pselect] (LIBC_CANCEL_HANDLED): Likewise.
	* sysdeps/posix/pause.c (LIBC_CANCEL_HANDLED): Likewise.
	* sysdeps/unix/sysv/linux/generic/creat.c (LIBC_CANCEL_HANDLED):
	Likewise.
	* nptl/pthreadP.h (__do_cancel): Rewrite to both disable asynchronous
	cancellation and setting the thread as cancelled.
	(CANCEL_ASYNC): Remove definition.
	(CANCEL_RESET): Likewise.
	(LIBC_CANCEL_ASYNC): Likewise.
	(LIBC_CANCEL_RESET): Likewise.
	(LIBC_CANCEL_HANDLED): Likewise.
	(__syscall_cancel_arch): Add prototype.
	(__pthread_enable_asynccancel): Remove prototype.
	(__pthread_disable_asynccancel): Likewise.
	(__libc_enable_asynccancel): Likewise.
	(__libc_disable_asynccancel): Likewise.
	(__librt_enable_asynccancel): Likewise.
	(__librt_disable_asynccancel): Likewise.
	(__syscall_cancel_arch): Add prototype.
	(__syscall_do_cancel): Likewise.
	* nptl/pthread_cancel.c (pthread_cancel): Rewrite to just set
	CANCELLED_BIT and call __pthread_kill.
	* nptl/pthread_create.c (start_thread): Likewise.
	* nptl/pthread_timedjoin.c (pthread_timedjoin_np): Likewise.
	* nptl/sem_timedwait.c (sem_timedwait):  Likewise.
	* nptl/sem_wait.c (__new_sem_wait): Likewise.
	* nptl/sem_waitcommon.c (futex_abstimed_wait): Likewise.
	* sysdeps/nptl/aio_misc.h (AIO_MISC_WAIT): Likewise.
	* sysdeps/nptl/gai_misc.h (GAI_MISC_WAIT): Likewise.
	* sysdeps/posix/sigpause.c (do_sigpause): Likewise.
	* sysdeps/posix/sigwait.c (__sigwait): Likewise.
	* sysdeps/posix/waitid.c (__waitid): Likewise.
	* sysdeps/nptl/lowlevellock.h (lll_wait_tid): Likewise.
	* sysdeps/posix/open64.c (__libc_open64): Likewise.
	* sysdeps/unix/sysv/linux/sigwait.c (__sigwait): Likewise.
	* nptl/pthread_exit.c (pthread_exit): Rewrite to set EXITING_BIT
	before call __pthread_unwind.
	* nptl/pthread_join.c (pthread_join): Remove CANCEL_ASYNC/CANCEL_RESET
	usage.
	* rt/Makefile [CFLAGS-librt-cancellation.c]: Remove rule.
	* sysdeps/generic/sysdep-cancel.h (LIBC_CANCEL_ASYNC): Remove define.
	(LIBC_CANCEL_RESET): Likewise.
	(LIBC_CANCEL_HANDLED): Likewise.
	* sysdeps/unix/sysv/linux/clock_nanosleep.c (__clock_nanosleep):
	Likewise.
	* sysdeps/unix/sysv/linux/fcntl.c (__libc_fcntl): Likewise.
	* sysdeps/unix/sysv/linux/generic/wordsize-32/fcntl.c (__libc_fcntl):
	Likewise.
	* sysdeps/nptl/Makefile [$(subdir) = rt] (librt-sysdep_routines):
	Remove librt-cancellation object.
	[$(subdir) = rt] (librt-cancellation.c): Remove rule.
	* sysdeps/nptl/librt-cancellation.c: Remove file.
	* sysdeps/unix/sysv/linux/futex-internal.h (lll_futex_wait_cancel):
	Use lll_futex_timed_wait_cancel.
	(futex_reltimed_wait_cancelable): Likewise.
	(futex_abstimed_wait_cancelable)): Use
	lll_futex_timed_wait_bitset_cancel.
	* sysdeps/unix/sysv/linux/lowlevellock-futex.h
	(lll_futex_wait_cancel): New macro.
	(lll_futex_timed_wait_cancel): Likewise.
	(lll_futex_timed_wait_bitset_cancel): Likewise.
	* sysdeps/unix/sysdep.h (SYSCALL_CANCEL): New macro: cancelable
	syscall calls.
	(INTERNAL_SYSCALL_NCS_CALL): New macro.
	(__syscall_cancel): New prototype.
	* sysdeps/unix/sysv/linux/socketcall.h (SOCKETCALL): Use __SSC macros.
	(SOCKETCALL_CANCEL): Use SYSCALL_CANCEL macros.
	* sysdeps/generic/sysdep-cancel.h (LIBC_CANCEL_ASYNC): Remove define.
	(LIBC_CANCEL_RESET): Likewise.
	(LIBC_CANCEL_HANDLED): Likewise.
	* sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): Allow
	SIGCANCEL to be sent.
	* nptl/tst-cancel28.c: New file.
	* sysdeps/unix/sysv/linux/syscall_cancel.c: Likewise.
	* support/temp_file.c (create_temp_fifo): New function.
	* support/temp_file.h (create_temp_fifo): Likewise.
---
 ChangeLog                                    |  85 ++++++++++++++++++++++
 io/creat.c                                   |   3 -
 io/ppoll.c                                   |   2 -
 manual/llio.texi                             |   4 +-
 misc/pselect.c                               |   2 -
 nptl/Makefile                                |   8 +--
 nptl/Versions                                |   3 +
 nptl/cancellation.c                          | 101 ---------------------------
 nptl/descr.h                                 |  15 ++--
 nptl/libc-cancellation.c                     |  47 ++++++++++++-
 nptl/lll_timedlock_wait.c                    |   2 +-
 nptl/lll_timedwait_tid.c                     |   3 +-
 nptl/nptl-init.c                             |  78 +++++++++++++--------
 nptl/pthreadP.h                              |  73 +++++++------------
 nptl/pthread_cancel.c                        |  68 ++++--------------
 nptl/pthread_create.c                        |   7 +-
 nptl/pthread_exit.c                          |   9 ++-
 nptl/pthread_join_common.c                   |   7 +-
 nptl/sem_wait.c                              |   8 +--
 nptl/tst-cancel28.c                          |  94 +++++++++++++++++++++++++
 rt/Makefile                                  |   1 -
 support/temp_file.c                          |  23 ++++++
 support/temp_file.h                          |   6 ++
 sysdeps/generic/sigcontextinfo.h             |  15 ++++
 sysdeps/generic/sysdep-cancel.h              |   3 -
 sysdeps/nptl/Makefile                        |   3 +-
 sysdeps/nptl/aio_misc.h                      |  13 +---
 sysdeps/nptl/gai_misc.h                      |  13 +---
 sysdeps/nptl/librt-cancellation.c            |  24 -------
 sysdeps/nptl/lowlevellock.h                  |   5 +-
 sysdeps/posix/open64.c                       |  12 +---
 sysdeps/posix/pause.c                        |   2 -
 sysdeps/posix/sigpause.c                     |   3 -
 sysdeps/posix/sigwait.c                      |   9 +--
 sysdeps/posix/waitid.c                       |  11 +--
 sysdeps/sparc/sparc32/lowlevellock.c         |   3 +-
 sysdeps/unix/sysdep.h                        |  96 +++++++++++++++++++++----
 sysdeps/unix/sysv/linux/clock_nanosleep.c    |  20 +-----
 sysdeps/unix/sysv/linux/creat.c              |   2 -
 sysdeps/unix/sysv/linux/creat64.c            |   2 -
 sysdeps/unix/sysv/linux/futex-internal.h     |  18 ++---
 sysdeps/unix/sysv/linux/lowlevellock-futex.h |  34 ++++++++-
 sysdeps/unix/sysv/linux/pthread_kill.c       |   5 +-
 sysdeps/unix/sysv/linux/sigwait.c            |   3 -
 sysdeps/unix/sysv/linux/sigwaitinfo.c        |   3 -
 sysdeps/unix/sysv/linux/socketcall.h         |  37 ++++++++--
 sysdeps/unix/sysv/linux/syscall_cancel.c     |  62 ++++++++++++++++
 sysdeps/unix/sysv/linux/sysdep.h             |  17 +++++
 48 files changed, 639 insertions(+), 425 deletions(-)
 delete mode 100644 nptl/cancellation.c
 create mode 100644 nptl/tst-cancel28.c
 delete mode 100644 sysdeps/nptl/librt-cancellation.c
 create mode 100644 sysdeps/unix/sysv/linux/syscall_cancel.c

diff --git a/io/creat.c b/io/creat.c
index 21ee56e..3d0afca 100644
--- a/io/creat.c
+++ b/io/creat.c
@@ -27,6 +27,3 @@ creat (const char *file, mode_t mode)
 {
   return __open (file, O_WRONLY|O_CREAT|O_TRUNC, mode);
 }
-
-/* __open handles cancellation.  */
-LIBC_CANCEL_HANDLED ();
diff --git a/io/ppoll.c b/io/ppoll.c
index ec26b99..5ccfdb9 100644
--- a/io/ppoll.c
+++ b/io/ppoll.c
@@ -70,7 +70,5 @@ ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
 }
 
 #ifndef ppoll
-/* __poll handles cancellation.  */
-LIBC_CANCEL_HANDLED ();
 libc_hidden_def (ppoll);
 #endif
diff --git a/manual/llio.texi b/manual/llio.texi
index b4fd5e1..573c34b 100644
--- a/manual/llio.texi
+++ b/manual/llio.texi
@@ -2531,13 +2531,13 @@ aiocb64}, since the LFS transparently replaces the old interface.
 @c     sigemptyset ok
 @c     sigaddset ok
 @c     setjmp ok
-@c     CANCEL_ASYNC -> pthread_enable_asynccancel ok
+@c     __pthread_setcanceltype ok
 @c      do_cancel ok
 @c       pthread_unwind ok
 @c        Unwind_ForcedUnwind or longjmp ok [@ascuheap @acsmem?]
 @c     lll_lock @asulock @aculock
 @c     lll_unlock @asulock @aculock
-@c     CANCEL_RESET -> pthread_disable_asynccancel ok
+@c     __pthread_setcanceltype ok
 @c      lll_futex_wait ok
 @c     ->start_routine ok -----
 @c     call_tls_dtors @asulock @ascuheap @aculock @acsmem
diff --git a/misc/pselect.c b/misc/pselect.c
index 2c29230..07d5ffc 100644
--- a/misc/pselect.c
+++ b/misc/pselect.c
@@ -73,6 +73,4 @@ __pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 }
 #ifndef __pselect
 weak_alias (__pselect, pselect)
-/* __select handles cancellation.  */
-LIBC_CANCEL_HANDLED ();
 #endif
diff --git a/nptl/Makefile b/nptl/Makefile
index 76ecf6c..34a7a18 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -30,7 +30,7 @@ install-lib-ldscripts := libpthread.so
 
 routines = alloca_cutoff forward libc-lowlevellock libc-cancellation \
 	   libc-cleanup libc_pthread_init libc_multiple_threads \
-	   register-atfork pthread_self
+	   register-atfork pthread_self syscall_cancel
 shared-only-routines = forward
 
 # We need to provide certain routines for compatibility with existing
@@ -117,7 +117,6 @@ libpthread-routines = nptl-init vars events version pt-interp \
 		      cleanup cleanup_defer cleanup_compat \
 		      cleanup_defer_compat unwind \
 		      pt-longjmp pt-cleanup\
-		      cancellation \
 		      lowlevellock \
 		      lll_timedlock_wait lll_timedwait_tid \
 		      pt-fork pt-vfork \
@@ -166,7 +165,6 @@ CFLAGS-pthread_setcanceltype.c += -fexceptions -fasynchronous-unwind-tables
 
 # These are internal functions which similar functionality as setcancelstate
 # and setcanceltype.
-CFLAGS-cancellation.c += -fasynchronous-unwind-tables
 CFLAGS-libc-cancellation.c += -fasynchronous-unwind-tables
 
 # Calling pthread_exit() must cause the registered cancel handlers to
@@ -225,6 +223,8 @@ CFLAGS-fsync.c += -fexceptions -fasynchronous-unwind-tables
 
 CFLAGS-pt-system.c += -fexceptions
 
+CFLAGS-syscall_cancel.c = -fexceptions -fasynchronous-unwind-tables
+
 LDLIBS-tst-once5 = -lstdc++
 CFLAGS-tst-thread_local1.o = -std=gnu++11
 LDLIBS-tst-thread_local1 = -lstdc++
@@ -277,7 +277,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
 	tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \
 	tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \
 	tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel24 tst-cancel25 \
-	tst-cancel26 tst-cancel27 \
+	tst-cancel26 tst-cancel27 tst-cancel28 \
 	tst-cancel-self tst-cancel-self-cancelstate \
 	tst-cancel-self-canceltype tst-cancel-self-testcancel \
 	tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \
diff --git a/nptl/Versions b/nptl/Versions
index 0ae5def..734d47a 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -36,6 +36,9 @@ libc {
     __libc_pthread_init;
     __libc_current_sigrtmin_private; __libc_current_sigrtmax_private;
     __libc_allocate_rtsig_private;
+    __syscall_cancel;
+    __syscall_cancel_arch_start;
+    __syscall_cancel_arch_end;
   }
 }
 
diff --git a/nptl/cancellation.c b/nptl/cancellation.c
deleted file mode 100644
index 47a9b55..0000000
--- a/nptl/cancellation.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   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 <setjmp.h>
-#include <stdlib.h>
-#include "pthreadP.h"
-#include <futex-internal.h>
-
-
-/* The next two functions are similar to pthread_setcanceltype() but
-   more specialized for the use in the cancelable functions like write().
-   They do not need to check parameters etc.  */
-int
-attribute_hidden
-__pthread_enable_asynccancel (void)
-{
-  struct pthread *self = THREAD_SELF;
-  int oldval = THREAD_GETMEM (self, cancelhandling);
-
-  while (1)
-    {
-      int newval = oldval | CANCELTYPE_BITMASK;
-
-      if (newval == oldval)
-	break;
-
-      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
-					      oldval);
-      if (__glibc_likely (curval == oldval))
-	{
-	  if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
-	    {
-	      THREAD_SETMEM (self, result, PTHREAD_CANCELED);
-	      __do_cancel ();
-	    }
-
-	  break;
-	}
-
-      /* Prepare the next round.  */
-      oldval = curval;
-    }
-
-  return oldval;
-}
-
-
-void
-attribute_hidden
-__pthread_disable_asynccancel (int oldtype)
-{
-  /* If asynchronous cancellation was enabled before we do not have
-     anything to do.  */
-  if (oldtype & CANCELTYPE_BITMASK)
-    return;
-
-  struct pthread *self = THREAD_SELF;
-  int newval;
-
-  int oldval = THREAD_GETMEM (self, cancelhandling);
-
-  while (1)
-    {
-      newval = oldval & ~CANCELTYPE_BITMASK;
-
-      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
-					      oldval);
-      if (__glibc_likely (curval == oldval))
-	break;
-
-      /* Prepare the next round.  */
-      oldval = curval;
-    }
-
-  /* We cannot return when we are being canceled.  Upon return the
-     thread might be things which would have to be undone.  The
-     following loop should loop until the cancellation signal is
-     delivered.  */
-  while (__builtin_expect ((newval & (CANCELING_BITMASK | CANCELED_BITMASK))
-			   == CANCELING_BITMASK, 0))
-    {
-      futex_wait_simple ((unsigned int *) &self->cancelhandling, newval,
-			 FUTEX_PRIVATE);
-      newval = THREAD_GETMEM (self, cancelhandling);
-    }
-}
diff --git a/nptl/descr.h b/nptl/descr.h
index 64ba29e..4595165 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -278,23 +278,20 @@ struct pthread
   /* Bit set if asynchronous cancellation mode is selected.  */
 #define CANCELTYPE_BIT		1
 #define CANCELTYPE_BITMASK	(0x01 << CANCELTYPE_BIT)
-  /* Bit set if canceling has been initiated.  */
-#define CANCELING_BIT		2
-#define CANCELING_BITMASK	(0x01 << CANCELING_BIT)
-  /* Bit set if canceled.  */
-#define CANCELED_BIT		3
+  /* Bit set if threads is canceled.  */
+#define CANCELED_BIT		2
 #define CANCELED_BITMASK	(0x01 << CANCELED_BIT)
   /* Bit set if thread is exiting.  */
-#define EXITING_BIT		4
+#define EXITING_BIT		3
 #define EXITING_BITMASK		(0x01 << EXITING_BIT)
   /* Bit set if thread terminated and TCB is freed.  */
-#define TERMINATED_BIT		5
+#define TERMINATED_BIT		4
 #define TERMINATED_BITMASK	(0x01 << TERMINATED_BIT)
   /* Bit set if thread is supposed to change XID.  */
-#define SETXID_BIT		6
+#define SETXID_BIT		5
 #define SETXID_BITMASK		(0x01 << SETXID_BIT)
   /* Mask for the rest.  Helps the compiler to optimize.  */
-#define CANCEL_RESTMASK		0xffffff80
+#define CANCEL_RESTMASK		0xffffffc0
 
 #define CANCEL_ENABLED_AND_CANCELED(value) \
   (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK	      \
diff --git a/nptl/libc-cancellation.c b/nptl/libc-cancellation.c
index aef5b5d..9b054aa 100644
--- a/nptl/libc-cancellation.c
+++ b/nptl/libc-cancellation.c
@@ -16,9 +16,50 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <setjmp.h>
+#include <stdlib.h>
 #include "pthreadP.h"
 
+/* Cancellation function called by all cancellable syscalls.  */
+long int
+__syscall_cancel (__syscall_arg_t nr, __syscall_arg_t a1,
+		  __syscall_arg_t a2, __syscall_arg_t a3,
+		  __syscall_arg_t a4, __syscall_arg_t a5,
+		  __syscall_arg_t a6)
+{
+  pthread_t self = (pthread_t) THREAD_SELF;
+  volatile struct pthread *pd = (volatile struct pthread *) self;
+  long int result;
 
-#define __pthread_enable_asynccancel __libc_enable_asynccancel
-#define __pthread_disable_asynccancel __libc_disable_asynccancel
-#include <nptl/cancellation.c>
+  /* If cancellation is not enabled, call the syscall directly.  */
+  if (pd->cancelhandling & CANCELSTATE_BITMASK)
+    {
+      INTERNAL_SYSCALL_DECL (err);
+      result = INTERNAL_SYSCALL_NCS_CALL (nr, err, a1, a2, a3, a4, a5, a6);
+      if (INTERNAL_SYSCALL_ERROR_P (result, err))
+	return -INTERNAL_SYSCALL_ERRNO (result, err);
+      return result;
+    }
+
+  /* Call the arch-specific entry points that contains the globals markers
+     to be checked by SIGCANCEL handler.  */
+  result = __syscall_cancel_arch (&pd->cancelhandling, nr, a1, a2, a3, a4, a5,
+			          a6);
+
+  if ((result == -EINTR)
+      && (pd->cancelhandling & CANCELED_BITMASK)
+      && !(pd->cancelhandling & CANCELSTATE_BITMASK))
+    __syscall_do_cancel ();
+
+  return result;
+}
+libc_hidden_def (__syscall_cancel)
+
+/* Since __do_cancel is a always inline function, this creates a symbol the
+   arch-specific symbol can call to cancel the thread.  */
+void
+__cleanup_fct_attribute attribute_hidden __attribute ((noreturn))
+__syscall_do_cancel (void)
+{
+  __do_cancel ();
+}
diff --git a/nptl/lll_timedlock_wait.c b/nptl/lll_timedlock_wait.c
index 91bf963..f1f2bed 100644
--- a/nptl/lll_timedlock_wait.c
+++ b/nptl/lll_timedlock_wait.c
@@ -52,7 +52,7 @@ __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
         return ETIMEDOUT;
 
       /* If *futex == 2, wait until woken or timeout.  */
-      lll_futex_timed_wait (futex, 2, &rt, private);
+      lll_futex_timed_wait_cancel (futex, 2, &rt, private);
     }
 
   return 0;
diff --git a/nptl/lll_timedwait_tid.c b/nptl/lll_timedwait_tid.c
index c836a6f..e0b001c 100644
--- a/nptl/lll_timedwait_tid.c
+++ b/nptl/lll_timedwait_tid.c
@@ -62,7 +62,8 @@ __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
          The kernel up to version 3.16.3 does not use the private futex
          operations for futex wake-up when the clone terminates.
       */
-      if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
+      if (lll_futex_timed_wait_cancel (tidp, tid, &rt, LLL_SHARED)
+	  == -ETIMEDOUT)
         return ETIMEDOUT;
     }
 
diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c
index 5a4b524..5cf6de9 100644
--- a/nptl/nptl-init.c
+++ b/nptl/nptl-init.c
@@ -38,6 +38,7 @@
 #include <kernel-features.h>
 #include <libc-pointer-arith.h>
 #include <pthread-pids.h>
+#include <sigcontextinfo.h>
 
 #ifndef TLS_MULTIPLE_THREADS_IN_TCB
 /* Pointer to the corresponding variable in libc.  */
@@ -175,49 +176,65 @@ __nptl_set_robust (struct pthread *self)
 
 
 #ifdef SIGCANCEL
+
+extern const char __syscall_cancel_arch_start[1];
+extern const char __syscall_cancel_arch_end[1];
+
+/* Workaround for architectures which either does not define the mask
+   as a sigset (alpha) or does not call sa_sigaction with a ucontext_t
+   as third argument (sparc).  */
+# ifndef UCONTEXT_SIGMASK
+#  define UCONTEXT_SIGMASK(cxt) \
+  &(((ucontext_t*) (cxt))->uc_sigmask)
+# endif
+
 /* For asynchronous cancellation we use a signal.  This is the handler.  */
 static void
 sigcancel_handler (int sig, siginfo_t *si, void *ctx)
 {
+  INTERNAL_SYSCALL_DECL (err);
+  pid_t pid = INTERNAL_SYSCALL_CALL (getpid, err);
+
   /* Safety check.  It would be possible to call this function for
      other signals and send a signal from another process.  This is not
      correct and might even be a security problem.  Try to catch as
      many incorrect invocations as possible.  */
   if (sig != SIGCANCEL
-      || si->si_pid != __getpid()
+      || si->si_pid != pid
       || si->si_code != SI_TKILL)
     return;
 
   struct pthread *self = THREAD_SELF;
+  volatile struct pthread *pd = (volatile struct pthread *) self;
 
-  int oldval = THREAD_GETMEM (self, cancelhandling);
-  while (1)
+  if (((pd->cancelhandling & (CANCELSTATE_BITMASK)) != 0)
+      || ((pd->cancelhandling & CANCELED_BITMASK) == 0))
+    return;
+
+  /* Add SIGCANCEL on ignored sigmask to avoid the handler to be called
+     again.  */
+  sigset_t *set = UCONTEXT_SIGMASK (ctx);
+  __sigaddset (set, SIGCANCEL);
+
+  /* Check if asynchronous cancellation mode is set and if interrupted
+     instruction pointer falls within the cancellable syscall bridge.  For
+     interruptable syscalls that might generate external side-effects (partial
+     reads or writes, for instance), the kernel will set the IP to after
+     '__syscall_cancel_arch_end', thus disabling the cancellation and allowing
+     the process to handle such conditions.  */
+  uintptr_t pc = ucontext_get_pc (ctx);
+  if (pd->cancelhandling & CANCELTYPE_BITMASK
+      || (pc >= (uintptr_t) __syscall_cancel_arch_start
+          && pc < (uintptr_t) __syscall_cancel_arch_end))
     {
-      /* We are canceled now.  When canceled by another thread this flag
-	 is already set but if the signal is directly send (internally or
-	 from another process) is has to be done here.  */
-      int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
-
-      if (oldval == newval || (oldval & EXITING_BITMASK) != 0)
-	/* Already canceled or exiting.  */
-	break;
-
-      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
-					      oldval);
-      if (curval == oldval)
-	{
-	  /* Set the return value.  */
-	  THREAD_SETMEM (self, result, PTHREAD_CANCELED);
-
-	  /* Make sure asynchronous cancellation is still enabled.  */
-	  if ((newval & CANCELTYPE_BITMASK) != 0)
-	    /* Run the registered destructors and terminate the thread.  */
-	    __do_cancel ();
-
-	  break;
-	}
-
-      oldval = curval;
+      THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
+      THREAD_SETMEM (self, result, PTHREAD_CANCELED);
+
+      INTERNAL_SYSCALL_CALL (rt_sigprocmask, err, SIG_SETMASK, set, NULL,
+			     _NSIG / 8);
+
+      __do_cancel ();
+      return;
     }
 }
 #endif
@@ -372,7 +389,10 @@ __pthread_initialize_minimal_internal (void)
      cannot install the handler we do not abort.  Maybe we should, but
      it is only asynchronous cancellation which is affected.  */
   sa.sa_sigaction = sigcancel_handler;
-  sa.sa_flags = SA_SIGINFO;
+  /* The signal handle should be non-interruptible to avoid the risk of
+     spurious EINTR caused by SIGCANCEL sent to process or if pthread_cancel
+     is called while cancellation is disabled in the target thread.  */
+  sa.sa_flags = SA_SIGINFO | SA_RESTART;
   (void) __libc_sigaction (SIGCANCEL, &sa, NULL);
 # endif
 
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index 075530c..bb7ff81 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -291,51 +291,37 @@ __do_cancel (void)
 {
   struct pthread *self = THREAD_SELF;
 
-  /* Make sure we get no more cancellations.  */
-  THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
+  /* Make sure we get no more cancellations by clearing the cancel
+     state.  */
+  int oldval = THREAD_GETMEM (self, cancelhandling);
+  while (1)
+    {
+      int newval = (oldval | CANCELSTATE_BITMASK);
+      newval &= ~(CANCELTYPE_BITMASK);
+      if (oldval == newval)
+	break;
+
+      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+					  oldval);
+      if (__glibc_likely (curval == oldval))
+	break;
+      oldval = curval;
+    }
+
+  THREAD_SETMEM (self, result, PTHREAD_CANCELED);
 
   __pthread_unwind ((__pthread_unwind_buf_t *)
 		    THREAD_GETMEM (self, cleanup_jmp_buf));
 }
 
 
-/* Set cancellation mode to asynchronous.  */
-#define CANCEL_ASYNC() \
-  __pthread_enable_asynccancel ()
-/* Reset to previous cancellation mode.  */
-#define CANCEL_RESET(oldtype) \
-  __pthread_disable_asynccancel (oldtype)
-
-#if IS_IN (libc)
-/* Same as CANCEL_ASYNC, but for use in libc.so.  */
-# define LIBC_CANCEL_ASYNC() \
-  __libc_enable_asynccancel ()
-/* Same as CANCEL_RESET, but for use in libc.so.  */
-# define LIBC_CANCEL_RESET(oldtype) \
-  __libc_disable_asynccancel (oldtype)
-# define LIBC_CANCEL_HANDLED() \
-  __asm (".globl " __SYMBOL_PREFIX "__libc_enable_asynccancel"); \
-  __asm (".globl " __SYMBOL_PREFIX "__libc_disable_asynccancel")
-#elif IS_IN (libpthread)
-# define LIBC_CANCEL_ASYNC() CANCEL_ASYNC ()
-# define LIBC_CANCEL_RESET(val) CANCEL_RESET (val)
-# define LIBC_CANCEL_HANDLED() \
-  __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \
-  __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel")
-#elif IS_IN (librt)
-# define LIBC_CANCEL_ASYNC() \
-  __librt_enable_asynccancel ()
-# define LIBC_CANCEL_RESET(val) \
-  __librt_disable_asynccancel (val)
-# define LIBC_CANCEL_HANDLED() \
-  __asm (".globl " __SYMBOL_PREFIX "__librt_enable_asynccancel"); \
-  __asm (".globl " __SYMBOL_PREFIX "__librt_disable_asynccancel")
-#else
-# define LIBC_CANCEL_ASYNC()	0 /* Just a dummy value.  */
-# define LIBC_CANCEL_RESET(val)	((void)(val)) /* Nothing, but evaluate it.  */
-# define LIBC_CANCEL_HANDLED()	/* Nothing.  */
-#endif
+extern long int __syscall_cancel_arch (volatile int *, __syscall_arg_t nr,
+     __syscall_arg_t arg1, __syscall_arg_t arg2, __syscall_arg_t arg3,
+     __syscall_arg_t arg4, __syscall_arg_t arg5, __syscall_arg_t arg6);
+libc_hidden_proto (__syscall_cancel_arch);
 
+extern void __syscall_do_cancel (void)
+     __cleanup_fct_attribute attribute_hidden __attribute ((__noreturn__));
 
 /* Internal prototypes.  */
 
@@ -503,8 +489,6 @@ extern int __pthread_kill (pthread_t threadid, int signo);
 extern void __pthread_exit (void *value) __attribute__ ((__noreturn__));
 extern int __pthread_join (pthread_t threadid, void **thread_return);
 extern int __pthread_setcanceltype (int type, int *oldtype);
-extern int __pthread_enable_asynccancel (void) attribute_hidden;
-extern void __pthread_disable_asynccancel (int oldtype) attribute_hidden;
 extern void __pthread_testcancel (void);
 extern int __pthread_timedjoin_ex (pthread_t, void **, const struct timespec *,
 				   bool);
@@ -543,15 +527,6 @@ extern int __pthread_cond_wait_2_0 (pthread_cond_2_0_t *cond,
 extern int __pthread_getaffinity_np (pthread_t th, size_t cpusetsize,
 				     cpu_set_t *cpuset);
 
-/* The two functions are in libc.so and not exported.  */
-extern int __libc_enable_asynccancel (void) attribute_hidden;
-extern void __libc_disable_asynccancel (int oldtype) attribute_hidden;
-
-
-/* The two functions are in librt.so and not exported.  */
-extern int __librt_enable_asynccancel (void) attribute_hidden;
-extern void __librt_disable_asynccancel (int oldtype) attribute_hidden;
-
 #if IS_IN (libpthread)
 /* Special versions which use non-exported functions.  */
 extern void __pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c
index 84c8c4e..20ff7e0 100644
--- a/nptl/pthread_cancel.c
+++ b/nptl/pthread_cancel.c
@@ -37,67 +37,23 @@ __pthread_cancel (pthread_t th)
 #ifdef SHARED
   pthread_cancel_init ();
 #endif
-  int result = 0;
-  int oldval;
-  int newval;
-  do
-    {
-    again:
-      oldval = pd->cancelhandling;
-      newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
 
-      /* Avoid doing unnecessary work.  The atomic operation can
-	 potentially be expensive if the bug has to be locked and
-	 remote cache lines have to be invalidated.  */
-      if (oldval == newval)
-	break;
+  THREAD_ATOMIC_BIT_SET (pd, cancelhandling, CANCELED_BIT);
 
-      /* If the cancellation is handled asynchronously just send a
-	 signal.  We avoid this if possible since it's more
-	 expensive.  */
-      if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
-	{
-	  /* Mark the cancellation as "in progress".  */
-	  if (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling,
-						    oldval | CANCELING_BITMASK,
-						    oldval))
-	    goto again;
-
-#ifdef SIGCANCEL
-	  /* The cancellation handler will take care of marking the
-	     thread as canceled.  */
-	  pid_t pid = __getpid ();
-
-	  INTERNAL_SYSCALL_DECL (err);
-	  int val = INTERNAL_SYSCALL_CALL (tgkill, err, pid, pd->tid,
-					   SIGCANCEL);
-	  if (INTERNAL_SYSCALL_ERROR_P (val, err))
-	    result = INTERNAL_SYSCALL_ERRNO (val, err);
-#else
-          /* It should be impossible to get here at all, since
-             pthread_setcanceltype should never have allowed
-             PTHREAD_CANCEL_ASYNCHRONOUS to be set.  */
-          abort ();
-#endif
-
-	  break;
-	}
-
-	/* A single-threaded process should be able to kill itself, since
-	   there is nothing in the POSIX specification that says that it
-	   cannot.  So we set multiple_threads to true so that cancellation
-	   points get executed.  */
-	THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
+  /* A single-threaded process should be able to kill itself, since there is
+     nothing in the POSIX specification that says that it cannot.  So we set
+     multiple_threads to true so that cancellation points get executed.  */
+  THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
 #ifndef TLS_MULTIPLE_THREADS_IN_TCB
-	__pthread_multiple_threads = *__libc_multiple_threads_ptr = 1;
+  __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1;
 #endif
-    }
-  /* Mark the thread as canceled.  This has to be done
-     atomically since other bits could be modified as well.  */
-  while (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling, newval,
-					       oldval));
 
-  return result;
+  /* Avoid signaling when thread attempts cancel itself (pthread_kill
+     is expensive).  */
+  if (pd == THREAD_SELF && !(pd->cancelhandling & CANCELTYPE_BITMASK))
+    return 0;
+
+  return __pthread_kill (th, SIGCANCEL);
 }
 weak_alias (__pthread_cancel, pthread_cancel)
 
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index caaf07c..cf0dc37 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -412,7 +412,7 @@ START_THREAD_DEFN
   /* If the parent was running cancellation handlers while creating
      the thread the new thread inherited the signal mask.  Reset the
      cancellation signal mask.  */
-  if (__glibc_unlikely (pd->parent_cancelhandling & CANCELING_BITMASK))
+  if (__glibc_unlikely (pd->parent_cancelhandling & CANCELED_BITMASK))
     {
       INTERNAL_SYSCALL_DECL (err);
       sigset_t mask;
@@ -444,7 +444,8 @@ START_THREAD_DEFN
 	 have ownership (see CONCURRENCY NOTES above).  */
       if (__glibc_unlikely (pd->stopped_start))
 	{
-	  int oldtype = CANCEL_ASYNC ();
+	  int ct;
+	  __pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &ct);
 
 	  /* Get the lock the parent locked to force synchronization.  */
 	  lll_lock (pd->lock, LLL_PRIVATE);
@@ -454,7 +455,7 @@ START_THREAD_DEFN
 	  /* And give it up right away.  */
 	  lll_unlock (pd->lock, LLL_PRIVATE);
 
-	  CANCEL_RESET (oldtype);
+	  __pthread_setcanceltype (ct, NULL);
 	}
 
       LIBC_PROBE (pthread_start, 3, (pthread_t) pd, pd->start_routine, pd->arg);
diff --git a/nptl/pthread_exit.c b/nptl/pthread_exit.c
index c8383e4..b69dee3 100644
--- a/nptl/pthread_exit.c
+++ b/nptl/pthread_exit.c
@@ -23,9 +23,14 @@
 void
 __pthread_exit (void *value)
 {
-  THREAD_SETMEM (THREAD_SELF, result, value);
+  struct pthread *self = THREAD_SELF;
 
-  __do_cancel ();
+  THREAD_SETMEM (self, result, value);
+
+  THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
+
+  __pthread_unwind ((__pthread_unwind_buf_t *)
+		    THREAD_GETMEM (self, cleanup_jmp_buf));
 }
 weak_alias (__pthread_exit, pthread_exit)
 
diff --git a/nptl/pthread_join_common.c b/nptl/pthread_join_common.c
index 702fcd1..9b2adc6 100644
--- a/nptl/pthread_join_common.c
+++ b/nptl/pthread_join_common.c
@@ -54,7 +54,7 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return,
   if ((pd == self
        || (self->joinid == pd
 	   && (pd->cancelhandling
-	       & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
+	       & (CANCELED_BITMASK | EXITING_BITMASK
 		  | TERMINATED_BITMASK)) == 0))
       && !CANCEL_ENABLED_AND_CANCELED (self->cancelhandling))
     /* This is a deadlock situation.  The threads are waiting for each
@@ -81,14 +81,15 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return,
 	 un-wait-ed for again.  */
       pthread_cleanup_push (cleanup, &pd->joinid);
 
-      int oldtype = CANCEL_ASYNC ();
+      int ct;
+      __pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &ct);
 
       if (abstime != NULL)
 	result = lll_timedwait_tid (pd->tid, abstime);
       else
 	lll_wait_tid (pd->tid);
 
-      CANCEL_RESET (oldtype);
+      __pthread_setcanceltype (ct, NULL);
 
       pthread_cleanup_pop (0);
     }
diff --git a/nptl/sem_wait.c b/nptl/sem_wait.c
index e7d9106..e057b05 100644
--- a/nptl/sem_wait.c
+++ b/nptl/sem_wait.c
@@ -56,14 +56,8 @@ __old_sem_wait (sem_t *sem)
       if (atomic_decrement_if_positive (futex) > 0)
 	return 0;
 
-      /* Enable asynchronous cancellation.  Required by the standard.  */
-      int oldtype = __pthread_enable_asynccancel ();
-
       /* Always assume the semaphore is shared.  */
-      err = lll_futex_wait (futex, 0, LLL_SHARED);
-
-      /* Disable asynchronous cancellation.  */
-      __pthread_disable_asynccancel (oldtype);
+      err = lll_futex_wait_cancel (futex, 0, LLL_SHARED);
     }
   while (err == 0 || err == -EWOULDBLOCK);
 
diff --git a/nptl/tst-cancel28.c b/nptl/tst-cancel28.c
new file mode 100644
index 0000000..185dedd
--- /dev/null
+++ b/nptl/tst-cancel28.c
@@ -0,0 +1,94 @@
+/* Check side-effect act for cancellable syscalls (BZ #12683).
+   Copyright (C) 2017 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/>.  */
+
+/* This testcase checks if there is resource leakage if the syscall has
+   returned from kernelspace, but before userspace saves the return
+   value.  The 'leaker' thread should be able to close the file descriptor
+   if the resource is already allocated, meaning that if the cancellation
+   signal arrives *after* the open syscal return from kernel, the
+   side-effect should be visible to application.  */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <support/xthread.h>
+#include <support/check.h>
+#include <support/temp_file.h>
+
+static void *
+writeopener (void *arg)
+{
+  int fd;
+  for (;;)
+    {
+      fd = open (arg, O_WRONLY);
+      close (fd);
+    }
+  return NULL;
+}
+
+static void *
+leaker (void *arg)
+{
+  int fd = open (arg, O_RDONLY);
+  pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, 0);
+  close (fd);
+  return NULL;
+}
+
+
+#define ITER_COUNT 1000
+#define MAX_FILENO 1024
+
+static int
+do_test (void)
+{
+  struct stat st;
+  int i;
+
+  char *name = NULL;
+  support_create_temp_fifo ("tst-cancel28", &name);
+
+  srand (1);
+
+  xpthread_create (NULL, writeopener, name);
+  for (i = 0; i < ITER_COUNT; i++)
+    {
+      pthread_t td = xpthread_create (NULL, leaker, name);
+      struct timespec ts =
+	{ .tv_nsec = rand () % 100000, .tv_sec = 0 };
+      nanosleep (&ts, NULL);
+      /* Ignore pthread_cancel result because it might be the
+	 case when pthread_cancel is called when thread is already
+	 exited.  */
+      pthread_cancel (td);
+      xpthread_join (td);
+    }
+
+  for (i = STDERR_FILENO+1; i < MAX_FILENO; i++)
+    if (fstat (i, &st) == 0)
+      FAIL_EXIT1 ("leaked fd %d", i);
+
+  return 0;
+}
+
+#define TIMEOUT 10
+#include <support/test-driver.c>
diff --git a/rt/Makefile b/rt/Makefile
index 6d6b896..9c32752 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -64,7 +64,6 @@ CFLAGS-aio_suspend.c += -fexceptions
 CFLAGS-mq_timedreceive.c += -fexceptions -fasynchronous-unwind-tables
 CFLAGS-mq_timedsend.c += -fexceptions -fasynchronous-unwind-tables
 CFLAGS-clock_nanosleep.c += -fexceptions -fasynchronous-unwind-tables
-CFLAGS-librt-cancellation.c += -fasynchronous-unwind-tables
 
 LDFLAGS-rt.so = -Wl,--enable-new-dtags,-z,nodelete
 
diff --git a/support/temp_file.c b/support/temp_file.c
index 0bbc7f9..362ef17 100644
--- a/support/temp_file.c
+++ b/support/temp_file.c
@@ -86,6 +86,29 @@ create_temp_file (const char *base, char **filename)
   return fd;
 }
 
+int
+support_create_temp_fifo (const char *base, char **fifoname)
+{
+  char *fname = xasprintf ("%s/%sXXXXXX", test_dir, base);
+  mktemp (fname);
+
+  int fd = mkfifo (fname, 0600);
+  if (fd == -1)
+    {
+      printf ("cannot open temporary fifo '%s': %m\n", fname);
+      free (fname);
+      return -1;
+    }
+
+  add_temp_file (fname);
+  if (fifoname != NULL)
+    *fifoname = fname;
+  else
+    free (fname);
+
+  return fd;
+}
+
 char *
 support_create_temp_directory (const char *base)
 {
diff --git a/support/temp_file.h b/support/temp_file.h
index c7795cc..081b241 100644
--- a/support/temp_file.h
+++ b/support/temp_file.h
@@ -32,6 +32,12 @@ void add_temp_file (const char *name);
    *FILENAME.  */
 int create_temp_file (const char *base, char **filename);
 
+/* Create a temporary fifo.  Return the opened file descriptor on
+   success, or -1 on failure.  Write the file name to *FILENAME if
+   FILENAME is not NULL.  In this case, the caller is expected to free
+   *FILENAME.  */
+int support_create_temp_fifo (const char *name, char **fifoname);
+
 /* Create a temporary directory and schedule it for deletion.  BASE is
    used as a prefix for the unique directory name, which the function
    returns.  The caller should free this string.  */
diff --git a/sysdeps/generic/sigcontextinfo.h b/sysdeps/generic/sigcontextinfo.h
index 078b034..60fdf0e 100644
--- a/sysdeps/generic/sigcontextinfo.h
+++ b/sysdeps/generic/sigcontextinfo.h
@@ -16,6 +16,11 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
+
 /* In general we cannot provide any information.  */
 #define SIGCONTEXT struct sigcontext *
 #define SIGCONTEXT_EXTRA_ARGS
@@ -24,3 +29,13 @@
 #define GET_STACK(ctx)	((void *) 0)
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+/* Obtain the Program Counter from third argument in signal handler set
+   with SA_SIGINFO.  */
+static inline uintptr_t
+ucontext_get_pc (void *ctx)
+{
+  return 0;
+}
+
+#endif
diff --git a/sysdeps/generic/sysdep-cancel.h b/sysdeps/generic/sysdep-cancel.h
index ba6a1e0..5c84b44 100644
--- a/sysdeps/generic/sysdep-cancel.h
+++ b/sysdeps/generic/sysdep-cancel.h
@@ -3,6 +3,3 @@
 /* No multi-thread handling enabled.  */
 #define SINGLE_THREAD_P (1)
 #define RTLD_SINGLE_THREAD_P (1)
-#define LIBC_CANCEL_ASYNC()	0 /* Just a dummy value.  */
-#define LIBC_CANCEL_RESET(val)	((void)(val)) /* Nothing, but evaluate it.  */
-#define LIBC_CANCEL_HANDLED()	/* Nothing.  */
diff --git a/sysdeps/nptl/Makefile b/sysdeps/nptl/Makefile
index 6b87b82..f537fc0 100644
--- a/sysdeps/nptl/Makefile
+++ b/sysdeps/nptl/Makefile
@@ -21,8 +21,7 @@ libpthread-sysdep_routines += errno-loc
 endif
 
 ifeq ($(subdir),rt)
-librt-sysdep_routines += timer_routines librt-cancellation
-CFLAGS-librt-cancellation.c += -fexceptions -fasynchronous-unwind-tables
+librt-sysdep_routines += timer_routines
 
 tests += tst-mqueue8x
 CFLAGS-tst-mqueue8x.c += -fexceptions
diff --git a/sysdeps/nptl/aio_misc.h b/sysdeps/nptl/aio_misc.h
index 206d8e1..92c262d 100644
--- a/sysdeps/nptl/aio_misc.h
+++ b/sysdeps/nptl/aio_misc.h
@@ -34,22 +34,18 @@
 
 #define AIO_MISC_WAIT(result, futex, timeout, cancel)			      \
   do {									      \
-    volatile unsigned int *futexaddr = &futex;				      \
+    unsigned int *futexaddr = (unsigned int *)&futex;			      \
     unsigned int oldval = futex;					      \
 									      \
     if (oldval != 0)							      \
       {									      \
 	pthread_mutex_unlock (&__aio_requests_mutex);			      \
 									      \
-	int oldtype;							      \
-	if (cancel)							      \
-	  oldtype = LIBC_CANCEL_ASYNC ();				      \
-									      \
 	int status;							      \
 	do								      \
 	  {								      \
-	    status = futex_reltimed_wait ((unsigned int *) futexaddr, oldval, \
-					  timeout, FUTEX_PRIVATE);	      \
+	    status = futex_reltimed_wait_cancelable (futexaddr, oldval,	      \
+						     timeout, FUTEX_PRIVATE); \
 	    if (status != EAGAIN)					      \
 	      break;							      \
 									      \
@@ -57,9 +53,6 @@
 	  }								      \
 	while (oldval != 0);						      \
 									      \
-	if (cancel)							      \
-	  LIBC_CANCEL_RESET (oldtype);					      \
-									      \
 	if (status == EINTR)						      \
 	  result = EINTR;						      \
 	else if (status == ETIMEDOUT)					      \
diff --git a/sysdeps/nptl/gai_misc.h b/sysdeps/nptl/gai_misc.h
index 815e6c0..3dca11e 100644
--- a/sysdeps/nptl/gai_misc.h
+++ b/sysdeps/nptl/gai_misc.h
@@ -35,22 +35,18 @@
 
 #define GAI_MISC_WAIT(result, futex, timeout, cancel) \
   do {									      \
-    volatile unsigned int *futexaddr = &futex;				      \
+    unsigned int *futexaddr = (unsigned int *)&futex;			      \
     unsigned int oldval = futex;					      \
 									      \
     if (oldval != 0)							      \
       {									      \
 	pthread_mutex_unlock (&__gai_requests_mutex);			      \
 									      \
-	int oldtype;							      \
-	if (cancel)							      \
-	  oldtype = LIBC_CANCEL_ASYNC ();				      \
-									      \
 	int status;							      \
 	do								      \
 	  {								      \
-	    status = futex_reltimed_wait ((unsigned int *) futexaddr, oldval, \
-					  timeout, FUTEX_PRIVATE);	      \
+	    status = futex_reltimed_wait_cancelable (futexaddr, oldval,	      \
+						     timeout, FUTEX_PRIVATE); \
 	    if (status != EAGAIN)					      \
 	      break;							      \
 									      \
@@ -58,9 +54,6 @@
 	  }								      \
 	while (oldval != 0);						      \
 									      \
-	if (cancel)							      \
-	  LIBC_CANCEL_RESET (oldtype);					      \
-									      \
 	if (status == EINTR)						      \
 	  result = EINTR;						      \
 	else if (status == ETIMEDOUT)					      \
diff --git a/sysdeps/nptl/librt-cancellation.c b/sysdeps/nptl/librt-cancellation.c
deleted file mode 100644
index 39c5991..0000000
--- a/sysdeps/nptl/librt-cancellation.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   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 <nptl/pthreadP.h>
-
-
-#define __pthread_enable_asynccancel __librt_enable_asynccancel
-#define __pthread_disable_asynccancel __librt_disable_asynccancel
-#include <nptl/cancellation.c>
diff --git a/sysdeps/nptl/lowlevellock.h b/sysdeps/nptl/lowlevellock.h
index 8326e28..5af4a48 100644
--- a/sysdeps/nptl/lowlevellock.h
+++ b/sysdeps/nptl/lowlevellock.h
@@ -180,12 +180,13 @@ extern int __lll_timedlock_wait (int *futex, const struct timespec *,
    wake-up when the clone terminates.  The memory location contains the
    thread ID while the clone is running and is reset to zero by the kernel
    afterwards.  The kernel up to version 3.16.3 does not use the private futex
-   operations for futex wake-up when the clone terminates.  */
+   operations for futex wake-up when the clone terminates.
+   Both lll_wait_tid and lll_timewait_tid acts as cancellation points.  */
 #define lll_wait_tid(tid) \
   do {					\
     __typeof (tid) __tid;		\
     while ((__tid = (tid)) != 0)	\
-      lll_futex_wait (&(tid), __tid, LLL_SHARED);\
+      lll_futex_wait_cancel (&(tid), __tid, LLL_SHARED);\
   } while (0)
 
 extern int __lll_timedwait_tid (int *, const struct timespec *)
diff --git a/sysdeps/posix/open64.c b/sysdeps/posix/open64.c
index c4209c8..e4ec5d1 100644
--- a/sysdeps/posix/open64.c
+++ b/sysdeps/posix/open64.c
@@ -34,16 +34,8 @@ __libc_open64 (const char *file, int oflag, ...)
       va_end (arg);
     }
 
-  if (SINGLE_THREAD_P)
-    return __libc_open (file, oflag | O_LARGEFILE, mode);
-
-  int oldtype = LIBC_CANCEL_ASYNC ();
-
-  int result = __libc_open (file, oflag | O_LARGEFILE, mode);
-
-  LIBC_CANCEL_RESET (oldtype);
-
-  return result;
+  /* __libc_open should be a cancellation point.  */
+  return __libc_open (file, oflag | O_LARGEFILE, mode);
 }
 weak_alias (__libc_open64, __open64)
 libc_hidden_weak (__open64)
diff --git a/sysdeps/posix/pause.c b/sysdeps/posix/pause.c
index 2b9eca2..879a8ab 100644
--- a/sysdeps/posix/pause.c
+++ b/sysdeps/posix/pause.c
@@ -38,5 +38,3 @@ __libc_pause (void)
   return __sigsuspend (&set);
 }
 weak_alias (__libc_pause, pause)
-
-LIBC_CANCEL_HANDLED ();		/* sigsuspend handles our cancellation.  */
diff --git a/sysdeps/posix/sigpause.c b/sysdeps/posix/sigpause.c
index db9df8e..9a17d1b 100644
--- a/sysdeps/posix/sigpause.c
+++ b/sysdeps/posix/sigpause.c
@@ -70,6 +70,3 @@ __xpg_sigpause (int sig)
   return __sigpause (sig, 1);
 }
 strong_alias (__xpg_sigpause, __libc___xpg_sigpause)
-
-/* __sigsuspend handles cancellation.  */
-LIBC_CANCEL_HANDLED ();
diff --git a/sysdeps/posix/sigwait.c b/sysdeps/posix/sigwait.c
index 4ff9d84..2387ecc 100644
--- a/sysdeps/posix/sigwait.c
+++ b/sysdeps/posix/sigwait.c
@@ -88,13 +88,8 @@ __sigwait (const sigset_t *set, int *sig)
   if (SINGLE_THREAD_P)
     return do_sigwait (set, sig);
 
-  int oldtype = LIBC_CANCEL_ASYNC ();
-
-  int result = do_sigwait (set, sig);
-
-  LIBC_CANCEL_RESET (oldtype);
-
-  return result;
+  /* do_sigwait should be a cancellation point.  */
+  return do_sigwait (set, sig);
 }
 libc_hidden_def (__sigwait)
 weak_alias (__sigwait, sigwait)
diff --git a/sysdeps/posix/waitid.c b/sysdeps/posix/waitid.c
index 3207c74..7be34d2 100644
--- a/sysdeps/posix/waitid.c
+++ b/sysdeps/posix/waitid.c
@@ -151,16 +151,7 @@ OUR_WAITID (idtype_t idtype, id_t id, siginfo_t *infop, int options)
 int
 __waitid (idtype_t idtype, id_t id, siginfo_t *infop, int options)
 {
-  if (SINGLE_THREAD_P)
-    return do_waitid (idtype, id, infop, options);
-
-  int oldtype = LIBC_CANCEL_ASYNC ();
-
-  int result = do_waitid (idtype, id, infop, options);
-
-  LIBC_CANCEL_RESET (oldtype);
-
-  return result;
+  return do_waitid (idtype, id, infop, options);
 }
 weak_alias (__waitid, waitid)
 strong_alias (__waitid, __libc_waitid)
diff --git a/sysdeps/sparc/sparc32/lowlevellock.c b/sysdeps/sparc/sparc32/lowlevellock.c
index 8b18559..3b4cca6 100644
--- a/sysdeps/sparc/sparc32/lowlevellock.c
+++ b/sysdeps/sparc/sparc32/lowlevellock.c
@@ -122,7 +122,8 @@ __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
 
       /* Wait until thread terminates.  The kernel so far does not use
 	 the private futex operations for this.  */
-      if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
+      if (lll_futex_timed_wait_cancel (tidp, tid, &rt, LLL_SHARED)
+	  == -ETIMEDOUT)
 	return ETIMEDOUT;
     }
 
diff --git a/sysdeps/unix/sysdep.h b/sysdeps/unix/sysdep.h
index aac9303..cea81a5 100644
--- a/sysdeps/unix/sysdep.h
+++ b/sysdeps/unix/sysdep.h
@@ -24,6 +24,9 @@
 #define	SYSCALL__(name, args)	PSEUDO (__##name, name, args)
 #define	SYSCALL(name, args)	PSEUDO (name, name, args)
 
+#ifndef __ASSEMBLER__
+# include <errno.h>
+
 #define __SYSCALL_CONCAT_X(a,b)     a##b
 #define __SYSCALL_CONCAT(a,b)       __SYSCALL_CONCAT_X (a, b)
 
@@ -57,6 +60,29 @@
 #define INTERNAL_SYSCALL_CALL(...) \
   __INTERNAL_SYSCALL_DISP (__INTERNAL_SYSCALL, __VA_ARGS__)
 
+#define __INTERNAL_SYSCALL_NCS0(name, err) \
+  INTERNAL_SYSCALL_NCS (name, err, 0)
+#define __INTERNAL_SYSCALL_NCS1(name, err, a1) \
+  INTERNAL_SYSCALL_NCS (name, err, 1, a1)
+#define __INTERNAL_SYSCALL_NCS2(name, err, a1, a2) \
+  INTERNAL_SYSCALL_NCS (name, err, 2, a1, a2)
+#define __INTERNAL_SYSCALL_NCS3(name, err, a1, a2, a3) \
+  INTERNAL_SYSCALL_NCS (name, err, 3, a1, a2, a3)
+#define __INTERNAL_SYSCALL_NCS4(name, err, a1, a2, a3, a4) \
+  INTERNAL_SYSCALL_NCS (name, err, 4, a1, a2, a3, a4)
+#define __INTERNAL_SYSCALL_NCS5(name, err, a1, a2, a3, a4, a5) \
+  INTERNAL_SYSCALL_NCS (name, err, 5, a1, a2, a3, a4, a5)
+#define __INTERNAL_SYSCALL_NCS6(name, err, a1, a2, a3, a4, a5, a6) \
+  INTERNAL_SYSCALL_NCS (name, err, 6, a1, a2, a3, a4, a5, a6)
+#define __INTERNAL_SYSCALL_NCS7(name, err, a1, a2, a3, a4, a5, a6, a7) \
+  INTERNAL_SYSCALL_NCS (name, err, 7, a1, a2, a3, a4, a5, a6, a7)
+
+/* Issue a syscall defined by syscall number plus any other argument required.
+   It is similar to INTERNAL_SYSCALL_NCS macro, but without the need to pass
+   the expected argument number as third parameter.  */
+#define INTERNAL_SYSCALL_NCS_CALL(...) \
+  __INTERNAL_SYSCALL_DISP (__INTERNAL_SYSCALL_NCS, __VA_ARGS__)
+
 #define __INLINE_SYSCALL0(name) \
   INLINE_SYSCALL (name, 0)
 #define __INLINE_SYSCALL1(name, a1) \
@@ -88,19 +114,65 @@
 #define INLINE_SYSCALL_CALL(...) \
   __INLINE_SYSCALL_DISP (__INLINE_SYSCALL, __VA_ARGS__)
 
-#define SYSCALL_CANCEL(...) \
-  ({									     \
-    long int sc_ret;							     \
-    if (SINGLE_THREAD_P) 						     \
-      sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); 			     \
-    else								     \
-      {									     \
-	int sc_cancel_oldtype = LIBC_CANCEL_ASYNC ();			     \
-	sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__);			     \
-        LIBC_CANCEL_RESET (sc_cancel_oldtype);				     \
-      }									     \
-    sc_ret;								     \
+
+/* Cancellation macros.  */
+#ifndef __SSC
+typedef long int __syscall_arg_t;
+# define __SSC(__x) ((__syscall_arg_t) (__x))
+#endif
+
+long int __syscall_cancel (__syscall_arg_t nr, __syscall_arg_t arg1,
+			   __syscall_arg_t arg2, __syscall_arg_t arg3,
+			   __syscall_arg_t arg4, __syscall_arg_t arg5,
+			   __syscall_arg_t arg6);
+libc_hidden_proto (__syscall_cancel);
+
+#define __SYSCALL_CANCEL0(name) \
+  (__syscall_cancel)(__NR_##name, 0, 0, 0, 0, 0, 0)
+#define __SYSCALL_CANCEL1(name, a1) \
+  (__syscall_cancel)(__NR_##name, __SSC(a1), 0, 0, 0, 0, 0)
+#define __SYSCALL_CANCEL2(name, a1, a2) \
+  (__syscall_cancel)(__NR_##name, __SSC(a1), __SSC(a2), 0, 0, 0, 0)
+#define __SYSCALL_CANCEL3(name, a1, a2, a3) \
+  (__syscall_cancel)(__NR_##name, __SSC(a1), __SSC(a2), __SSC(a3), 0, 0, 0)
+#define __SYSCALL_CANCEL4(name, a1, a2, a3, a4) \
+  (__syscall_cancel)(__NR_##name, __SSC(a1), __SSC(a2), __SSC(a3), \
+		     __SSC(a4), 0, 0)
+#define __SYSCALL_CANCEL5(name, a1, a2, a3, a4, a5) \
+  (__syscall_cancel)(__NR_##name, __SSC(a1), __SSC(a2), __SSC(a3), \
+		     __SSC(a4), __SSC(a5), 0)
+#define __SYSCALL_CANCEL6(name, a1, a2, a3, a4, a5, a6) \
+  (__syscall_cancel)(__NR_##name, __SSC(a1), __SSC(a2), __SSC(a3), \
+		     __SSC(a4), __SSC(a5), __SSC(a6))
+
+#define __SYSCALL_CANCEL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n
+#define __SYSCALL_CANCEL_NARGS(...) \
+  __SYSCALL_CANCEL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,)
+#define __SYSCALL_CANCEL_CONCAT_X(a,b)     a##b
+#define __SYSCALL_CANCEL_CONCAT(a,b)       __SYSCALL_CANCEL_CONCAT_X (a, b)
+#define __SYSCALL_CANCEL_DISP(b,...) \
+  __SYSCALL_CANCEL_CONCAT (b,__SYSCALL_CANCEL_NARGS(__VA_ARGS__))(__VA_ARGS__)
+
+#define __SYSCALL_CANCEL_CALL(...) \
+  __SYSCALL_CANCEL_DISP (__SYSCALL_CANCEL, __VA_ARGS__)
+
+#define SYSCALL_CANCEL_NCS(name, nr, args...) \
+  __SYSCALL_CANCEL_CALL (name, nr, args)
+
+
+/* The loader does not need to handle thread cancellation, use direct
+   syscall instead.  */
+#if IS_IN (rtld)
+# define SYSCALL_CANCEL(...) INLINE_SYSCALL_CALL (__VA_ARGS__)
+#else
+# define SYSCALL_CANCEL(...) \
+  ({									\
+    long int sc_ret = __SYSCALL_CANCEL_CALL (__VA_ARGS__);		\
+    SYSCALL_CANCEL_RET ((sc_ret));					\
   })
+#endif
+
+#endif /* __ASSEMBLER__  */
 
 /* Machine-dependent sysdep.h files are expected to define the macro
    PSEUDO (function_name, syscall_name) to emit assembly code to define the
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 93d5d6e..7f86c10 100644
--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
+++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
@@ -28,27 +28,13 @@ int
 __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
 		   struct timespec *rem)
 {
-  INTERNAL_SYSCALL_DECL (err);
-  int r;
-
   if (clock_id == CLOCK_THREAD_CPUTIME_ID)
     return EINVAL;
   if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
     clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);
 
-  if (SINGLE_THREAD_P)
-    r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req, rem);
-  else
-    {
-      int oldstate = LIBC_CANCEL_ASYNC ();
-
-      r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req,
-			    rem);
-
-      LIBC_CANCEL_RESET (oldstate);
-    }
-
-  return (INTERNAL_SYSCALL_ERROR_P (r, err)
-	  ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
+  /* If the call is interrupted by a signal handler or encounters an error,
+     it returns a positive value similar to errno.  */
+  return -SYSCALL_CANCEL_NCS (clock_nanosleep, clock_id, flags, req, rem);
 }
 weak_alias (__clock_nanosleep, clock_nanosleep)
diff --git a/sysdeps/unix/sysv/linux/creat.c b/sysdeps/unix/sysv/linux/creat.c
index c996cbd..089a869 100644
--- a/sysdeps/unix/sysv/linux/creat.c
+++ b/sysdeps/unix/sysv/linux/creat.c
@@ -35,6 +35,4 @@ __creat (const char *file, mode_t mode)
 }
 weak_alias (__creat, creat)
 
-LIBC_CANCEL_HANDLED ();
-
 #endif
diff --git a/sysdeps/unix/sysv/linux/creat64.c b/sysdeps/unix/sysv/linux/creat64.c
index d3ada38..c9eba2e 100644
--- a/sysdeps/unix/sysv/linux/creat64.c
+++ b/sysdeps/unix/sysv/linux/creat64.c
@@ -37,5 +37,3 @@ weak_alias (__creat64, creat64)
 strong_alias (__creat64, __creat)
 weak_alias (__creat64, creat)
 #endif
-
-LIBC_CANCEL_HANDLED ();
diff --git a/sysdeps/unix/sysv/linux/futex-internal.h b/sysdeps/unix/sysv/linux/futex-internal.h
index 96a07b0..9f25bfc 100644
--- a/sysdeps/unix/sysv/linux/futex-internal.h
+++ b/sysdeps/unix/sysv/linux/futex-internal.h
@@ -83,10 +83,7 @@ static __always_inline int
 futex_wait_cancelable (unsigned int *futex_word, unsigned int expected,
 		       int private)
 {
-  int oldtype;
-  oldtype = __pthread_enable_asynccancel ();
-  int err = lll_futex_timed_wait (futex_word, expected, NULL, private);
-  __pthread_disable_asynccancel (oldtype);
+  int err = lll_futex_timed_wait_cancel (futex_word, expected, NULL, private);
   switch (err)
     {
     case 0:
@@ -137,10 +134,7 @@ futex_reltimed_wait_cancelable (unsigned int *futex_word,
 				unsigned int expected,
 			        const struct timespec *reltime, int private)
 {
-  int oldtype;
-  oldtype = __pthread_enable_asynccancel ();
-  int err = lll_futex_timed_wait (futex_word, expected, reltime, private);
-  __pthread_disable_asynccancel (oldtype);
+  int err = lll_futex_timed_wait_cancel (futex_word, expected, reltime, private);
   switch (err)
     {
     case 0:
@@ -200,11 +194,9 @@ futex_abstimed_wait_cancelable (unsigned int *futex_word,
      despite them being valid.  */
   if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0)))
     return ETIMEDOUT;
-  int oldtype;
-  oldtype = __pthread_enable_asynccancel ();
-  int err = lll_futex_timed_wait_bitset (futex_word, expected, abstime,
-					 FUTEX_CLOCK_REALTIME, private);
-  __pthread_disable_asynccancel (oldtype);
+  int err = lll_futex_timed_wait_bitset_cancel (futex_word, expected, abstime,
+						FUTEX_CLOCK_REALTIME,
+						private);
   switch (err)
     {
     case 0:
diff --git a/sysdeps/unix/sysv/linux/lowlevellock-futex.h b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
index 4eddadb..3a63ad5 100644
--- a/sysdeps/unix/sysv/linux/lowlevellock-futex.h
+++ b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
@@ -89,6 +89,12 @@
      ? -INTERNAL_SYSCALL_ERRNO (__ret, __err) : 0);                     \
   })
 
+#define lll_futex_syscall_cp(...)					\
+  ({                                                                    \
+    long int __ret = __SYSCALL_CANCEL_CALL (__VA_ARGS__);		\
+    __ret;								\
+  })
+
 #define lll_futex_wait(futexp, val, private) \
   lll_futex_timed_wait (futexp, val, NULL, private)
 
@@ -140,6 +146,32 @@
 					 private),                      \
 		     nr_wake, nr_move, mutex, val)
 
-#endif  /* !__ASSEMBLER__  */
+/* Cancellable futex macros.  */
+#define lll_futex_wait_cancel(futexp, val, private) \
+  lll_futex_timed_wait_cancel (futexp, val, NULL, private)
+
+#define lll_futex_timed_wait_cancel(futexp, val, timeout, private)	\
+  ({									\
+    long int __ret;							\
+    int __op = FUTEX_WAIT;						\
+    __ret = lll_futex_syscall_cp (futex, futexp,			\
+				  __lll_private_flag (__op, private),	\
+				  val, timeout);			\
+    __ret;								\
+  })
+
+#define lll_futex_timed_wait_bitset_cancel(futexp, val, timeout,	\
+                                           clockbit, private)		\
+  ({									\
+    long int __ret;							\
+    int __op = FUTEX_WAIT_BITSET | clockbit;				\
+    __ret = lll_futex_syscall_cp (futex, futexp,			\
+				  __lll_private_flag (__op, private), 	\
+				  val, timeout, 0,			\
+				  FUTEX_BITSET_MATCH_ANY);		\
+    __ret;								\
+  })
+
+# endif  /* !__ASSEMBLER__  */
 
 #endif  /* lowlevellock-futex.h */
diff --git a/sysdeps/unix/sysv/linux/pthread_kill.c b/sysdeps/unix/sysv/linux/pthread_kill.c
index 3a6171b..58980c3 100644
--- a/sysdeps/unix/sysv/linux/pthread_kill.c
+++ b/sysdeps/unix/sysv/linux/pthread_kill.c
@@ -42,9 +42,8 @@ __pthread_kill (pthread_t threadid, int signo)
     /* Not a valid thread handle.  */
     return ESRCH;
 
-  /* Disallow sending the signal we use for cancellation, timers,
-     for the setxid implementation.  */
-  if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID)
+  /* Disallow sending the signal we use for setxid implementation.  */
+  if (signo == SIGSETXID)
     return EINVAL;
 
   /* We have a special syscall to do the work.  */
diff --git a/sysdeps/unix/sysv/linux/sigwait.c b/sysdeps/unix/sysv/linux/sigwait.c
index 920c924..18ef2cf 100644
--- a/sysdeps/unix/sysv/linux/sigwait.c
+++ b/sysdeps/unix/sysv/linux/sigwait.c
@@ -37,6 +37,3 @@ __sigwait (const sigset_t *set, int *sig)
 libc_hidden_def (__sigwait)
 weak_alias (__sigwait, sigwait)
 strong_alias (__sigwait, __libc_sigwait)
-
-/* __sigtimedwait handles cancellation.  */
-LIBC_CANCEL_HANDLED ();
diff --git a/sysdeps/unix/sysv/linux/sigwaitinfo.c b/sysdeps/unix/sysv/linux/sigwaitinfo.c
index 55003fc..71bdc94 100644
--- a/sysdeps/unix/sysv/linux/sigwaitinfo.c
+++ b/sysdeps/unix/sysv/linux/sigwaitinfo.c
@@ -28,6 +28,3 @@ __sigwaitinfo (const sigset_t *set, siginfo_t *info)
 libc_hidden_def (__sigwaitinfo)
 weak_alias (__sigwaitinfo, sigwaitinfo)
 strong_alias (__sigwaitinfo, __libc_sigwaitinfo)
-
-/* __sigtimedwait handles cancellation.  */
-LIBC_CANCEL_HANDLED ();
diff --git a/sysdeps/unix/sysv/linux/socketcall.h b/sysdeps/unix/sysv/linux/socketcall.h
index bbae6f8..eda233d 100644
--- a/sysdeps/unix/sysv/linux/socketcall.h
+++ b/sysdeps/unix/sysv/linux/socketcall.h
@@ -87,16 +87,39 @@
   })
 
 
-#if IS_IN (libc)
-# define __pthread_enable_asynccancel  __libc_enable_asynccancel
-# define __pthread_disable_asynccancel __libc_disable_asynccancel
-#endif
+#define __SOCKETCALL_CANCEL1(__name, __a1) \
+  SYSCALL_CANCEL_NCS (socketcall, __name, \
+     ((long int [1]) { (long int) __a1 }))
+#define __SOCKETCALL_CANCEL2(__name, __a1, __a2) \
+  SYSCALL_CANCEL_NCS (socketcall, __name, \
+     ((long int [2]) { (long int) __a1, (long int) __a2 }))
+#define __SOCKETCALL_CANCEL3(__name, __a1, __a2, __a3) \
+  SYSCALL_CANCEL_NCS (socketcall, __name, \
+     ((long int [3]) { (long int) __a1, (long int) __a2, (long int) __a3 }))
+#define __SOCKETCALL_CANCEL4(__name, __a1, __a2, __a3, __a4) \
+  SYSCALL_CANCEL_NCS (socketcall, __name, \
+     ((long int [4]) { (long int) __a1, (long int) __a2, (long int) __a3, \
+                       (long int) __a4 }))
+#define __SOCKETCALL_CANCEL5(__name, __a1, __a2, __a3, __a4, __a5) \
+  SYSCALL_CANCEL_NCS (socketcall, __name, \
+     ((long int [5]) { (long int) __a1, (long int) __a2, (long int) __a3, \
+                       (long int) __a4, (long int) __a5 }))
+#define __SOCKETCALL_CANCEL6(__name, __a1, __a2, __a3, __a4, __a5, __a6) \
+  SYSCALL_CANCEL_NCS (socketcall, __name, \
+     ((long int [6]) { (long int) __a1, (long int) __a2, (long int) __a3, \
+                       (long int) __a4, (long int) __a5, (long int) __a6 }))
+
+#define __SOCKETCALL_CANCEL(...) __SOCKETCALL_DISP (__SOCKETCALL_CANCEL,\
+						    __VA_ARGS__)
 
 #define SOCKETCALL_CANCEL(name, args...)				\
   ({									\
-    int oldtype = LIBC_CANCEL_ASYNC ();					\
-    long int sc_ret = __SOCKETCALL (SOCKOP_##name, args);		\
-    LIBC_CANCEL_RESET (oldtype);					\
+    long int sc_ret = __SOCKETCALL_CANCEL (SOCKOP_##name, args);	\
+    if (sc_ret > -4096UL)						\
+      {									\
+        __set_errno (-sc_ret);						\
+        sc_ret = -1L;							\
+      }									\
     sc_ret;								\
   })
 
diff --git a/sysdeps/unix/sysv/linux/syscall_cancel.c b/sysdeps/unix/sysv/linux/syscall_cancel.c
new file mode 100644
index 0000000..ac08bb7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/syscall_cancel.c
@@ -0,0 +1,62 @@
+/* Default cancellation syscall bridge.
+   Copyright (C) 2017 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>
+#include <pthreadP.h>
+
+#define ADD_LABEL(__label)		\
+  asm volatile (			\
+    ".global " __label "\t\n"		\
+    ".type " __label ",\%function\t\n" 	\
+    __label ":\n");
+
+/* This is the generic version of the cancellable syscall code which
+   adds the label guards (__syscall_cancel_arch_{start,end}) used
+   on SIGCANCEL handler (sigcancel_handler at nptl-init.c) to check if
+   the cancelled syscall have side-effects that need to be signaled to
+   program.
+
+   An important contrainst should be observed when using this generic
+   implementation: the __syscall_cancel_arch_end should point to the
+   immediate next instruction after the syscall one.  This is because
+   kernel will signal interrupted syscall with side effects by setting
+   the signal frame Program Counter right after the syscall instruction.
+
+   If the INTERNAL_SYSCALL_NCS macro use more instructions to get the
+   error condition from kernel (as for powerpc and sparc), uses an
+   out of the line helper (as for ARM thumb), or uses a kernel helper
+   gate (as for i686 or ia64) the architecture should either adjust the
+   macro or provide a custom __syscall_cancel_arch implementation.   */
+long int
+__syscall_cancel_arch (volatile int *ch, __syscall_arg_t nr,
+		       __syscall_arg_t a1, __syscall_arg_t a2,
+		       __syscall_arg_t a3, __syscall_arg_t a4,
+		       __syscall_arg_t a5, __syscall_arg_t a6)
+{
+  ADD_LABEL ("__syscall_cancel_arch_start");
+  if (__glibc_unlikely (*ch & CANCELED_BITMASK))
+    __syscall_do_cancel();
+
+  INTERNAL_SYSCALL_DECL(err);
+  long int result = INTERNAL_SYSCALL_NCS (nr, err, 6, a1, a2, a3, a4, a5, a6);
+  ADD_LABEL ("__syscall_cancel_arch_end");
+  if (INTERNAL_SYSCALL_ERROR_P (result, err))
+    return -INTERNAL_SYSCALL_ERRNO (result, err);
+  return result;
+}
+libc_hidden_def (__syscall_cancel_arch)
diff --git a/sysdeps/unix/sysv/linux/sysdep.h b/sysdeps/unix/sysv/linux/sysdep.h
index 4fd0a9b..235399e 100644
--- a/sysdeps/unix/sysv/linux/sysdep.h
+++ b/sysdeps/unix/sysv/linux/sysdep.h
@@ -27,6 +27,23 @@
     -1l;					\
   })
 
+/* Check error from cancellable syscall and set errno accordingly.
+   Linux uses a negative return value to indicate syscall errors
+   and since version 2.1 the return value of a system call might be
+   negative even if the call succeeded (e.g., the `lseek' system call
+   might return a large offset).
+   Current contract is kernel make sure the no syscall returns a value
+   in -1 .. -4095 as a valid result so we can savely test with -4095.  */
+#define SYSCALL_CANCEL_RET(__ret)		\
+  ({						\
+    if (__ret > -4096UL)			\
+      {						\
+	__set_errno (-__ret);			\
+	__ret = -1;				\
+      }						\
+    __ret;					\
+   })
+
 /* Provide a dummy argument that can be used to force register
    alignment for register pairs if required by the syscall ABI.  */
 #ifdef __ASSUME_ALIGNED_REGISTER_PAIRS
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 04/21] nptl: x86_64: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (2 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 03/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-05-07  2:49   ` Zack Weinberg
  2018-02-26 21:03 ` [PATCH v2 05/21] nptl: x32: " Adhemerval Zanella
                   ` (16 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patches adds the x86_64 modification required for the BZ#12683.
It basically provide the required ucontext_get_pc symbol and remove
the arch-specific libc-cancellation implementations.

It also remove bogus arch-specific THREAD_ATOMIC_BIT_SET where it
always reference to current thread instead of the one referenced by
input 'descr' argument. It works as long the input is the self thread
pointer, however it creates wrong code is it used along with a
description to a different one (as on nptl/pthread_cancel.c).

The code generated create an additional load to reference to TLS segment,
for instance the code:

  THREAD_ATOMIC_BIT_SET (THREAD_SELF, cancelhandling, CANCELED_BIT);

Compiles to:

  lock;orl $4, %fs:776

Where with patch changes it now compiles to:

  mov %fs:16,%rax
  lock;orl $4, 776(%rax)

If some usage indeed proves to be a hotspot we can add an extra macro
with a more descriptive name (THREAD_ATOMIC_BIT_SET_SELF for instance)
where x86_64 might optimize it.  In fact all x86_64 THREAD_ATOMIC_* macros
do not respect the input descr and possible will fail when used with
a 'descr' difference than THREAD_SELF.

Checked on x86_64-linux-gnu.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/x86_64/cancellation.S: Remove file.
	* sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S: Remove file.
	* sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S: Remove file.
	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_wait_tid):
	Use cancellable futex wait call.
	* sysdeps/unix/sysv/linux/x86_64/sigcontextinfo.h (ucontext_get_pc):
	New function.
	* sysdeps/x86_64/nptl/tcb-offsets.sym (TCB_CANCELING_BITMASK):
	Remove.
	* sysdeps/x86_64/nptl/tls.h (THREAD_ATOMIC_CMPXCHG_VAL,
	THREAD_ATOMIC_BIT_SET): Remove macros.
---
 ChangeLog                                          |  13 +++
 sysdeps/unix/sysv/linux/x86_64/cancellation.S      | 115 ---------------------
 sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S |  21 ----
 .../unix/sysv/linux/x86_64/librt-cancellation.S    |  21 ----
 sysdeps/unix/sysv/linux/x86_64/lowlevellock.h      |   8 +-
 sysdeps/unix/sysv/linux/x86_64/sigcontextinfo.h    |  11 ++
 sysdeps/x86_64/nptl/tcb-offsets.sym                |   1 -
 sysdeps/x86_64/nptl/tls.h                          |  11 --
 8 files changed, 28 insertions(+), 173 deletions(-)
 delete mode 100644 sysdeps/unix/sysv/linux/x86_64/cancellation.S
 delete mode 100644 sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S
 delete mode 100644 sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S

diff --git a/sysdeps/unix/sysv/linux/x86_64/cancellation.S b/sysdeps/unix/sysv/linux/x86_64/cancellation.S
deleted file mode 100644
index f3fb19d..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/cancellation.S
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Copyright (C) 2009-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2009.
-
-   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>
-#include <tcb-offsets.h>
-#include <kernel-features.h>
-#include "lowlevellock.h"
-
-#define PTHREAD_UNWIND JUMPTARGET(__pthread_unwind)
-#if IS_IN (libpthread)
-# if defined SHARED && !defined NO_HIDDEN
-#  undef PTHREAD_UNWIND
-#  define PTHREAD_UNWIND __GI___pthread_unwind
-# endif
-#else
-# ifndef SHARED
-	.weak __pthread_unwind
-# endif
-#endif
-
-
-#ifdef __ASSUME_PRIVATE_FUTEX
-# define LOAD_PRIVATE_FUTEX_WAIT(reg) \
-	movl	$(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
-#else
-# if FUTEX_WAIT == 0
-#  define LOAD_PRIVATE_FUTEX_WAIT(reg) \
-	movl	%fs:PRIVATE_FUTEX, reg
-# else
-#  define LOAD_PRIVATE_FUTEX_WAIT(reg) \
-	movl	%fs:PRIVATE_FUTEX, reg ; \
-	orl	$FUTEX_WAIT, reg
-# endif
-#endif
-
-/* It is crucial that the functions in this file don't modify registers
-   other than %rax and %r11.  The syscall wrapper code depends on this
-   because it doesn't explicitly save the other registers which hold
-   relevant values.  */
-	.text
-
-	.hidden __pthread_enable_asynccancel
-ENTRY(__pthread_enable_asynccancel)
-	movl	%fs:CANCELHANDLING, %eax
-2:	movl	%eax, %r11d
-	orl	$TCB_CANCELTYPE_BITMASK, %r11d
-	cmpl	%eax, %r11d
-	je	1f
-
-	lock
-	cmpxchgl %r11d, %fs:CANCELHANDLING
-	jnz	2b
-
-	andl	$(TCB_CANCELSTATE_BITMASK|TCB_CANCELTYPE_BITMASK|TCB_CANCELED_BITMASK|TCB_EXITING_BITMASK|TCB_CANCEL_RESTMASK|TCB_TERMINATED_BITMASK), %r11d
-	cmpl	$(TCB_CANCELTYPE_BITMASK|TCB_CANCELED_BITMASK), %r11d
-	je	3f
-
-1:	ret
-
-3:	subq	$8, %rsp
-	cfi_adjust_cfa_offset(8)
-	LP_OP(mov) $TCB_PTHREAD_CANCELED, %fs:RESULT
-	lock
-	orl	$TCB_EXITING_BITMASK, %fs:CANCELHANDLING
-	mov	%fs:CLEANUP_JMP_BUF, %RDI_LP
-	call	PTHREAD_UNWIND
-	hlt
-END(__pthread_enable_asynccancel)
-
-
-	.hidden __pthread_disable_asynccancel
-ENTRY(__pthread_disable_asynccancel)
-	testl	$TCB_CANCELTYPE_BITMASK, %edi
-	jnz	1f
-
-	movl	%fs:CANCELHANDLING, %eax
-2:	movl	%eax, %r11d
-	andl	$~TCB_CANCELTYPE_BITMASK, %r11d
-	lock
-	cmpxchgl %r11d, %fs:CANCELHANDLING
-	jnz	2b
-
-	movl	%r11d, %eax
-3:	andl	$(TCB_CANCELING_BITMASK|TCB_CANCELED_BITMASK), %eax
-	cmpl	$TCB_CANCELING_BITMASK, %eax
-	je	4f
-1:	ret
-
-	/* Performance doesn't matter in this loop.  We will
-	   delay until the thread is canceled.  And we will unlikely
-	   enter the loop twice.  */
-4:	mov	%fs:0, %RDI_LP
-	movl	$__NR_futex, %eax
-	xorq	%r10, %r10
-	addq	$CANCELHANDLING, %rdi
-	LOAD_PRIVATE_FUTEX_WAIT (%esi)
-	syscall
-	movl	%fs:CANCELHANDLING, %eax
-	jmp	3b
-END(__pthread_disable_asynccancel)
diff --git a/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S b/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S
deleted file mode 100644
index ed7af0d..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Copyright (C) 2009-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2009.
-
-   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/>.  */
-
-#define __pthread_enable_asynccancel __libc_enable_asynccancel
-#define __pthread_disable_asynccancel __libc_disable_asynccancel
-#include "cancellation.S"
diff --git a/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S b/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S
deleted file mode 100644
index d0f0ee4..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Copyright (C) 2009-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2009.
-
-   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/>.  */
-
-#define __pthread_enable_asynccancel __librt_enable_asynccancel
-#define __pthread_disable_asynccancel __librt_disable_asynccancel
-#include "cancellation.S"
diff --git a/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
index eedb6fc..957d4c1 100644
--- a/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
+++ b/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
@@ -231,10 +231,10 @@ extern int __lll_timedlock_elision (int *futex, short *adapt_count,
    afterwards.  The kernel up to version 3.16.3 does not use the private futex
    operations for futex wake-up when the clone terminates.  */
 #define lll_wait_tid(tid) \
-  do {					\
-    __typeof (tid) __tid;		\
-    while ((__tid = (tid)) != 0)	\
-      lll_futex_wait (&(tid), __tid, LLL_SHARED);\
+  do {									      \
+    __typeof (tid) __tid;						      \
+    while ((__tid = (tid)) != 0)					      \
+      lll_futex_wait_cancel (&(tid), __tid, LLL_SHARED);		      \
   } while (0)
 
 extern int __lll_timedwait_tid (int *, const struct timespec *)
diff --git a/sysdeps/unix/sysv/linux/x86_64/sigcontextinfo.h b/sysdeps/unix/sysv/linux/x86_64/sigcontextinfo.h
index 41ace60..3cc7336 100644
--- a/sysdeps/unix/sysv/linux/x86_64/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/x86_64/sigcontextinfo.h
@@ -15,6 +15,9 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
 #include <stdint.h>
 
 #define SIGCONTEXT siginfo_t *_si, ucontext_t *
@@ -28,3 +31,11 @@
 
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+static inline
+uintptr_t ucontext_get_pc (const ucontext_t *uc)
+{
+  return uc->uc_mcontext.gregs[REG_RIP];
+}
+
+#endif
diff --git a/sysdeps/x86_64/nptl/tcb-offsets.sym b/sysdeps/x86_64/nptl/tcb-offsets.sym
index 8a25c48..b225e5b 100644
--- a/sysdeps/x86_64/nptl/tcb-offsets.sym
+++ b/sysdeps/x86_64/nptl/tcb-offsets.sym
@@ -19,7 +19,6 @@ PRIVATE_FUTEX		offsetof (tcbhead_t, private_futex)
 -- Not strictly offsets, but these values are also used in the TCB.
 TCB_CANCELSTATE_BITMASK	 CANCELSTATE_BITMASK
 TCB_CANCELTYPE_BITMASK	 CANCELTYPE_BITMASK
-TCB_CANCELING_BITMASK	 CANCELING_BITMASK
 TCB_CANCELED_BITMASK	 CANCELED_BITMASK
 TCB_EXITING_BITMASK	 EXITING_BITMASK
 TCB_CANCEL_RESTMASK	 CANCEL_RESTMASK
diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h
index bdd0237..ed0c65b 100644
--- a/sysdeps/x86_64/nptl/tls.h
+++ b/sysdeps/x86_64/nptl/tls.h
@@ -315,17 +315,6 @@ typedef struct
 	      abort (); })
 
 
-/* Atomic set bit.  */
-# define THREAD_ATOMIC_BIT_SET(descr, member, bit) \
-  (void) ({ if (sizeof ((descr)->member) == 4)				      \
-	      asm volatile (LOCK_PREFIX "orl %1, %%fs:%P0"		      \
-			    :: "i" (offsetof (struct pthread, member)),	      \
-			       "ir" (1 << (bit)));			      \
-	    else							      \
-	      /* Not necessary for other sizes in the moment.  */	      \
-	      abort (); })
-
-
 /* Set the stack guard field in TCB head.  */
 # define THREAD_SET_STACK_GUARD(value) \
     THREAD_SETMEM (THREAD_SELF, header.stack_guard, value)
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 05/21] nptl: x32: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (3 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 04/21] nptl: x86_64: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 06/21] nptl: i386: " Adhemerval Zanella
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patches adds the x32 modification required for the BZ#12683.
It basically adjust the syscall size used to pass the arguments to
the syscall cancel wrappers by zero extending pointers type while
preserting values for default types (such as off_t).

Checked on x86_64-linux-gnu-x32.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h (__syscall_arg_t):
	Define type for x32.
	(__SSC): Add platform specific macro.
	* include/libc-pointer-arith.h (__integer_if_pointer_type_sub,
	__integer_if_pointer_type, cast_to_integer): Parametrize integer type
	cast.
	(cast_to_uinteger): New macro.
---
 ChangeLog                                   |  9 +++++++++
 include/libc-pointer-arith.h                | 16 +++++++++++-----
 sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h | 13 +++++++++++++
 3 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/include/libc-pointer-arith.h b/include/libc-pointer-arith.h
index 1ee3362..65107cc 100644
--- a/include/libc-pointer-arith.h
+++ b/include/libc-pointer-arith.h
@@ -25,17 +25,23 @@
 # define __pointer_type(type) (__builtin_classify_type ((type) 0) == 5)
 
 /* intptr_t if P is true, or T if P is false.  */
-# define __integer_if_pointer_type_sub(T, P) \
+# define __integer_if_pointer_type_sub(T, P, INTTYPE) \
   __typeof__ (*(0 ? (__typeof__ (0 ? (T *) 0 : (void *) (P))) 0 \
-		  : (__typeof__ (0 ? (intptr_t *) 0 : (void *) (!(P)))) 0))
+		  : (__typeof__ (0 ? (INTTYPE *) 0 : (void *) (!(P)))) 0))
 
 /* intptr_t if EXPR has a pointer type, or the type of EXPR otherwise.  */
-# define __integer_if_pointer_type(expr) \
+# define __integer_if_pointer_type(expr, inttype) \
   __integer_if_pointer_type_sub(__typeof__ ((__typeof__ (expr)) 0), \
-				__pointer_type (__typeof__ (expr)))
+				__pointer_type (__typeof__ (expr)), \
+				inttype)
 
 /* Cast an integer or a pointer VAL to integer with proper type.  */
-# define cast_to_integer(val) ((__integer_if_pointer_type (val)) (val))
+# define cast_to_integer(val) \
+  ((__integer_if_pointer_type (val, intptr_t)) (val))
+
+/* Cast an integer or a pointer VAL to unsigned integer with proper type.  */
+# define cast_to_uinteger(val) \
+  ((__integer_if_pointer_type (val, uintptr_t)) (val))
 
 /* Align a value by rounding down to closest size.
    e.g. Using size of 4096, we get this behavior:
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
index 7f978c7..787e7f2 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
@@ -18,6 +18,19 @@
 #ifndef _LINUX_X32_SYSDEP_H
 #define _LINUX_X32_SYSDEP_H 1
 
+#ifndef __ASSEMBLER__
+#include <libc-internal.h>
+#include <libc-diag.h>
+
+typedef long long int __syscall_arg_t;
+
+/* Syscall arguments for x32 follows x86_64 size, however pointers are 32
+   bits in size.  The idea is to zero extend pointer types while cast to
+   signed 64 bit default arguments.  */
+#define __SSC(__x) ((__syscall_arg_t) cast_to_uinteger (__x))
+
+#endif
+
 /* There is some commonality.  */
 #include <sysdeps/unix/sysv/linux/x86_64/sysdep.h>
 #include <sysdeps/x86_64/x32/sysdep.h>
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 06/21] nptl: i386: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (4 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 05/21] nptl: x32: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-05-07  2:49   ` Zack Weinberg
  2018-02-26 21:03 ` [PATCH v2 07/21] nptl: powerpc: " Adhemerval Zanella
                   ` (14 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the i386 modifications required for the BZ#12683.
It basically provides the required ucontext_get_pc symbol, add the
cancelable syscall wrapper and fix a thread atomic update macro.

On i386 an arch-specific cancellation implementation is required
because depending of the glibc configuration and underlying kernel
the syscall may be done using a vDSO symbol (__kernel_vsyscall).
By using the vDSO symbol the resulting PC value for an interrupted
syscall points to an adress outside the expected markers in
__syscall_cancel_arch.  It has been discussed in LKML [1] on how
kernel could help userland to accomplish it, but afaik discussion
was stalled.

Also, since glibc supports i486, the old 'int 0x80' should be used
in the syscall wrapper.  One option could make minimum default chip
to pentium II (which implements sysenter) or add a runtime check
on syscall_cancel.S to use 'int 0x80' or sysenter.

Similar to x86_64, it also remove bogus arch-specific
THREAD_ATOMIC_BIT_SET where it always reference to current thread
instead of the one referenced by input 'descr' argument.

Checked on i686-linux-gnu.

	[BZ #12683]
	* sysdeps/i386/nptl/tls.h (THREAD_ATOMIC_CMPXCHG_VAL,
	THREAD_ATOMIC_BIT_SET): Remove macro.
	* sysdeps/unix/sysv/linux/i386/Makefile
	[$(subdir) = elf] (sysdep-rtld_routines): Add libc-do-syscall object.
	* sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_wait_tid): Use
	cancellable futex syscall macro.
	* sysdeps/unix/sysv/linux/i386/syscall_cancel.S: New file.
	* sysdeps/unix/sysv/linux/i386/sigcontextinfo.h (ucontext_get_pc):
	New function.

[1] https://lkml.org/lkml/2016/3/8/1105
---
 ChangeLog                                     |  10 +++
 sysdeps/i386/nptl/tls.h                       |  11 ---
 sysdeps/unix/sysv/linux/i386/Makefile         |   2 +-
 sysdeps/unix/sysv/linux/i386/lowlevellock.h   |   2 +-
 sysdeps/unix/sysv/linux/i386/sigcontextinfo.h |  13 ++++
 sysdeps/unix/sysv/linux/i386/syscall_cancel.S | 107 ++++++++++++++++++++++++++
 6 files changed, 132 insertions(+), 13 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/i386/syscall_cancel.S

diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h
index fcda135..ae4de89 100644
--- a/sysdeps/i386/nptl/tls.h
+++ b/sysdeps/i386/nptl/tls.h
@@ -383,17 +383,6 @@ tls_fill_user_desc (union user_desc_init *desc,
 	      abort (); })
 
 
-/* Atomic set bit.  */
-#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \
-  (void) ({ if (sizeof ((descr)->member) == 4)				      \
-	      asm volatile (LOCK_PREFIX "orl %1, %%gs:%P0"		      \
-			    :: "i" (offsetof (struct pthread, member)),	      \
-			       "ir" (1 << (bit)));			      \
-	    else							      \
-	      /* Not necessary for other sizes in the moment.  */	      \
-	      abort (); })
-
-
 /* Set the stack guard field in TCB head.  */
 #define THREAD_SET_STACK_GUARD(value) \
   THREAD_SETMEM (THREAD_SELF, header.stack_guard, value)
diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile
index 4080b8c..bae2e4b 100644
--- a/sysdeps/unix/sysv/linux/i386/Makefile
+++ b/sysdeps/unix/sysv/linux/i386/Makefile
@@ -6,7 +6,7 @@ sysdep_routines += ioperm iopl vm86
 endif
 
 ifeq ($(subdir),elf)
-sysdep-dl-routines += libc-do-syscall
+sysdep-rtld_routines += libc-do-syscall
 sysdep-others += lddlibc4
 install-bin += lddlibc4
 endif
diff --git a/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/sysdeps/unix/sysv/linux/i386/lowlevellock.h
index 38fbc25..072bc11 100644
--- a/sysdeps/unix/sysv/linux/i386/lowlevellock.h
+++ b/sysdeps/unix/sysv/linux/i386/lowlevellock.h
@@ -230,7 +230,7 @@ extern int __lll_timedlock_elision (int *futex, short *adapt_count,
   do {					\
     __typeof (tid) __tid;		\
     while ((__tid = (tid)) != 0)	\
-      lll_futex_wait (&(tid), __tid, LLL_SHARED);\
+      lll_futex_wait_cancel (&(tid), __tid, LLL_SHARED);\
   } while (0)
 
 extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime)
diff --git a/sysdeps/unix/sysv/linux/i386/sigcontextinfo.h b/sysdeps/unix/sysv/linux/i386/sigcontextinfo.h
index a4ed29a..e7a9f17 100644
--- a/sysdeps/unix/sysv/linux/i386/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/i386/sigcontextinfo.h
@@ -16,6 +16,11 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
+
 #define SIGCONTEXT struct sigcontext
 #define SIGCONTEXT_EXTRA_ARGS
 #define GET_PC(ctx)	((void *) ctx.eip)
@@ -48,3 +53,11 @@ do {									      \
 		      "i" (sizeof (struct sigcontext) / 4)		      \
 		    : "cc", "edi");					      \
 } while (0)
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+  return uc->uc_mcontext.gregs[REG_EIP];
+}
+
+#endif /* _SIGCONTEXTINFO_H  */
diff --git a/sysdeps/unix/sysv/linux/i386/syscall_cancel.S b/sysdeps/unix/sysv/linux/i386/syscall_cancel.S
new file mode 100644
index 0000000..5596b3e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/syscall_cancel.S
@@ -0,0 +1,107 @@
+/* Cancellable syscall wrapper.  Linux/i686 version.
+   Copyright (C) 2017 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 [eax] __syscall_cancel_arch (int *cancelhandling [SP],
+					 long int nr   [SP+4],
+					 long int arg1 [SP+8],
+					 long int arg2 [SP+12],
+					 long int arg3 [SP+16],
+					 long int arg4 [SP+20],
+					 long int arg5 [SP+24],
+					 long int arg6 [SP+28])  */
+
+ENTRY (__syscall_cancel_arch)
+	pushl %ebp
+	cfi_def_cfa_offset (8)
+	cfi_offset (ebp, -8)
+	pushl %edi
+	cfi_def_cfa_offset (12)
+	cfi_offset (edi, -12)
+	pushl %esi
+	cfi_def_cfa_offset (16)
+	cfi_offset (esi, -16)
+	pushl %ebx
+	cfi_def_cfa_offset (20)
+	cfi_offset (ebx, -20)
+
+	.global __syscall_cancel_arch_start
+	.type   __syscall_cancel_arch_start, @function
+__syscall_cancel_arch_start:
+
+	/* if (*cancelhandling & CANCELED_BITMASK)
+	     __syscall_do_cancel()  */
+	testb	$4, (%eax)
+	jne     1f
+
+	/* Issue a 6 argument syscall, the nr [%eax] being the syscall
+	   number.  */
+	movl    24(%esp), %eax
+	movl    28(%esp), %ebx
+	movl    32(%esp), %ecx
+	movl    36(%esp), %edx
+	movl    40(%esp), %esi
+	movl    44(%esp), %edi
+	movl    48(%esp), %ebp
+
+	/* We can not use the vDSO helper for syscall (__kernel_vsyscall)
+	   because the returned PC from kernel will indicate whether the
+	   interrupted syscall have any side-effects that need to be reported
+	   back to program.  And the signal handler (sigcancel_handler at
+	   nptl-init.c) checks the PC agains the __syscall_cancel_arch_*
+	   marks.  */
+	int	$128
+
+	.global __syscall_cancel_arch_end
+	.type   __syscall_cancel_arch_end, @function
+__syscall_cancel_arch_end:
+
+	popl %ebx
+	cfi_restore (ebx)
+	cfi_def_cfa_offset (16)
+	popl %esi
+	cfi_restore (esi)
+	cfi_def_cfa_offset (12)
+	popl %edi
+	cfi_restore (edi)
+	cfi_def_cfa_offset (8)
+	popl %ebp
+	cfi_restore (ebp)
+	cfi_def_cfa_offset (4)
+        ret
+
+1:
+	/* Although the __syscall_do_cancel do not return, we need to stack
+	   being set correctly for unwind.  */
+	popl %ebx
+	cfi_restore (ebx)
+	cfi_def_cfa_offset (16)
+	popl %esi
+	cfi_restore (esi)
+	cfi_def_cfa_offset (12)
+	popl %edi
+	cfi_restore (edi)
+	cfi_def_cfa_offset (8)
+	popl %ebp
+	cfi_restore (ebp)
+	cfi_def_cfa_offset (4)
+	jmp __syscall_do_cancel
+
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 07/21] nptl: powerpc: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (5 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 06/21] nptl: i386: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-05-07 19:25   ` Tulio Magno Quites Machado Filho
  2018-02-26 21:03 ` [PATCH v2 08/21] nptl: aarch64: " Adhemerval Zanella
                   ` (13 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patches adds the powerpc64 modification required for the BZ#12683.
It basically adds the required __pthread_get_pc function and a arch
specific syscall_cancel implementation.

The powerpc requires an arch-specific syscall_cancel because
INTERNAL_SYSCALL_NCS adds a mfcr just after the sc instruction to get
the CR0.SO bit information from kernel (which signals the error
return status).  So for cancelled syscalls with side effects,
__pthread_get_pc will point to mcfr and thus invalidating the checks
on sigcancel_handler.

Checked on powerpc64le-linux-gnu and powerpc-linux-gnu.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S: New file.
	* sysdeps/unix/sysv/linux/powerpc/sysdep-cancel.h
	(__pthread_get_pc): New function.
---
 ChangeLog                                        |  5 ++
 sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h | 16 ++++++
 sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S | 64 ++++++++++++++++++++++++
 3 files changed, 85 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S

diff --git a/sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h b/sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h
index 72381e3..3be71f7 100644
--- a/sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h
@@ -15,7 +15,11 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
 #include <signal.h>
+#include <stdint.h>
 
 #define SIGCONTEXT struct sigcontext *
 #define SIGCONTEXT_EXTRA_ARGS
@@ -24,3 +28,15 @@
 #define GET_STACK(ctx)	((void *)((ctx)->regs->gpr[1]))
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+#ifdef __powerpc64__
+  return uc->uc_mcontext.gp_regs[PT_NIP];
+#else
+  return uc->uc_mcontext.uc_regs->gregs[PT_NIP];
+#endif
+}
+
+#endif /* _SIGCONTEXTINFO_H  */
diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S b/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S
new file mode 100644
index 0000000..2e56c72
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S
@@ -0,0 +1,64 @@
+/* Cancellable syscall wrapper.  Linux/powerpc version.
+   Copyright (C) 2017 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 [r3] __syscall_cancel_arch (int *cancelhandling [r3],
+					long int nr   [r4],
+					long int arg1 [r5],
+					long int arg2 [r6],
+					long int arg3 [r7],
+					long int arg4 [r8],
+					long int arg5 [r9],
+					long int arg6 [r10])  */
+
+ENTRY (__syscall_cancel_arch)
+
+	.globl __syscall_cancel_arch_start
+	.type  __syscall_cancel_arch_start,@function
+__syscall_cancel_arch_start:
+
+	/* if (*cancelhandling & CANCELED_BITMASK)
+	     __syscall_do_cancel()  */
+	lwz     r0,0(r3)
+	rldicl. r0,r0,62,63
+	beq     1f
+	b       __syscall_do_cancel
+	nop
+1:
+	ABORT_TRANSACTION
+	/* Issue a 6 argument syscall, the nr [r4] being the syscall
+	   number.  */
+	mr      r0,r4
+	mr      r3,r5
+	mr      r4,r6
+	mr      r5,r7
+	mr      r6,r8
+	mr      r7,r9
+	mr      r8,r10
+	sc
+
+	.globl __syscall_cancel_arch_end
+	.type  __syscall_cancel_arch_end,@function
+__syscall_cancel_arch_end:
+
+	bnslr+
+	neg	r3,r3
+	blr
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 08/21] nptl: aarch64: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (6 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 07/21] nptl: powerpc: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 09/21] nptl: arm: " Adhemerval Zanella
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the aarch64 modifications required for the BZ#12683.
It basically adds the required ucontext_get_pc function.

The built cancelable syscall wrapper for aarch64 using GCC 7.2.1 and
default configuration flags shows an expected optimized version:

---
__GI___syscall_cancel_arch:
.LFB38:
        .cfi_startproc
        .global __syscall_cancel_arch_start
.type __syscall_cancel_arch_start,@function
__syscall_cancel_arch_start:
        ldr     w9, [x0]
        tbnz    x9, 2, .L7
        mov     x8, x1
        mov     x0, x2
        mov     x1, x3
        mov     x2, x4
        mov     x3, x5
        mov     x4, x6
        mov     x5, x7
        svc     0       // syscall nr
        .global __syscall_cancel_arch_end
.type __syscall_cancel_arch_end,@function
__syscall_cancel_arch_end:
        ret
---

A similar code is obtained with GCC 5.3.1, so I see to need to provide
an arch-specific syscall_cancel.S for aarch64.

Checked on aarch64-linux-gnu.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h (PSEUDO): Redefine
	to call __syscall_cancel function for cancellable syscalls.
	(__pthread_get_ip): Add implementation.
	* sysdeps/unix/sysv/linux/aarch64/sysdep.h (SYSCALL_CANCEL_ERROR): Add
	definition.
	(SYSCALL_CANCEL_ERRNO): Likewise.
---
 ChangeLog                                        |  4 ++++
 sysdeps/unix/sysv/linux/aarch64/sigcontextinfo.h | 11 +++++++++++
 2 files changed, 15 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/aarch64/sigcontextinfo.h b/sysdeps/unix/sysv/linux/aarch64/sigcontextinfo.h
index 04596ef..d9822dc 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/aarch64/sigcontextinfo.h
@@ -16,6 +16,9 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
 #include <stdint.h>
 #include <sys/ucontext.h>
 
@@ -33,3 +36,11 @@
   (act)->sa_flags |= SA_SIGINFO; \
   (sigaction) (sig, act, oact); \
 })
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+  return uc->uc_mcontext.pc;
+}
+
+#endif
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 09/21] nptl: arm: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (7 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 08/21] nptl: aarch64: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 10/21] nptl: s390: " Adhemerval Zanella
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the ARM modifications required for the BZ#12683.
It basically adds the required ucontext_get_pc function and adjust
the generic syscall_cancel build.

For ARM we need to build syscall_cancel in ARM mode (-marm) to avoid
INTERNAL_SYSCALL to issue the syscall through the helper gate
__libc_do_syscall (which invalidates the mark checks on SIGCANCEL
handler).

Checked on arm-linux-gnueabihf.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/arm/Makefile (CFLAGS-syscall_cancel.c): New
	rule.
	* sysdeps/unix/sysv/linux/arm/sigcontextinfo.h (ucontext_get_pc):
	New function.
---
 ChangeLog                                    |  6 ++++++
 sysdeps/unix/sysv/linux/arm/Makefile         |  3 +++
 sysdeps/unix/sysv/linux/arm/sigcontextinfo.h | 12 ++++++++++++
 3 files changed, 21 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/arm/Makefile b/sysdeps/unix/sysv/linux/arm/Makefile
index 4adc35d..8f01b52 100644
--- a/sysdeps/unix/sysv/linux/arm/Makefile
+++ b/sysdeps/unix/sysv/linux/arm/Makefile
@@ -30,6 +30,9 @@ endif
 ifeq ($(subdir),nptl)
 libpthread-sysdep_routines += libc-do-syscall
 libpthread-shared-only-routines += libc-do-syscall
+
+# INLINE_SYSCALL uses the helper __libc_do_syscall in thumb mode.
+CFLAGS-syscall_cancel.c += -marm
 endif
 
 ifeq ($(subdir),resolv)
diff --git a/sysdeps/unix/sysv/linux/arm/sigcontextinfo.h b/sysdeps/unix/sysv/linux/arm/sigcontextinfo.h
index daf9bd3..3d4eb2f 100644
--- a/sysdeps/unix/sysv/linux/arm/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/arm/sigcontextinfo.h
@@ -16,6 +16,10 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
 #include <sys/ucontext.h>
 
 #define SIGCONTEXT siginfo_t *_si, ucontext_t *
@@ -46,3 +50,11 @@
   (act)->sa_flags |= SA_SIGINFO; \
   (sigaction) (sig, act, oact); \
 })
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+  return uc->uc_mcontext.arm_pc;
+}
+
+#endif /* _SIGCONTEXTINFO_H  */
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 10/21] nptl: s390: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (8 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 09/21] nptl: arm: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 11/21] nptl: ia64: " Adhemerval Zanella
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha; +Cc: Adhemerval Zanella

From: Adhemerval Zanella <adhemerval.zanella@linaro.com>

This patch adds the s390 modifications required for the BZ#12683 fix.
It basically adds the required ucontext_get_pc function.

The built cancelable syscall wrapper for s390 using GCC 7.2.1 and
default configuration flags shows the wrappers on expected corrected
places:

---
__GI___syscall_cancel_arch:
.LFB39:
        .cfi_startproc
        stm     %r6,%r15,24(%r15)
        .cfi_offset 6, -72
        .cfi_offset 7, -68
        .cfi_offset 8, -64
        .cfi_offset 9, -60
        .cfi_offset 10, -56
        .cfi_offset 11, -52
        .cfi_offset 12, -48
        .cfi_offset 13, -44
        .cfi_offset 14, -40
        .cfi_offset 15, -36
        ahi     %r15,-96
        .cfi_def_cfa_offset 192

        .global __syscall_cancel_arch_start
.type __syscall_cancel_arch_start,@function
__syscall_cancel_arch_start:
        l       %r0,0(%r2)
        tml     %r0,4
        jne     .L5
        lr      %r1,%r3
        lr      %r2,%r4
        lr      %r3,%r5
        lr      %r4,%r6
        l       %r5,192(%r15)
        l       %r6,196(%r15)
        l       %r7,200(%r15)
        svc    0

        .global __syscall_cancel_arch_end
.type __syscall_cancel_arch_end,@function
__syscall_cancel_arch_end:
        l       %r4,152(%r15)
        lm      %r6,%r15,120(%r15)
        .cfi_remember_state
        .cfi_restore 15
        .cfi_restore 14
        .cfi_restore 13
        .cfi_restore 12
        .cfi_restore 11
        .cfi_restore 10
        .cfi_restore 9
        .cfi_restore 8
        .cfi_restore 7
        .cfi_restore 6
        .cfi_def_cfa_offset 96
        br      %r4
.L5:
        .cfi_restore_state
        brasl   %r14,__syscall_do_cancel
        .cfi_endproc
---

The s390x version also shows similar placement:

---
__GI___syscall_cancel_arch:
        .cfi_startproc
        stmg    %r6,%r15,48(%r15)
        .cfi_offset 6, -112
        .cfi_offset 7, -104
        .cfi_offset 8, -96
        .cfi_offset 9, -88
        .cfi_offset 10, -80
        .cfi_offset 11, -72
        .cfi_offset 12, -64
        .cfi_offset 13, -56
        .cfi_offset 14, -48
        .cfi_offset 15, -40
        aghi    %r15,-160
        .cfi_def_cfa_offset 320

        .global __syscall_cancel_arch_start
.type __syscall_cancel_arch_start,@function
__syscall_cancel_arch_start:
        l       %r0,0(%r2)
        tmll    %r0,4
        jne     .L5
        lgr     %r1,%r3
        lgr     %r2,%r4
        lgr     %r3,%r5
        lgr     %r4,%r6
        lg      %r5,320(%r15)
        lg      %r6,328(%r15)
        lg      %r7,336(%r15)
        svc    0

        .global __syscall_cancel_arch_end
.type __syscall_cancel_arch_end,@function
__syscall_cancel_arch_end:
        lg      %r4,272(%r15)
        lmg     %r6,%r15,208(%r15)
        .cfi_remember_state
        .cfi_restore 15
        .cfi_restore 14
        .cfi_restore 13
        .cfi_restore 12
        .cfi_restore 11
        .cfi_restore 10
        .cfi_restore 9
        .cfi_restore 8
        .cfi_restore 7
        .cfi_restore 6
        .cfi_def_cfa_offset 160
        br      %r4
.L5:
        .cfi_restore_state
        brasl   %r14,__syscall_do_cancel
        .cfi_endproc
---

Checked with a s390-linux-gnu and s390x-linux-gnu build with
run-tests-built=no.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/s390/sigcontextinfo.h (ucontext_get_pc):
	New function.
---
 ChangeLog                                     |  5 ++++-
 sysdeps/unix/sysv/linux/s390/sigcontextinfo.h | 17 +++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/sysdeps/unix/sysv/linux/s390/sigcontextinfo.h b/sysdeps/unix/sysv/linux/s390/sigcontextinfo.h
index 2533e63..89e6c47 100644
--- a/sysdeps/unix/sysv/linux/s390/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/s390/sigcontextinfo.h
@@ -16,7 +16,11 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
 #include <signal.h>
+#include <stdint.h>
 
 #define SIGCONTEXT struct sigcontext *
 #define SIGCONTEXT_EXTRA_ARGS
@@ -25,3 +29,16 @@
 #define GET_STACK(ctx)	((void *)((ctx)->sregs->regs.gprs[15]))
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+#ifdef __s390x__
+  return uc->uc_mcontext.psw.addr;
+#else
+  /* We have 31bit addresses, remove bit 0.  */
+  return uc->uc_mcontext.psw.addr & 0x7FFFFFFF;
+#endif
+}
+
+#endif
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 11/21] nptl: ia64: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (9 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 10/21] nptl: s390: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 12/21] nptl: alpha: " Adhemerval Zanella
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the s390 modifications required for the BZ#12683.
It basically adds the required ucontext_get_pc function. a workaround
for mismatched sigcontext::sa_flags defiition between kernel and
GLIBC (tracked by BZ#21634), and an arch specific syscall_cancel
implementation.

IA64 requires an arch-specific syscall_cancel implemetantion because
{INLINE,INTERNAL}_SYSCALL is implemented by branching to a gate
DSO (similar to i386) which renders the pointer comparison in
SIGCANCEL handler wrong.  This incurs in performance penalty due the
use of a break instruction insteaf of a eds one, however
cancellable syscalls should potentially incur in syscalls blocking.

Checked with a ia64-linux-gnu build with run-tests-built=no.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h (ucontext_get_pc,
	ucontext_get_mask): New functions.
	* sysdeps/unix/sysv/linux/ia64/syscall_cancel.S: New file.
---
 ChangeLog                                     |  5 ++
 sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h | 24 +++++++
 sysdeps/unix/sysv/linux/ia64/syscall_cancel.S | 94 +++++++++++++++++++++++++++
 3 files changed, 123 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/ia64/syscall_cancel.S

diff --git a/sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h b/sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h
index 214292d..24cfb51 100644
--- a/sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h
@@ -15,6 +15,11 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
+
 #define SIGCONTEXT siginfo_t *_si, struct sigcontext *
 #define SIGCONTEXT_EXTRA_ARGS _si,
 #define GET_PC(ctx)	((ctx)->sc_ip)
@@ -23,3 +28,22 @@
 
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+/* Different that other architectures, ia64 pass a sigcontext_t struct
+   in third argument for sa_sigaction handler with SA_SIGINFO.  */
+static inline uintptr_t
+ucontext_get_pc (const struct sigcontext *sigctx)
+{
+  return sigctx->sc_ip;
+}
+
+static inline sigset_t *
+ucontext_get_mask (const struct sigcontext *sigctx)
+{
+  /* IA64 sigcontext::sa_mask is a sigset_t since Linux 2.6.12 (initial
+     git repository build).  */
+  return (sigset_t *) &sigctx->sc_mask;
+}
+#define UCONTEXT_SIGMASK(ctx) ucontext_get_mask (ctx)
+
+#endif /* _SIGCONTEXTINFO_H  */
diff --git a/sysdeps/unix/sysv/linux/ia64/syscall_cancel.S b/sysdeps/unix/sysv/linux/ia64/syscall_cancel.S
new file mode 100644
index 0000000..9c6c9d3
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/ia64/syscall_cancel.S
@@ -0,0 +1,94 @@
+/* Cancellable syscall wrapper.  Linux/IA64 version.
+   Copyright (C) 2017 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>
+#undef ret
+
+/* long int __syscall_cancel_arch (int *cancelhandling, long int nr,
+				   long int arg1, long int arg2, long int arg3,
+				   long int arg4, long int arg5, long int arg6)
+*/
+
+ENTRY (__syscall_cancel_arch)
+	.prologue 14, 40
+	.mmi
+	.save ar.pfs, r41
+	alloc r41 = ar.pfs, 8, 4, 8, 0
+	.vframe r42
+	mov r42 = r12
+	.save rp, r40
+	mov r40 = b0
+	.body
+	;;
+
+	.global __syscall_cancel_arch_start	
+	.type __syscall_cancel_arch_start,@function	
+__syscall_cancel_arch_start:
+
+	;;
+	.mmi
+	nop 0
+	ld4.acq r14 = [r32]
+	nop 0
+	;;
+	.mib
+	nop 0
+	tbit.z p6, p7 = r14, 2
+	.pred.safe_across_calls p1-p63
+	(p7) br.call.dpnt.many b0 = __syscall_do_cancel#
+	.pred.safe_across_calls p1-p5,p16-p63
+	;;
+	.mmi
+	mov r15 = r33
+	mov r49 = r39
+	mov r48 = r38
+	.mmi
+	mov r47 = r37
+	mov r46 = r36
+	mov r45 = r35
+	;;
+	.mmi
+	nop 0
+	mov r44 = r34
+	nop 0
+	;;
+	break 0x100000
+	;;
+
+	.global __syscall_cancel_arch_end	
+	.type __syscall_cancel_arch_end,@function	
+__syscall_cancel_arch_end:
+
+	;;
+	.mmi
+	cmp.ne p6, p7 = -1, r10
+	nop 0
+	mov ar.pfs = r41
+	;;
+	.mmi
+	nop 0
+	(p7) sub r8 = r0, r8
+	mov b0 = r40
+	.mmb
+	nop 0
+	.restore sp
+	mov r12 = r42
+	br.ret.sptk.many b0
+
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 12/21] nptl: alpha: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (10 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 11/21] nptl: ia64: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 13/21] nptl: m68k: " Adhemerval Zanella
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the alpha modifications required for the BZ#12683.
It basically adds the required ucontext_get_pc function

The default syscall_cancel.c should be fine for alpha and GCC 6.1
generates the following cod for syscall_cancel.os:

---
0000000000000000 <__GI___syscall_cancel_arch>:
   0:   00 00 bb 27     ldah    gp,0(t12)
   4:   00 00 bd 23     lda     gp,0(gp)
   8:   f0 ff de 23     lda     sp,-16(sp)
   c:   00 04 f1 47     mov     a1,v0
  10:   00 00 5e b7     stq     ra,0(sp)

0000000000000014 <__syscall_cancel_arch_start>:
  14:   00 00 30 a0     ldl     t0,0(a0)
  18:   01 00 e1 43     sextl   t0,t0
  1c:   01 90 20 44     and     t0,0x4,t0
  20:   0f 00 20 f4     bne     t0,60 <__syscall_cancel_arch_end+0x20>
  24:   10 04 f2 47     mov     a2,a0
  28:   11 04 f3 47     mov     a3,a1
  2c:   12 04 f4 47     mov     a4,a2
  30:   10 00 9e a6     ldq     a4,16(sp)
  34:   13 04 f5 47     mov     a5,a3
  38:   18 00 be a6     ldq     a5,24(sp)
  3c:   83 00 00 00     callsys

0000000000000040 <__syscall_cancel_arch_end>:
  40:   21 05 e0 43     negq    v0,t0
  44:   00 00 5e a7     ldq     ra,0(sp)
  48:   c0 04 61 46     cmovne  a3,t0,v0
  4c:   10 00 de 23     lda     sp,16(sp)
  50:   01 80 fa 6b     ret
  54:   00 00 fe 2f     unop
  58:   1f 04 ff 47     nop
  5c:   00 00 fe 2f     unop
  60:   00 00 7d a7     ldq     t12,0(gp)
  64:   00 40 5b 6b     jsr     ra,(t12),68 <__syscall_cancel_arch_end+0x28>
  68:   1f 04 ff 47     nop
  6c:   00 00 fe 2f     unop
---

Checked on alpha-linux-gnu, no regression found.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h (ucontext_get_pc):
	New function.
---
 ChangeLog                                      |  4 ++++
 sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h | 13 +++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h b/sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h
index 23f66d0..f762fff 100644
--- a/sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h
@@ -15,6 +15,11 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
+
 #define SIGCONTEXT int _code, struct sigcontext *
 #define SIGCONTEXT_EXTRA_ARGS _code,
 #define GET_PC(ctx)	((void *) (ctx)->sc_pc)
@@ -22,3 +27,11 @@
 #define GET_STACK(ctx)	((void *) (ctx)->sc_regs[30])
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+  return uc->uc_mcontext.sc_pc;
+}
+
+#endif /* _SIGCONTEXTINFO_H  */
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 13/21] nptl: m68k: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (11 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 12/21] nptl: alpha: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 14/21] nptl: microblaze: " Adhemerval Zanella
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the m68k modifications required for the BZ#12683.
It basically adds the required ucontext_get_pc function

The default syscall_cancel.c should is as expected for m68k with
GCC 6.2.1.  It generates the following code for syscall_cancel.os:

---
00000000 <__GI___syscall_cancel_arch>:
   0:   4e56 0000       linkw %fp,#0
   4:   48e7 3c00       moveml %d2-%d5,%sp@-

00000008 <__syscall_cancel_arch_start>:
   8:   206e 0008       moveal %fp@(8),%a0
   c:   2010            movel %a0@,%d0
   e:   0800 0002       btst #2,%d0
  12:   6628            bnes 3c <__syscall_cancel_arch_end+0xa>
  14:   206e 0024       moveal %fp@(36),%a0
  18:   2a2e 0020       movel %fp@(32),%d5
  1c:   282e 001c       movel %fp@(28),%d4
  20:   262e 0018       movel %fp@(24),%d3
  24:   242e 0014       movel %fp@(20),%d2
  28:   222e 0010       movel %fp@(16),%d1
  2c:   202e 000c       movel %fp@(12),%d0
  30:   4e40            trap #0

00000032 <__syscall_cancel_arch_end>:
  32:   4cee 003c fff0  moveml %fp@(-16),%d2-%d5
  38:   4e5e            unlk %fp
  3a:   4e75            rts
  3c:   61ff 0000 0000  bsrl 3e <__syscall_cancel_arch_end+0xc>
---

Checked against a build and make check run-built-tests=no for
m68k-linux-gnu.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/m68k/sigcontextinfo.h (ucontext_get_pc):
	New function.
---
 ChangeLog                                     |  4 ++++
 sysdeps/unix/sysv/linux/m68k/sigcontextinfo.h | 13 +++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/m68k/sigcontextinfo.h b/sysdeps/unix/sysv/linux/m68k/sigcontextinfo.h
index 58374ed..3a288ea 100644
--- a/sysdeps/unix/sysv/linux/m68k/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/m68k/sigcontextinfo.h
@@ -16,6 +16,11 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
+
 #define SIGCONTEXT int _code, struct sigcontext *
 #define SIGCONTEXT_EXTRA_ARGS _code,
 #define GET_PC(ctx)	((void *) (ctx)->sc_pc)
@@ -23,3 +28,11 @@
 #define GET_STACK(ctx)	((void *) (ctx)->sc_usp)
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+  return uc->uc_mcontext.gregs[R_PC];
+}
+
+#endif /* _SIGCONTEXTINFO_H  */
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 14/21] nptl: microblaze: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (12 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 13/21] nptl: m68k: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 15/21] nptl: tile: " Adhemerval Zanella
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the microblaze modifications required for the BZ#12683.
It basically adds the required ucontext_get_pc function.

Microblaze requires an arch specific assembly implementation because
the archicture INTERNAL_SYSCALL_NCS implementation adds a nop after
the brki instruction because the instruction expect a delay branch
slot.  I based this implementation on generated assembly using GCC 6.1.

Checked against a build and make check run-built-tests=no for
microblaze-linux-gnu.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/microblaze/syscall_cancel.S: New file.
	* sysdeps/unix/sysv/linux/microblaze/sigcontextinfo.h
	(ucontext_get_pc): New function.
---
 ChangeLog                                          |  5 ++
 .../unix/sysv/linux/microblaze/sigcontextinfo.h    | 13 +++++
 .../unix/sysv/linux/microblaze/syscall_cancel.S    | 62 ++++++++++++++++++++++
 3 files changed, 80 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/microblaze/syscall_cancel.S

diff --git a/sysdeps/unix/sysv/linux/microblaze/sigcontextinfo.h b/sysdeps/unix/sysv/linux/microblaze/sigcontextinfo.h
index 64d8f2f..fae7144 100644
--- a/sysdeps/unix/sysv/linux/microblaze/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/microblaze/sigcontextinfo.h
@@ -16,6 +16,11 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
+
 #define SIGCONTEXT int _code, ucontext_t *
 #define SIGCONTEXT_EXTRA_ARGS _code,
 #define GET_PC(ctx)    ((void *) (ctx)->uc_mcontext.regs.pc)
@@ -23,3 +28,11 @@
 #define GET_STACK(ctx) ((void *) (ctx)->uc_mcontext.regs.sp)
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+  return uc->uc_mcontext.regs.pc;
+}
+
+#endif /* _SIGCONTEXTINFO_H  */
diff --git a/sysdeps/unix/sysv/linux/microblaze/syscall_cancel.S b/sysdeps/unix/sysv/linux/microblaze/syscall_cancel.S
new file mode 100644
index 0000000..d892362
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/microblaze/syscall_cancel.S
@@ -0,0 +1,62 @@
+/* Cancellable syscall wrapper.  Linux/microblaze version.
+   Copyright (C) 2017 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 __syscall_cancel_arch (int *cancelhandling,
+				   long int nr,
+				   long int arg1,
+				   long int arg2,
+				   long int arg3,
+				   long int arg4,
+				   long int arg5,
+				   long int arg6)  */
+
+ENTRY (__syscall_cancel_arch)
+
+	.globl __syscall_cancel_arch_start
+__syscall_cancel_arch_start:
+
+	lwi	r3,r5,0
+	andi	r3,r3,4 #and1
+	bneid	r3,1f
+	addk	r12,r6,r0
+
+	addk	r5,r7,r0
+	addk	r6,r8,r0
+	addk	r7,r9,r0
+	addk	r8,r10,r0
+	lwi	r9,r1,56
+	lwi	r10,r1,60
+	brki	r14,8
+
+	.globl __syscall_cancel_arch_end
+__syscall_cancel_arch_end:
+
+	nop
+	lwi	r15,r1,0
+	rtsd	r15,8
+	addik	r1,r1,28
+
+1:
+	brlid	r15, __syscall_do_cancel
+	nop
+
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
+
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 15/21] nptl: tile: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (13 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 14/21] nptl: microblaze: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 16/21] nptl: sparc: " Adhemerval Zanella
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the tile modifications required for the BZ#12683.
It basically adds the required ucontext_get_pc function

The default syscall_cancel.c should be as expected for TILE. With
GCC 6.1 syscall_cancel.c generates the following code:

* TILEGX

0000000000000000 <__GI___syscall_cancel_arch>:
   0:   c7bf46ce576bfd9d        { move r29, sp ; addi r28, sp, -24 ; st sp, lr }
   8:   283bf825401e0db6        { addi sp, sp, -32 ; move r10, r1 }
  10:   eeedf85b85c18d9b        { addi r27, sp, 24 ; move lr, r2 ; st r28, r29 }
  18:   eef5f88155bbf0c1        { move r1, r3 ; move r2, r4 ; st r27, r30 }
  20:   283bf8c25107f143        { move r3, r5 ; move r4, r6 }
  28:   283bf8e2d1483000        { move r5, r7 }

0000000000000030 <__syscall_cancel_arch_start>:
  30:   9c5e4000340c3000        { ld4s r11, r0 }
  38:   18182165d1483000        { andi r11, r11, 4 }
  40:   17c00163d1483000        { bnez r11, 78 <__syscall_cancel_arch_end+0x20> }
  48:   283bfee051483000        { move r0, lr }
  50:   286b180051485000        { swint1 }

0000000000000058 <__syscall_cancel_arch_end>:
  58:   180906ced1401ff7        { subx lr, zero, r1 ; addi r29, sp, 32 }
  60:   87b8c6ce4dd77040        { cmovnez r0, r1, lr ; addi r28, sp, 24 ; ld lr, r29 }
  68:   9ef6400035cc3000        { ld r30, r28 }
  70:   286a6ee040120db6        { addi sp, sp, 32 ; jrp lr }
  78:   2000000051483000        { jal 78 <__syscall_cancel_arch_end+0x20> }

* TILEGX32

00000000 <__GI___syscall_cancel_arch>:
   0:   cbbfc6ce576bfd9d        { move r29, sp ; addxi r28, sp, -8 ; st sp, lr }
   8:   283bf825402f0db6        { addxi sp, sp, -16 ; move r10, r1 }
  10:   eeedf860d5cbf0b7        { move lr, r2 ; move r1, r3 ; st r28, r29 }
  18:   283bf8a1d107f102        { move r2, r4 ; move r3, r5 }
  20:   283bf8e2d107f184        { move r4, r6 ; move r5, r7 }

00000028 <__syscall_cancel_arch_start>:
  28:   9c5e4000340c3000        { ld4s r11, r0 }
  30:   18182165d1483000        { andi r11, r11, 4 }
  38:   17c0016351483000        { bnez r11, 68 <__syscall_cancel_arch_end+0x18> }
  40:   283bfee051483000        { move r0, lr }
  48:   286b180051485000        { swint1 }

00000050 <__syscall_cancel_arch_end>:
  50:   28660fe540210d9d        { addxi r29, sp, 16 ; subx r10, zero, r1 }
  58:   9fbe40004dd4a040        { cmovnez r0, r1, r10 ; ld lr, r29 }
  60:   286a6ee040210db6        { addxi sp, sp, 16 ; jrp lr }
  68:   2000000051483000        { jal 68 <__syscall_cancel_arch_end+0x18> }

Checked with build and make check run-built-tests=no for tilegx{32}-linux-gnu.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/tile/sigcontextinfo.h (ucontext_get_pc):
	New function.
---
 ChangeLog                                     |  4 ++++
 sysdeps/unix/sysv/linux/tile/sigcontextinfo.h | 12 ++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/tile/sigcontextinfo.h b/sysdeps/unix/sysv/linux/tile/sigcontextinfo.h
index 82bc0c7..c6edd2a 100644
--- a/sysdeps/unix/sysv/linux/tile/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/tile/sigcontextinfo.h
@@ -16,6 +16,10 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
 #include <arch/abi.h>
 
 #define SIGCONTEXT siginfo_t *_si, ucontext_t *
@@ -25,3 +29,11 @@
 #define GET_STACK(ctx)	((void *) (long) ctx->uc_mcontext.sp)
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+  return uc->uc_mcontext.pc;
+}
+
+#endif /* _SIGCONTEXTINFO_H  */
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 16/21] nptl: sparc: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (14 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 15/21] nptl: tile: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 17/21] nptl: nios2: " Adhemerval Zanella
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the sparc modifications required for the BZ#12683.
It basically adds the required ucontext_get_pc function, cancellable
syscall wrappers, and a fix for pause.

Sparc requires arch-specific syscall_cancel implementation because
INLINE_SYSCALL_NCS uses the __SYSCALL_STRING (defined different
for sparc32 and sparc64) and it issues additional instructions
after the syscall one to check the resulting error code.  When used
in the default syscall_cancel.c implementation the label
__syscall_cancel_arch_end is not placed just after the syscall as
expected.  Both 32 and 64 bits version were based on default C version
built with GCC 6.1.

Also, different than other architectures, SPARC passes the sigcontext_t
struct pointer as third argument in the signal handler set with
SA_SIGINFO (some info at [1]) for 64 bits and the pt_regs in 32 bits.
From Linux code:

* arch/sparc/kernel/signal_64.c

428         /* 3. signal handler back-trampoline and parameters */
429         regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS;
430         regs->u_regs[UREG_I0] = ksig->sig;
431         regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
432
433         /* The sigcontext is passed in this way because of how it
434          * is defined in GLIBC's /usr/include/bits/sigcontext.h
435          * for sparc64.  It includes the 128 bytes of siginfo_t.
436          */
437         regs->u_regs[UREG_I2] = (unsigned long) &sf->info;

* arch/sparc/kernel/signal_32.c:

392         regs->u_regs[UREG_FP] = (unsigned long) sf;
393         regs->u_regs[UREG_I0] = ksig->sig;
394         regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
395         regs->u_regs[UREG_I2] = (unsigned long) &sf->regs;
396
397         regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
398         regs->npc = (regs->pc + 4);

So to access the signal mask in the signal frame, a arch-specific
ucontext_get_mask is defined which obtain the sa_mask from the context.

Checked on a SPARC T5 for sparc64-linux-gnu and sparcv9-linux-gnu.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/sparc/sparc32/sigcontextinfo.h
	(ucontext_get_pc): New function.
	* sysdeps/unix/sysv/linux/sparc/sparc64/sigcontextinfo.h
	(ucontext_get_pc): Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/syscall_cancel.S: New file.
	* sysdeps/unix/sysv/linux/sparc/sparc64/syscall_cancel.S: Likwise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/pause.c: New file.

[1] https://www.spinics.net/lists/sparclinux/msg05037.html
---
 ChangeLog                                          |  9 +++
 sysdeps/unix/sysv/linux/sparc/lowlevellock.h       |  2 +-
 .../unix/sysv/linux/sparc/sparc32/sigcontextinfo.h | 52 +++++++++++++++
 .../unix/sysv/linux/sparc/sparc32/syscall_cancel.S | 74 ++++++++++++++++++++++
 sysdeps/unix/sysv/linux/sparc/sparc64/pause.c      | 25 ++++++++
 .../unix/sysv/linux/sparc/sparc64/sigcontextinfo.h | 40 ++++++++++++
 .../unix/sysv/linux/sparc/sparc64/syscall_cancel.S | 74 ++++++++++++++++++++++
 7 files changed, 275 insertions(+), 1 deletion(-)
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/syscall_cancel.S
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc64/pause.c
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc64/syscall_cancel.S

diff --git a/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
index e2c0b2a..ed2e746 100644
--- a/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
+++ b/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
@@ -117,7 +117,7 @@ __lll_timedlock (int *futex, const struct timespec *abstime, int private)
     {							\
       __typeof (tid) __tid;				\
       while ((__tid = (tid)) != 0)			\
-	lll_futex_wait (&(tid), __tid, LLL_SHARED);	\
+	lll_futex_wait_cancel (&(tid), __tid, LLL_SHARED); \
     }							\
   while (0)
 
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/sigcontextinfo.h b/sysdeps/unix/sysv/linux/sparc/sparc32/sigcontextinfo.h
index 91233b8..4114035 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/sigcontextinfo.h
@@ -16,6 +16,11 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
+
 #define SIGCONTEXT struct sigcontext *
 #define SIGCONTEXT_EXTRA_ARGS
 #define GET_PC(__ctx)	((void *) ((__ctx)->si_regs.pc))
@@ -29,3 +34,50 @@
 #define GET_FRAME(__ctx)	ADVANCE_STACK_FRAME (GET_STACK(__ctx))
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+/* Different that other architectures, SPARC32 pass a pt_regs (or pt_regs32
+   in 32 bits compat mode) struct pointer as third argument for sa_sigaction
+   handler with SA_SIGINFO.
+
+   Also current sparc32 rt signal frame layout is:
+
+   field                                  | size
+   ---------------------------------------| ----
+   struct rt_signal_frame {               |
+     struct sparc_stackf     ss;          |  96
+     siginfo_t               info;        | 128
+     struct pt_regs          regs;        |  80
+     sigset_t                mask;        | 128
+     __siginfo_fpu_t __user  *fpu_save;   |   4
+     unsigned int            insns[2];    |   8
+     stack_t                 stack;       |  12
+     unsigned int            extra_size;  |   4
+     __siginfo_rwin_t __user *rwin_save;  |   4
+   };
+
+   So to obtain a pointer to signal mask based on address of pt_regs
+   we need to add 208.  */
+
+struct pt_regs32
+{
+   unsigned int psr;
+   unsigned int pc;
+   unsigned int npc;
+   unsigned int y;
+   unsigned int u_regs[16];
+};
+
+static inline uintptr_t
+ucontext_get_pc (struct pt_regs32 *regs)
+{
+  return regs->pc;
+}
+
+static inline sigset_t *
+ucontext_get_mask (const void *ctx)
+{
+  return (sigset_t *)((uintptr_t)ctx + 208);
+}
+#define UCONTEXT_SIGMASK(ctx) ucontext_get_mask (ctx)
+
+#endif /* _SIGCONTEXTINFO_H  */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/syscall_cancel.S b/sysdeps/unix/sysv/linux/sparc/sparc32/syscall_cancel.S
new file mode 100644
index 0000000..c06f9d1
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/syscall_cancel.S
@@ -0,0 +1,74 @@
+/* Cancellable syscall wrapper.  Linux/sparc32 version.
+   Copyright (C) 2017 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 __syscall_cancel_arch (int *cancelhandling,
+				   long int nr,
+				   long int arg1,
+				   long int arg2,
+				   long int arg3,
+				   long int arg4,
+				   long int arg5,
+				   long int arg6)  */
+
+ENTRY (__syscall_cancel_arch)
+	save	%sp, -104, %sp
+
+	cfi_window_save
+	cfi_register (15, 31)
+	cfi_def_cfa_register (30)
+
+	.globl __syscall_cancel_arch_start
+__syscall_cancel_arch_start:
+
+	/* if (*cancelhandling & CANCELED_BITMASK)
+	     __syscall_do_cancel()  */
+	ld	[%i0], %g2
+	andcc	%g2, 4, %g0
+	bne,pn	%icc, 2f
+
+	/* Issue a 6 argument syscall.  */
+	mov	%i1, %g1
+	mov	%i2, %o0
+	mov	%i3, %o1
+	mov	%i4, %o2
+	mov	%i5, %o3
+	ld	[%fp+92], %o4
+	ld	[%fp+96], %o5
+	ta	0x10
+
+	.globl __syscall_cancel_arch_end
+__syscall_cancel_arch_end:
+	bcc	1f
+	mov	0,%g1
+	sub	%g0, %o0, %o0
+	mov	1, %g1
+
+1:
+	mov	%o0, %i0
+	return	%i7+8
+	 nop
+
+2:
+	call	__syscall_do_cancel, 0
+	 nop
+	nop
+
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/pause.c b/sysdeps/unix/sysv/linux/sparc/sparc64/pause.c
new file mode 100644
index 0000000..4a0cf4d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/pause.c
@@ -0,0 +1,25 @@
+/* Linux pause syscall implementation.  Linux/sparc64.
+   Copyright (C) 2017 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 <sys/syscall.h>
+
+/* On sparc interrupted pause syscall returns with a PC indicating a
+   side-effect and this deviates from other architectures.  Fall back to
+   ppool implementation.  */
+#undef __NR_pause
+#include <sysdeps/unix/sysv/linux/pause.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/sigcontextinfo.h b/sysdeps/unix/sysv/linux/sparc/sparc64/sigcontextinfo.h
index c9d2685..dc04c42 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/sigcontextinfo.h
@@ -16,6 +16,11 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
+
 #ifndef STACK_BIAS
 #define STACK_BIAS 2047
 #endif
@@ -29,3 +34,38 @@
 #define GET_FRAME(__ctx)	ADVANCE_STACK_FRAME (GET_STACK (__ctx))
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+/* Different that other architectures, SPARC64 pass a sigcontext_t struct
+   pointer in third argument for sa_sigaction handler with SA_SIGINFO.
+
+   Also current sparc64 rt signal frame layout is:
+
+   field                                  | size
+   ---------------------------------------| ----
+   struct rt_signal_frame {               |
+      struct sparc_stackf     ss;         | 192
+      siginfo_t               info;       | 128
+      struct pt_regs          regs;       | 160
+      __siginfo_fpu_t __user  *fpu_save;  |   8
+      stack_t                 stack;      |  24
+      sigset_t                mask;       | 128
+      __siginfo_rwin_t        *rwin_save; |   8
+   };
+
+   So to obtain a pointer to signal mask based on address of info
+   we need to add 320.  */
+
+static inline uintptr_t
+ucontext_get_pc (const struct sigcontext *sigctx)
+{
+  return sigctx->sigc_regs.tpc;
+}
+
+static inline sigset_t *
+ucontext_get_mask (const void *ctx)
+{
+  return (sigset_t *)((uintptr_t)ctx + 320);
+}
+#define UCONTEXT_SIGMASK(ctx) ucontext_get_mask (ctx)
+
+#endif /* _SIGCONTEXTINFO_H  */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/syscall_cancel.S b/sysdeps/unix/sysv/linux/sparc/sparc64/syscall_cancel.S
new file mode 100644
index 0000000..f3eef78
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/syscall_cancel.S
@@ -0,0 +1,74 @@
+/* Cancellable syscall wrapper.  Linux/sparc64 version.
+   Copyright (C) 2017 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 __syscall_cancel_arch (int *cancelhandling,
+					long int nr,
+					long int arg1,
+					long int arg2,
+					long int arg3,
+					long int arg4,
+					long int arg5,
+					long int arg6)  */
+
+ENTRY (__syscall_cancel_arch)
+	save	%sp, -176, %sp
+
+	cfi_window_save
+	cfi_register (15, 31)
+	cfi_def_cfa_register (30)
+
+	.globl __syscall_cancel_arch_start
+__syscall_cancel_arch_start:
+
+	/* if (*cancelhandling & CANCELED_BITMASK)
+	     __syscall_do_cancel()  */
+	lduw	[%i0], %g1
+	andcc	%g1, 4, %g0
+	bne,pn	%xcc, 2f
+
+	/* Issue a 6 argument syscall.  */
+	mov	%i1, %g1
+	mov	%i2, %o0
+	mov	%i3, %o1
+	mov	%i4, %o2
+	mov	%i5, %o3
+	ldx	[%fp + STACK_BIAS + 176], %o4
+	ldx	[%fp + STACK_BIAS + 184], %o5
+	ta	0x6d
+
+	.global __syscall_cancel_arch_end
+__syscall_cancel_arch_end:
+
+	bcc,pt	%xcc, 1f
+	mov	0, %g1
+	sub	%g0, %o0, %o0
+	mov	1, %g1
+1:
+	mov	%o0, %i0
+	return	%i7+8
+	nop
+
+2:
+	call	__syscall_do_cancel, 0
+	nop
+	nop
+
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 17/21] nptl: nios2: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (15 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 16/21] nptl: sparc: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 18/21] nptl: sh: " Adhemerval Zanella
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the nios2 modifications required for the BZ#12683.
It basically adds the required ucontext_get_pc function.

The default syscall_cancel.c should be as expected for NIOS2. With
GCC 6.2.1 syscall_cancel.c generates the following code:

---
00000000 <__GI___syscall_cancel_arch>:
   0:   defffe04        addi    sp,sp,-8
   4:   dd800015        stw     r22,0(sp)
   8:   002ce03a        nextpc  r22
   c:   02000034        movhi   r8,0
  10:   42000004        addi    r8,r8,0
  14:   dfc00115        stw     ra,4(sp)
  18:   b22d883a        add     r22,r22,r8

0000001c <__syscall_cancel_arch_start>:
  1c:   20c00017        ldw     r3,0(r4)
  20:   18c0010c        andi    r3,r3,4
  24:   18000f1e        bne     r3,zero,64 <__syscall_cancel_arch_end+0x18>
  28:   3015883a        mov     r10,r6
  2c:   2805883a        mov     r2,r5
  30:   da400517        ldw     r9,20(sp)
  34:   380b883a        mov     r5,r7
  38:   da000417        ldw     r8,16(sp)
  3c:   d9c00317        ldw     r7,12(sp)
  40:   d9800217        ldw     r6,8(sp)
  44:   5009883a        mov     r4,r10
  48:   003b683a        trap    0

0000004c <__syscall_cancel_arch_end>:
  4c:   38000126        beq     r7,zero,54 <__syscall_cancel_arch_end+0x8>
  50:   0085c83a        sub     r2,zero,r2
  54:   dfc00117        ldw     ra,4(sp)
  58:   dd800017        ldw     r22,0(sp)
  5c:   dec00204        addi    sp,sp,8
  60:   f800283a        ret
  64:   b0800017        ldw     r2,0(r22)
  68:   103ee83a        callr   r2
---

Checked against a build and make check run-built-tests=no for
nios2-linux-gnu.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/nios2/sigcontextinfo.h (ucontext_get_pc):
	New function.
---
 ChangeLog                                      |  4 ++++
 sysdeps/unix/sysv/linux/nios2/sigcontextinfo.h | 16 ++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/nios2/sigcontextinfo.h b/sysdeps/unix/sysv/linux/nios2/sigcontextinfo.h
index 57b9b50..7ae735f 100644
--- a/sysdeps/unix/sysv/linux/nios2/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/nios2/sigcontextinfo.h
@@ -16,6 +16,11 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
+
 #include <sys/ucontext.h>
 #include "kernel-features.h"
 
@@ -33,3 +38,14 @@
   (act)->sa_flags |= SA_SIGINFO; \
   (sigaction) (sig, act, oact); \
 })
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+  /* rt_restore_ucontext (arch/nios/kernel/signal.c) sets this position
+     to 'ea' register which is stated as exception return address (pc)
+     at arch/nios2/include/asm/ptrace.h.  */
+  return uc->uc_mcontext.regs[27];
+}
+
+#endif /* _SIGCONTEXTINFO_H  */
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 18/21] nptl: sh: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (16 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 17/21] nptl: nios2: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 19/21] nptl: mips: " Adhemerval Zanella
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the sh modifications required for the BZ#12683.
It basically adds the required ucontext_get_pc function and a
cancellable syscall wrapper.

SH requires an arch-specific syscall_cancel because the
INTERNAL_SYSCALL_NCS adds the required or instruction to workaround
a hardware bug [1].  The implementation were based on on default C
version built with GCC 6.2.1.

Checked against a build and make check run-built-tests=no for
sh4-linux-gnu.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/sh/syscall_cancel.S: New file.
	* sysdeps/unix/sysv/linux/sh/sigcontextinfo.h (ucontext_get_pc):
	New function.

[1] http://documentation.renesas.com/eng/products/mpumcu/tu/tnsh7456ae.pdf
---
 ChangeLog                                   |   6 ++
 sysdeps/sh/sysdep.h                         |   1 +
 sysdeps/unix/sysv/linux/sh/sigcontextinfo.h |  11 +++
 sysdeps/unix/sysv/linux/sh/syscall_cancel.S | 125 ++++++++++++++++++++++++++++
 4 files changed, 143 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/sh/syscall_cancel.S

diff --git a/sysdeps/sh/sysdep.h b/sysdeps/sh/sysdep.h
index 37889fb..df34c4c 100644
--- a/sysdeps/sh/sysdep.h
+++ b/sysdeps/sh/sysdep.h
@@ -24,6 +24,7 @@
 
 #define ALIGNARG(log2) log2
 #define ASM_SIZE_DIRECTIVE(name) .size name,.-name
+#define L(label) .L##label
 
 #ifdef SHARED
 #define PLTJMP(_x)	_x##@PLT
diff --git a/sysdeps/unix/sysv/linux/sh/sigcontextinfo.h b/sysdeps/unix/sysv/linux/sh/sigcontextinfo.h
index d6dd48d..239f931 100644
--- a/sysdeps/unix/sysv/linux/sh/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/sh/sigcontextinfo.h
@@ -16,6 +16,9 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
 #define SIGCONTEXT int _a2, int _a3, int _a4, struct sigcontext
 
 #define SIGCONTEXT_EXTRA_ARGS _a2, _a3, _a4,
@@ -24,3 +27,11 @@
 #define GET_STACK(ctx)	((void *) ctx.sc_regs[15])
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+  return uc->uc_mcontext.pc;
+}
+
+#endif /* _SIGCONTEXTINFO_H  */
diff --git a/sysdeps/unix/sysv/linux/sh/syscall_cancel.S b/sysdeps/unix/sysv/linux/sh/syscall_cancel.S
new file mode 100644
index 0000000..02a050d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sh/syscall_cancel.S
@@ -0,0 +1,125 @@
+/* Cancellable syscall wrapper.  Linux/sh version.
+   Copyright (C) 2017 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 __syscall_cancel_arch (int *cancelhandling,
+				   long int nr,
+				   long int arg1,
+				   long int arg2,
+				   long int arg3,
+				   long int arg4,
+				   long int arg5,
+				   long int arg6)  */
+
+ENTRY (__syscall_cancel_arch)
+
+#ifdef SHARED
+	mov.l	r12,@-r15
+	cfi_def_cfa_offset (4)
+	cfi_offset (12, -4)
+	mova	L(GT),r0
+	mov.l	L(GT),r12
+	sts.l	pr,@-r15
+	cfi_def_cfa_offset (8)
+	cfi_offset (17, -8)
+	add	r0,r12
+#else
+	sts.l	pr,@-r15
+	cfi_def_cfa_offset (4)
+	cfi_offset (17, -4)
+#endif
+
+	.globl __syscall_cancel_arch_start
+__syscall_cancel_arch_start:
+
+	/* if (*cancelhandling & CANCELED_BITMASK)
+	     __syscall_do_cancel()  */
+	mov.l	@r4,r0
+	tst	#4,r0
+	bf/s	1f
+
+	/* Issue a 6 argument syscall.  */
+	mov	r5,r3
+	mov	r6,r4
+	mov	r7,r5
+#ifdef SHARED
+	mov.l	@(8,r15),r6
+	mov.l	@(12,r15),r7
+	mov.l	@(16,r15),r0
+	mov.l	@(20,r15),r1
+#else
+	mov.l	@(4,r15),r6
+	mov.l	@(8,r15),r7
+	mov.l	@(12,r15),r0
+	mov.l	@(16,r15),r1
+#endif
+	trapa	#0x16
+
+/* The additional or is a workaround for a hardware issue:
+   http://documentation.renesas.com/eng/products/mpumcu/tu/tnsh7456ae.pdf  */
+	.globl __syscall_cancel_arch_end
+__syscall_cancel_arch_end:
+
+	or	r0,r0
+	or	r0,r0
+	or	r0,r0
+	or	r0,r0
+	or	r0,r0
+
+	lds.l	@r15+,pr
+	cfi_remember_state
+	cfi_restore (17)
+#ifdef SHARED
+	cfi_def_cfa_offset (4)
+	rts
+	mov.l	@r15+,r12
+	cfi_def_cfa_offset (0)
+	cfi_restore (12)
+	.align 1
+1:
+	cfi_restore_state
+	mov.l	L(SC),r1
+	bsrf	r1
+L(M):
+	nop
+
+	.align 2
+L(GT):
+	.long	_GLOBAL_OFFSET_TABLE_
+L(SC):
+	.long	__syscall_do_cancel-(L(M)+2)
+#else
+	cfi_def_cfa_offset (0)
+	rts
+	nop
+
+	.align 1
+1:
+	cfi_restore_state
+	mov.l	2f,r1
+	jsr	@r1
+	nop
+
+	.align 2
+2:
+	.long	__syscall_do_cancel
+#endif
+
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 19/21] nptl: mips: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (17 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 18/21] nptl: sh: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 20/21] nptl: hppa: " Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 21/21] nptl: riscv: " Adhemerval Zanella
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the mips modifications required for the BZ#12683.
It adds the required ucontext_get_pc function, a mips32 cancellable
syscall wrapper and 7 argument cancellable syscall support.

To avoid code pessimization and add a requirement on all architectures
to support {INLINE,INTERNAL)_SYSCALL with 7 argument, its support is
added through a flag, HAVE_CANCELABLE_SYSCALL_WITH_7_ARGS, which changes
the signature and prototype of the requires macros and functions
(SYSCALL_CANCEL, __syscall_cancel and __syscall_cancel_arch). As
default 6 arguments cancellable syscalls are use.

MIPS o32 requires an arch-specific implementation because
INTERNAL_SYSCALL_NCS adds an 'addiu' just after the syscall
instruction which invalidates the checks on sigcancel_handler.

Checked against a build and make check run-built-tests=no for
mips-gnu-linux, mips64-linux-gnu, mips64-n32-linux-gnu.  I also
ran some basic o32 and n64 cancellation tests on a simulated
mips64 qemu system.

	[BZ #12683]
	* nptl/libc-cancellation.c (__syscall_cancel): Define and use 7
	argument syscall if architecture requires it.
	* nptl/pthreadP.h (__syscall_cancel_arch): Likewise.
	* sysdeps/unix/sysdep.h (__syscall_cancel, __SYSCALL_CANCEL*): Define
	with 7 argument if architecture requires it.
	(__SYSCALL_CANCEL7_ARG_DEF): New macro.
	(__SYSCALL_CANCEL7_ARG): Likewise.
	(__SYSCALL_CANCEL7_ARG7): Likewise.
	* sysdeps/unix/sysv/linux/syscall_cancel.c (__syscall_cancel_arch):
	Likewise.
	* sysdeps/mips/nptl/tls.h (READ_THREAD_POINTER): Check __mips_isa_rev
	existance for macro definition.
	* sysdeps/unix/sysv/linux/mips/sigcontextinfo.h (ucontext_get_pc):
	New function.
	* sysdeps/unix/sysv/linux/mips/mips32/syscall_cancel.S: New file.
	* sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
	(HAVE_CANCELABLE_SYSCALL_WITH_7_ARGS): Define.
---
 ChangeLog                                          |  19 +++
 nptl/libc-cancellation.c                           |   7 +-
 nptl/pthreadP.h                                    |   3 +-
 sysdeps/mips/nptl/tls.h                            |   2 +-
 sysdeps/unix/sysdep.h                              |  38 ++++--
 .../unix/sysv/linux/mips/mips32/syscall_cancel.S   | 128 +++++++++++++++++++++
 sysdeps/unix/sysv/linux/mips/mips32/sysdep.h       |   4 +
 sysdeps/unix/sysv/linux/mips/sigcontextinfo.h      |  13 ++-
 sysdeps/unix/sysv/linux/syscall_cancel.c           |   6 +-
 9 files changed, 204 insertions(+), 16 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/mips/mips32/syscall_cancel.S

diff --git a/nptl/libc-cancellation.c b/nptl/libc-cancellation.c
index 9b054aa..beb433c 100644
--- a/nptl/libc-cancellation.c
+++ b/nptl/libc-cancellation.c
@@ -25,7 +25,7 @@ long int
 __syscall_cancel (__syscall_arg_t nr, __syscall_arg_t a1,
 		  __syscall_arg_t a2, __syscall_arg_t a3,
 		  __syscall_arg_t a4, __syscall_arg_t a5,
-		  __syscall_arg_t a6)
+		  __syscall_arg_t a6 __SYSCALL_CANCEL7_ARG_DEF)
 {
   pthread_t self = (pthread_t) THREAD_SELF;
   volatile struct pthread *pd = (volatile struct pthread *) self;
@@ -35,7 +35,8 @@ __syscall_cancel (__syscall_arg_t nr, __syscall_arg_t a1,
   if (pd->cancelhandling & CANCELSTATE_BITMASK)
     {
       INTERNAL_SYSCALL_DECL (err);
-      result = INTERNAL_SYSCALL_NCS_CALL (nr, err, a1, a2, a3, a4, a5, a6);
+      result = INTERNAL_SYSCALL_NCS_CALL (nr, err, a1, a2, a3, a4, a5, a6
+					  __SYSCALL_CANCEL7_ARG7);
       if (INTERNAL_SYSCALL_ERROR_P (result, err))
 	return -INTERNAL_SYSCALL_ERRNO (result, err);
       return result;
@@ -44,7 +45,7 @@ __syscall_cancel (__syscall_arg_t nr, __syscall_arg_t a1,
   /* Call the arch-specific entry points that contains the globals markers
      to be checked by SIGCANCEL handler.  */
   result = __syscall_cancel_arch (&pd->cancelhandling, nr, a1, a2, a3, a4, a5,
-			          a6);
+			          a6 __SYSCALL_CANCEL7_ARG7);
 
   if ((result == -EINTR)
       && (pd->cancelhandling & CANCELED_BITMASK)
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index bb7ff81..448abea 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -317,7 +317,8 @@ __do_cancel (void)
 
 extern long int __syscall_cancel_arch (volatile int *, __syscall_arg_t nr,
      __syscall_arg_t arg1, __syscall_arg_t arg2, __syscall_arg_t arg3,
-     __syscall_arg_t arg4, __syscall_arg_t arg5, __syscall_arg_t arg6);
+     __syscall_arg_t arg4, __syscall_arg_t arg5, __syscall_arg_t arg6
+     __SYSCALL_CANCEL7_ARG_DEF);
 libc_hidden_proto (__syscall_cancel_arch);
 
 extern void __syscall_do_cancel (void)
diff --git a/sysdeps/mips/nptl/tls.h b/sysdeps/mips/nptl/tls.h
index 5f8cd21..d037cb8 100644
--- a/sysdeps/mips/nptl/tls.h
+++ b/sysdeps/mips/nptl/tls.h
@@ -35,7 +35,7 @@
 # define READ_THREAD_POINTER() (__builtin_thread_pointer ())
 #else
 /* Note: rd must be $v1 to be ABI-conformant.  */
-# if __mips_isa_rev >= 2
+# if defined __mips_isa_rev && __mips_isa_rev >= 2
 #  define READ_THREAD_POINTER() \
      ({ void *__result;							      \
         asm volatile ("rdhwr\t%0, $29" : "=v" (__result));	      	      \
diff --git a/sysdeps/unix/sysdep.h b/sysdeps/unix/sysdep.h
index cea81a5..42720c5 100644
--- a/sysdeps/unix/sysdep.h
+++ b/sysdeps/unix/sysdep.h
@@ -121,29 +121,51 @@ typedef long int __syscall_arg_t;
 # define __SSC(__x) ((__syscall_arg_t) (__x))
 #endif
 
+/* Adjust both the __syscall_cancel and the SYSCALL_CANCEL macro to support
+   7 arguments instead of default 6 (for some architectures like mip32).
+   We need it because using 7 arguments for all architecture would require
+   then to implement both {INTERNAL,INLINE}_SYSCALL and __syscall_cancel_arch
+   to accept 7 arguments.  */
+#ifdef HAVE_CANCELABLE_SYSCALL_WITH_7_ARGS
+# define __SYSCALL_CANCEL7_ARG_DEF 	, __syscall_arg_t arg7
+# define __SYSCALL_CANCEL7_ARG		, 0
+# define __SYSCALL_CANCEL7_ARG7		, arg7
+#else
+# define __SYSCALL_CANCEL7_ARG_DEF
+# define __SYSCALL_CANCEL7_ARG
+# define __SYSCALL_CANCEL7_ARG7
+#endif
+
 long int __syscall_cancel (__syscall_arg_t nr, __syscall_arg_t arg1,
 			   __syscall_arg_t arg2, __syscall_arg_t arg3,
 			   __syscall_arg_t arg4, __syscall_arg_t arg5,
-			   __syscall_arg_t arg6);
+			   __syscall_arg_t arg6 __SYSCALL_CANCEL7_ARG_DEF);
 libc_hidden_proto (__syscall_cancel);
 
 #define __SYSCALL_CANCEL0(name) \
-  (__syscall_cancel)(__NR_##name, 0, 0, 0, 0, 0, 0)
+  (__syscall_cancel)(__NR_##name, 0, 0, 0, 0, 0, 0 \
+		     __SYSCALL_CANCEL7_ARG)
 #define __SYSCALL_CANCEL1(name, a1) \
-  (__syscall_cancel)(__NR_##name, __SSC(a1), 0, 0, 0, 0, 0)
+  (__syscall_cancel)(__NR_##name, __SSC(a1), 0, 0, 0, 0, 0 \
+		     __SYSCALL_CANCEL7_ARG)
 #define __SYSCALL_CANCEL2(name, a1, a2) \
-  (__syscall_cancel)(__NR_##name, __SSC(a1), __SSC(a2), 0, 0, 0, 0)
+  (__syscall_cancel)(__NR_##name, __SSC(a1), __SSC(a2), 0, 0, 0, 0 \
+		     __SYSCALL_CANCEL7_ARG)
 #define __SYSCALL_CANCEL3(name, a1, a2, a3) \
-  (__syscall_cancel)(__NR_##name, __SSC(a1), __SSC(a2), __SSC(a3), 0, 0, 0)
+  (__syscall_cancel)(__NR_##name, __SSC(a1), __SSC(a2), __SSC(a3), 0, 0, 0 \
+		     __SYSCALL_CANCEL7_ARG)
 #define __SYSCALL_CANCEL4(name, a1, a2, a3, a4) \
   (__syscall_cancel)(__NR_##name, __SSC(a1), __SSC(a2), __SSC(a3), \
-		     __SSC(a4), 0, 0)
+		     __SSC(a4), 0, 0 __SYSCALL_CANCEL7_ARG)
 #define __SYSCALL_CANCEL5(name, a1, a2, a3, a4, a5) \
   (__syscall_cancel)(__NR_##name, __SSC(a1), __SSC(a2), __SSC(a3), \
-		     __SSC(a4), __SSC(a5), 0)
+		     __SSC(a4), __SSC(a5), 0 __SYSCALL_CANCEL7_ARG)
 #define __SYSCALL_CANCEL6(name, a1, a2, a3, a4, a5, a6) \
   (__syscall_cancel)(__NR_##name, __SSC(a1), __SSC(a2), __SSC(a3), \
-		     __SSC(a4), __SSC(a5), __SSC(a6))
+		     __SSC(a4), __SSC(a5), __SSC(a6) __SYSCALL_CANCEL7_ARG)
+#define __SYSCALL_CANCEL7(name, a1, a2, a3, a4, a5, a6, a7) \
+  (__syscall_cancel)(__NR_##name, __SSC(a1), __SSC(a2), __SSC(a3), \
+		     __SSC(a4), __SSC(a5), __SSC(a6), __SSC(a7))
 
 #define __SYSCALL_CANCEL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n
 #define __SYSCALL_CANCEL_NARGS(...) \
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/syscall_cancel.S b/sysdeps/unix/sysv/linux/mips/mips32/syscall_cancel.S
new file mode 100644
index 0000000..75c4390
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips32/syscall_cancel.S
@@ -0,0 +1,128 @@
+/* Cancellable syscall wrapper.  Linux/mips32 version.
+   Copyright (C) 2017 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>
+#include <sys/asm.h>
+
+/* long int __syscall_cancel_arch (int *cancelhandling,
+				   __syscall_arg_t nr,
+				   __syscall_arg_t arg1,
+				   __syscall_arg_t arg2,
+				   __syscall_arg_t arg3,
+				   __syscall_arg_t arg4,
+				   __syscall_arg_t arg5,
+				   __syscall_arg_t arg6,
+				   __syscall_arg_t arg7)  */
+
+#define FRAME_SIZE 56
+
+NESTED (__syscall_cancel_arch, FRAME_SIZE, fp)
+	.mask	0xc0070000,-SZREG
+	.fmask	0x00000000,0
+
+	PTR_ADDIU sp, -FRAME_SIZE
+	cfi_def_cfa_offset (FRAME_SIZE)
+
+	sw	fp,48(sp)
+	sw	ra,52(sp)
+	sw	s2,44(sp)
+	sw	s1,40(sp)
+	sw	s0,36(sp)
+#ifdef __PIC__
+	.cprestore	16
+#endif
+	cfi_offset (31, -4)
+	cfi_offset (30, -8)
+	cfi_offset (18, -12)
+	cfi_offset (17, -16)
+	cfi_offset (16, -20)
+	move	fp,sp
+	cfi_def_cfa_register (30)
+
+	.globl __syscall_cancel_arch_start
+	.type __syscall_cancel_arch_start, @function
+__syscall_cancel_arch_start:
+
+	lw	v0,0(a0)
+	andi	v0,v0,0x4
+	bne	v0,zero,2f
+
+	addiu	sp,sp,-16
+	addiu	v0,sp,16
+	sw	v0,24(fp)
+
+	move	s0,a1
+	move	a0,a2
+	move	a1,a3
+	lw	a2,72(fp)
+	lw	a3,76(fp)
+	lw	v0,84(fp)
+	lw	s1,80(fp)
+	lw	s2,88(fp)
+
+	.set	noreorder
+	subu	sp, 32
+	sw	s1, 16(sp)
+	sw	v0, 20(sp)
+	sw	s2, 24(sp)
+	move	v0, $16
+	syscall
+
+	.globl __syscall_cancel_arch_end
+	.type __syscall_cancel_arch_end, @function
+__syscall_cancel_arch_end:
+	addiu	sp, 32
+	.set	reorder
+
+	beq	a3,zero,1f
+	subu	v0,zero,v0
+1:
+	move	sp,fp
+	cfi_remember_state
+	cfi_def_cfa_register (29)
+	lw	ra,52(fp)
+	lw	fp,48(sp)
+	lw	s2,44(sp)
+	lw	s1,40(sp)
+	lw	s0,36(sp)
+	.set	noreorder
+	.set	nomacro
+	jr	ra
+	addiu	sp,sp,FRAME_SIZE
+
+	.set	macro
+	.set	reorder
+
+	cfi_def_cfa_offset (0)
+	cfi_restore (16)
+	cfi_restore (17)
+	cfi_restore (18)
+	cfi_restore (30)
+	cfi_restore (31)
+
+2:
+	cfi_restore_state
+#ifdef __PIC__
+	PTR_LA	t9, __syscall_do_cancel
+	jalr	t9
+#else
+	jal	__syscall_do_cancel
+#endif
+
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
index cbe9cd2..5417c43 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
@@ -18,6 +18,10 @@
 #ifndef _LINUX_MIPS_MIPS32_SYSDEP_H
 #define _LINUX_MIPS_MIPS32_SYSDEP_H 1
 
+/* mips32 have cancelable syscalls with 7 arguments (currently only
+   sync_file_range).  */
+#define HAVE_CANCELABLE_SYSCALL_WITH_7_ARGS	1
+
 /* There is some commonality.  */
 #include <sysdeps/unix/sysv/linux/sysdep.h>
 #include <sysdeps/unix/mips/mips32/sysdep.h>
diff --git a/sysdeps/unix/sysv/linux/mips/sigcontextinfo.h b/sysdeps/unix/sysv/linux/mips/sigcontextinfo.h
index d183a33..7da55f5 100644
--- a/sysdeps/unix/sysv/linux/mips/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/mips/sigcontextinfo.h
@@ -16,7 +16,10 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
 
+#include <stdint.h>
 #include <sgidefs.h>
 
 #if _MIPS_SIM == _ABIO32
@@ -39,4 +42,12 @@
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
 
-#endif
+#endif /* _MIPS_SIM == _ABIO32  */
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+  return uc->uc_mcontext.pc;
+}
+
+#endif /* _SIGCONTEXTINFO_H  */
diff --git a/sysdeps/unix/sysv/linux/syscall_cancel.c b/sysdeps/unix/sysv/linux/syscall_cancel.c
index ac08bb7..5a3d383 100644
--- a/sysdeps/unix/sysv/linux/syscall_cancel.c
+++ b/sysdeps/unix/sysv/linux/syscall_cancel.c
@@ -46,14 +46,16 @@ long int
 __syscall_cancel_arch (volatile int *ch, __syscall_arg_t nr,
 		       __syscall_arg_t a1, __syscall_arg_t a2,
 		       __syscall_arg_t a3, __syscall_arg_t a4,
-		       __syscall_arg_t a5, __syscall_arg_t a6)
+		       __syscall_arg_t a5, __syscall_arg_t a6
+		       __SYSCALL_CANCEL7_ARG_DEF)
 {
   ADD_LABEL ("__syscall_cancel_arch_start");
   if (__glibc_unlikely (*ch & CANCELED_BITMASK))
     __syscall_do_cancel();
 
   INTERNAL_SYSCALL_DECL(err);
-  long int result = INTERNAL_SYSCALL_NCS (nr, err, 6, a1, a2, a3, a4, a5, a6);
+  long int result = INTERNAL_SYSCALL_NCS_CALL (nr, err, a1, a2, a3, a4, a5,
+					       a6 __SYSCALL_CANCEL7_ARG7);
   ADD_LABEL ("__syscall_cancel_arch_end");
   if (INTERNAL_SYSCALL_ERROR_P (result, err))
     return -INTERNAL_SYSCALL_ERRNO (result, err);
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 20/21] nptl: hppa: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (18 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 19/21] nptl: mips: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-26 21:03 ` [PATCH v2 21/21] nptl: riscv: " Adhemerval Zanella
  20 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the hppa modifications required for the BZ#12683.
It basically adds the required __pthread_get_pc function.

HPPA requires an arch-specific syscall_cancel because the
INTERNAL_SYSCALL_NCS adds some instruction to fetch the returned
syscalls value.  The implementation were based on on default C
version built with GCC 6.1

Checked on hppa-linux-gnu.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/hppa/sigcontextinfo.h: New file.
	* sysdeps/unix/sysv/linux/hppa/syscall_cancel.S: Likewise.
---
 ChangeLog                                     |  4 ++
 sysdeps/unix/sysv/linux/hppa/sigcontextinfo.h | 38 +++++++++++++
 sysdeps/unix/sysv/linux/hppa/syscall_cancel.S | 82 +++++++++++++++++++++++++++
 3 files changed, 124 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/hppa/sigcontextinfo.h
 create mode 100644 sysdeps/unix/sysv/linux/hppa/syscall_cancel.S

diff --git a/sysdeps/unix/sysv/linux/hppa/sigcontextinfo.h b/sysdeps/unix/sysv/linux/hppa/sigcontextinfo.h
new file mode 100644
index 0000000..4f59c1e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hppa/sigcontextinfo.h
@@ -0,0 +1,38 @@
+/* Copyright (C) 2017 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/>.  */
+
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
+
+/* In general we cannot provide any information.  */
+#define SIGCONTEXT struct sigcontext *
+#define SIGCONTEXT_EXTRA_ARGS
+#define GET_PC(ctx)	((void *) 0)
+#define GET_FRAME(ctx)	((void *) 0)
+#define GET_STACK(ctx)	((void *) 0)
+#define CALL_SIGHANDLER(handler, signo, ctx) \
+  (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+  return uc->uc_mcontext.sc_iaoq[0] & ~0x3;
+}
+
+#endif /* _SIGCONTEXTINFO_H  */
diff --git a/sysdeps/unix/sysv/linux/hppa/syscall_cancel.S b/sysdeps/unix/sysv/linux/hppa/syscall_cancel.S
new file mode 100644
index 0000000..552ba2f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hppa/syscall_cancel.S
@@ -0,0 +1,82 @@
+/* Cancellable syscall wrapper.  Linux/hppa version.
+   Copyright (C) 2017 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 __syscall_cancel_arch (int *cancelhandling,
+				   long int nr,
+				   long int arg1,
+				   long int arg2,
+				   long int arg3,
+				   long int arg4,
+				   long int arg5,
+				   long int arg6)  */
+
+	.text
+ENTRY(__syscall_cancel_arch)
+	stw	%r2,-20(%r30)
+	ldo	128(%r30),%r30
+	cfi_def_cfa_offset (-128)
+	cfi_offset (2, -20)
+	ldw	-180(%r30),%r28
+	copy	%r24,%r31
+	stw	%r28,-104(%r30)
+	ldw	-184(%r30),%r28
+	stw	%r28,-108(%r30)
+	ldw	-188(%r30),%r28
+	stw	%r28,-112(%r30)
+	ldw	-192(%r30),%r28
+	stw	%r4,-100(%r30)
+	stw	%r28,-116(%r30)
+	copy	%r25,%r28
+	copy	%r23,%r25
+	stw	%r19,-32(%r30)
+	cfi_offset (4, 28)
+
+	.global __syscall_cancel_arch_start
+.type __syscall_cancel_arch_start,@function
+__syscall_cancel_arch_start:
+
+	ldw	0(%r26),%r20
+	stw	%r20,-120(%r30)
+	ldw	-120(%r30),%r20
+	bb,<	%r20,29,1f
+	ldw	-116(%r30),%r21
+	ldw	-112(%r30),%r22
+	copy	%r31,%r26
+	ldw	-108(%r30),%r23
+	ldw	-104(%r30),%r24
+	copy	%r19, %r4
+	ble	0x100(%sr2, %r0)
+
+	.global __syscall_cancel_arch_end
+.type __syscall_cancel_arch_end,@function	
+__syscall_cancel_arch_end:
+
+	copy	%r28, %r20
+	copy	%r4, %r19
+	ldw	-148(%r30),%r2
+	ldw	-100(%r30),%r4
+	bv	%r0(%r2)
+	ldo	-128(%r30),%r30
+1:
+	bl __syscall_do_cancel,%r2
+	nop
+	nop
+END(__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 21/21] nptl: riscv: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
                   ` (19 preceding siblings ...)
  2018-02-26 21:03 ` [PATCH v2 20/21] nptl: hppa: " Adhemerval Zanella
@ 2018-02-26 21:03 ` Adhemerval Zanella
  2018-02-27  1:16   ` DJ Delorie
  20 siblings, 1 reply; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-26 21:03 UTC (permalink / raw)
  To: libc-alpha

This patch adds the riscv modifications required for the BZ#12683.
It basically adds the required ucontext_get_pc function.

The default syscall_cancel.c should be as expected for RISCV. With
GCC 7.3.1 syscall_cancel.c generates the following code:

0000000000000000 <__GI___syscall_cancel_arch>:
   0:   8346                    mv      t1,a7

0000000000000002 <__syscall_cancel_arch_start>:
   2:   00052883                lw      a7,0(a0)
   6:   0048f893                andi    a7,a7,4
   a:   00089c63                bnez    a7,22 <.L0 >
   e:   88ae                    mv      a7,a1
  10:   8532                    mv      a0,a2
  12:   85b6                    mv      a1,a3
  14:   863a                    mv      a2,a4
  16:   86be                    mv      a3,a5
  18:   8742                    mv      a4,a6
  1a:   879a                    mv      a5,t1
  1c:   00000073                ecall

0000000000000020 <__syscall_cancel_arch_end>:
  20:   8082                    ret

  22:   1141                    addi    sp,sp,-16
  24:   e406                    sd      ra,8(sp)
  26:   00000097                auipc   ra,0x0
  2a:   000080e7                jalr    ra # 26 <.L0 >

Checked with a build for riscv64-linux-gnu with run-built-tests=no.

	[BZ #12683]
	* sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h (ucontext_get_pc):
	New fuction.
---
 ChangeLog                                      |  4 ++++
 sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h | 12 ++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h b/sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h
index 3ca8a80..5a68ff8 100644
--- a/sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h
@@ -16,6 +16,10 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
 #include <sys/ucontext.h>
 
 #define SIGCONTEXT siginfo_t *_si, ucontext_t *
@@ -26,3 +30,11 @@
 
 #define CALL_SIGHANDLER(handler, signo, ctx) \
   (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+
+static inline uintptr_t
+ucontext_get_pc (const ucontext_t *uc)
+{
+  return uc->uc_mcontext.__gregs[REG_PC];
+}
+
+#endif /* _SIGCONTEXTINFO_H  */
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 01/21] powerpc: Create stackframe information on syscall
  2018-02-26 21:03 ` [PATCH v2 01/21] powerpc: Create stackframe information on syscall Adhemerval Zanella
@ 2018-02-26 21:41   ` Andreas Schwab
  2018-02-27 12:05     ` Adhemerval Zanella
  2018-05-07  2:49   ` Zack Weinberg
  1 sibling, 1 reply; 45+ messages in thread
From: Andreas Schwab @ 2018-02-26 21:41 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

On Feb 26 2018, Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote:

> diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S
> index 2da9172..fae0fe8 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/syscall.S
> +++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S
> @@ -19,6 +19,14 @@
>  
>  ENTRY (syscall)
>  	ABORT_TRANSACTION
> +	/* Creates a minimum stack frame so backtrace works.  */

s/Creates/Create/

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 02/21] nptl: Fix testcases for new pthread cancellation mechanism
  2018-02-26 21:03 ` [PATCH v2 02/21] nptl: Fix testcases for new pthread cancellation mechanism Adhemerval Zanella
@ 2018-02-26 21:43   ` Andreas Schwab
  2018-02-27 12:05     ` Adhemerval Zanella
  2018-05-07  2:49   ` Zack Weinberg
  1 sibling, 1 reply; 45+ messages in thread
From: Andreas Schwab @ 2018-02-26 21:43 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha, Adhemerval Zanella

On Feb 26 2018, Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote:

> @@ -743,6 +747,10 @@ tf_send (void *arg)
>    char mem[WRITE_BUFFER_SIZE];
>  
>    send (tempfd2, mem, arg == NULL ? sizeof (mem) : 1, 0);
> +  /* Thez send can return a value higher than 0 (meaning partial send)

s/Thez/The/

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 21/21] nptl: riscv: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 ` [PATCH v2 21/21] nptl: riscv: " Adhemerval Zanella
@ 2018-02-27  1:16   ` DJ Delorie
  2018-02-27 13:03     ` Adhemerval Zanella
  0 siblings, 1 reply; 45+ messages in thread
From: DJ Delorie @ 2018-02-27  1:16 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
> +static inline uintptr_t
> +ucontext_get_pc (const ucontext_t *uc)
> +{
> +  return uc->uc_mcontext.__gregs[REG_PC];
> +}

That file already has a GET_PC() macro; why not use it?
(I mean, in the definition of this function)


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 01/21] powerpc: Create stackframe information on syscall
  2018-02-26 21:41   ` Andreas Schwab
@ 2018-02-27 12:05     ` Adhemerval Zanella
  0 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-27 12:05 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: libc-alpha



On 26/02/2018 18:41, Andreas Schwab wrote:
> On Feb 26 2018, Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote:
> 
>> diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S
>> index 2da9172..fae0fe8 100644
>> --- a/sysdeps/unix/sysv/linux/powerpc/syscall.S
>> +++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S
>> @@ -19,6 +19,14 @@
>>  
>>  ENTRY (syscall)
>>  	ABORT_TRANSACTION
>> +	/* Creates a minimum stack frame so backtrace works.  */
> 
> s/Creates/Create/
> 
> Andreas.
> 

Ack, fixed locally.


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 02/21] nptl: Fix testcases for new pthread cancellation mechanism
  2018-02-26 21:43   ` Andreas Schwab
@ 2018-02-27 12:05     ` Adhemerval Zanella
  0 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-27 12:05 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: libc-alpha, Adhemerval Zanella



On 26/02/2018 18:43, Andreas Schwab wrote:
> On Feb 26 2018, Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote:
> 
>> @@ -743,6 +747,10 @@ tf_send (void *arg)
>>    char mem[WRITE_BUFFER_SIZE];
>>  
>>    send (tempfd2, mem, arg == NULL ? sizeof (mem) : 1, 0);
>> +  /* Thez send can return a value higher than 0 (meaning partial send)
> 
> s/Thez/The/
> 
> Andreas.
> 

Ack, fixed locally.


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 21/21] nptl: riscv: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-27  1:16   ` DJ Delorie
@ 2018-02-27 13:03     ` Adhemerval Zanella
  0 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-02-27 13:03 UTC (permalink / raw)
  To: DJ Delorie; +Cc: libc-alpha



On 26/02/2018 22:16, DJ Delorie wrote:
> Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
>> +static inline uintptr_t
>> +ucontext_get_pc (const ucontext_t *uc)
>> +{
>> +  return uc->uc_mcontext.__gregs[REG_PC];
>> +}
> 
> That file already has a GET_PC() macro; why not use it?
> (I mean, in the definition of this function)
> 

I used just to avoid the extra cast (long int -> void -> uintptr_t).
I do not have a strong preference here in fact.


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 03/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 ` [PATCH v2 03/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
@ 2018-04-27 12:20   ` Zack Weinberg
  2018-04-27 12:25     ` Adhemerval Zanella
  2018-05-07  2:49   ` Zack Weinberg
  1 sibling, 1 reply; 45+ messages in thread
From: Zack Weinberg @ 2018-04-27 12:20 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library

On Mon, Feb 26, 2018 at 4:03 PM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> This patches fixes some race conditions in NPTL cancellation code by
> redefining how cancellable syscalls are defined and handled.  Current
> approach is to enable asynchronous cancellation prior to making the syscall
> and restore the previous cancellation type once the syscall returns.

Did these patches ever get reviewed/committed?  #12683 has been
festering for a long time...

zw


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 03/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-04-27 12:20   ` Zack Weinberg
@ 2018-04-27 12:25     ` Adhemerval Zanella
  2018-05-07  2:48       ` Zack Weinberg
  0 siblings, 1 reply; 45+ messages in thread
From: Adhemerval Zanella @ 2018-04-27 12:25 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: GNU C Library



On 27/04/2018 09:20, Zack Weinberg wrote:
> On Mon, Feb 26, 2018 at 4:03 PM, Adhemerval Zanella
> <adhemerval.zanella@linaro.org> wrote:
>> This patches fixes some race conditions in NPTL cancellation code by
>> redefining how cancellable syscalls are defined and handled.  Current
>> approach is to enable asynchronous cancellation prior to making the syscall
>> and restore the previous cancellation type once the syscall returns.
> 
> Did these patches ever get reviewed/committed?  #12683 has been
> festering for a long time...
> 
> zw
> 

Thanks for bring this up. No, I haven't received any review so far about it.


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 03/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-04-27 12:25     ` Adhemerval Zanella
@ 2018-05-07  2:48       ` Zack Weinberg
  0 siblings, 0 replies; 45+ messages in thread
From: Zack Weinberg @ 2018-05-07  2:48 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library

On Fri, Apr 27, 2018 at 8:25 AM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> On 27/04/2018 09:20, Zack Weinberg wrote:
>> On Mon, Feb 26, 2018 at 4:03 PM, Adhemerval Zanella
>> <adhemerval.zanella@linaro.org> wrote:
>>> This patches fixes some race conditions in NPTL cancellation code by
>>> redefining how cancellable syscalls are defined and handled.  Current
>>> approach is to enable asynchronous cancellation prior to making the syscall
>>> and restore the previous cancellation type once the syscall returns.
>>
>> Did these patches ever get reviewed/committed?  #12683 has been
>> festering for a long time...
>
> Thanks for bring this up. No, I haven't received any review so far about it.

Let's try to unjam this.  I will post reviews for patches 1, 2, 3, 4,
and 6 shortly.  Unfortunately, all of the other patches require review
by architecture experts; I don't know enough about the low-level ABI
details for anything other than plain x86-32 and -64.

zw

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 01/21] powerpc: Create stackframe information on syscall
  2018-02-26 21:03 ` [PATCH v2 01/21] powerpc: Create stackframe information on syscall Adhemerval Zanella
  2018-02-26 21:41   ` Andreas Schwab
@ 2018-05-07  2:49   ` Zack Weinberg
  2018-05-07 13:57     ` Adhemerval Zanella
  1 sibling, 1 reply; 45+ messages in thread
From: Zack Weinberg @ 2018-05-07  2:49 UTC (permalink / raw)
  To: libc-alpha; +Cc: adhemerval.zanella

On 26 Feb 2018, Adhemerval Zanella wrote:
> This patch adds a minimal stackframe creation on powerpc syscall
> implementation so backtrace works correctly on a signal handler.

I don't know powerpc well enough to know if this should be necessary.
I think one of the powerpc arch maintainers should comment.  I do have
a couple questions:

> +#ifdef __powerpc64__
> +	stdu r1, -FRAME_MIN_SIZE (r1)
> +	cfi_adjust_cfa_offset (FRAME_MIN_SIZE)
> +#else
> +	stwu r1,-16(1)
> +	cfi_def_cfa_offset (16)
> +#endif

Why does this use cfa_adjust_cfa_offset for 64-bit but _def_ for 32-bit?

> +#ifdef __powerpc64__
> +	addi r1, r1, FRAME_MIN_SIZE
> +#else
> +	addi r1,r1,16
> +#endif

If FRAME_MIN_SIZE were defined for ppc32, we could reduce the
ifdeffage here.

> +	cfi_def_cfa_offset (0)
>       sc
>       PSEUDO_RET

Shouldn't the stack adjustments be undone _after_ the 'sc'
instruction?  Actually, is it possible that a single
cfi_def_cfa_offset (0) at the beginning of the function is all that's
really needed here?  It seems like backtrace should be able to handle
leaf frames in general...

zw

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 02/21] nptl: Fix testcases for new pthread cancellation mechanism
  2018-02-26 21:03 ` [PATCH v2 02/21] nptl: Fix testcases for new pthread cancellation mechanism Adhemerval Zanella
  2018-02-26 21:43   ` Andreas Schwab
@ 2018-05-07  2:49   ` Zack Weinberg
  2018-05-07 17:13     ` Adhemerval Zanella
  1 sibling, 1 reply; 45+ messages in thread
From: Zack Weinberg @ 2018-05-07  2:49 UTC (permalink / raw)
  To: libc-alpha; +Cc: adhemerval.zanella

On 26 Feb 2018, Adhemerval Zanella wrote:
> With upcoming fix for BZ#12683, pthread cancellation does not act for:
>
>   1. If syscall is blocked but with some side effects already having
>      taken place (e.g. a partial read or write).
>   2. After the syscall has returned.
>
> The main change is due the fact programs need to act in syscalls with
> side-effects (for instance, to avoid leak of allocated resources or
> handle partial read/write).
>
> This patch changes the NPTL testcase that assumes the old behavior and
> also remove the tst-cancel-wrappers.sh test (which checks for symbols
> that will not exist anymore).

It's OK and expected that we have to adjust test cases that were
expecting the old behavior ...

> For tst-cancel{2,3} case it remove the pipe close because it might
> cause the write syscall to return with side effects if the close is
> executed before the pthread cancel.

... however, this change appears to be wrong.  If cancellation is
broken, these tests will now deadlock rather than failing cleanly.

If I understand correctly, the problem you're trying to avoid is that
the 'tf' thread could conceivably receive the closed-pipe event before
the cancellation signal, even though the 'do_test' thread triggers the
cancellation signal first.  I don't know of any way to fix this 100%,
but I think it would be good enough to use pthread_timedjoin_np to
sleep for a hundred milliseconds or so in the 'do_test' thread, and
then close the pipe if the 'tf' thread is still alive.

(tst-cancel4.c appears to be trying to ensure that cancellations are
pending with a pthread_barrier_t, but as far as I know there's no
guarantee that if a thread does

   pthread_cancel(th);
   pthread_barrier_wait(ba);

where 'th' also waits on 'ba', the SIGCANCEL will actually be
delivered before the barrier unblocks, either.  Feh.)

> It also changes how to call the read syscall on tst-backtrace{5,6}
> to use syscall instead of read cancelable syscall to avoid need to
> handle the cancelable bridge function calls.  It requires a change
> on powerpc syscall implementation to create a stackframe, since
> powerpc backtrace rely on such information.

It doesn't look technically difficult to me to handle an additional
stack frame or two in the trace.  They're always going to be there,
aren't they?  In the new world order, the stack trace will always be

 0  handle_signal
 1  <signal trampoline>
 2  __syscall_cancel_arch
 3  __syscall_cancel
 4  read
 5  fn
 6  fn
 7  fn
 8  do_test

won't it?  I think teaching the backtrace logic about this would be
better than needing to use a raw syscall() and then mess with the
PowerPC implementation of syscall().  I might feel differently about
this change if __read_nocancel were a public API, but it isn't...

> Checked on i686-linux-gnu, x86_64-linux-gnu, x86_64-linux-gnux32,
> aarch64-linux-gnu, arm-linux-gnueabihf, powerpc64le-linux-gnu,
> powerpc-linux-gnu, sparcv9-linux-gnu, and sparc64-linux-gnu.

When you say checked, do you mean you actually ran the test cases, or
did you just compile them (perhaps with a cross-compiler)?

>       * nptl/Makefile [$(run-built-tests) = yes] (tests-special): Remove
>       tst-cancel-wrappers.sh.
>       * nptl/tst-cancel-wrappers.sh: Remove file.

This part is OK.

>       * nptl/tst-cancel4.c (tf_write): Handle cancelled syscall with
>       side-effects.
>       (tf_send): Likewise.

This part is also OK.  I think the test can still fail spuriously due
to races, but this one can't deadlock, at least, so we can live with it.

>       * sysdeps/unix/sysv/linux/powerpc/syscall.S (syscall): Create stack
>       frame.

This ChangeLog entry belongs to patch 1.

zw

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 03/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 ` [PATCH v2 03/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
  2018-04-27 12:20   ` Zack Weinberg
@ 2018-05-07  2:49   ` Zack Weinberg
  2018-05-08 17:11     ` Adhemerval Zanella
  1 sibling, 1 reply; 45+ messages in thread
From: Zack Weinberg @ 2018-05-07  2:49 UTC (permalink / raw)
  To: libc-alpha; +Cc: adhemerval.zanella

On 26 Feb 2018, Adhemerval Zanella wrote:
> This patches fixes some race conditions in NPTL cancellation code by
> redefining how cancellable syscalls are defined and handled.  Current
> approach is to enable asynchronous cancellation prior to making the syscall
> and restore the previous cancellation type once the syscall returns.
>
> As decribed in BZ#12683, this approach shows 2 important problems:
>
>   1. Cancellation can act after the syscall has returned from kernel, but
>      before userspace saves the return value.  It might result in a resource
>      leak if the syscall allocated a resource or a side effect (partial
>      read/write), and there is no way to program handle it with cancellation
>      handlers.
>
>   2. If a signal is handled while the thread is blocked at a cancellable
>      syscall, the entire signal handler runs with asynchronous cancellation
>      enabled.  This can lead to issues if the signal handler call functions
>      which are async-signal-safe but not async-cancel-safe.
>
> For cancellation to work correctly, there are 5 points at which the
> cancellation signal could arrive:
>
>   1. Before the final "testcancel" and before the syscall is made.
>   2. Between the "testcancel" and the syscall.
>   3. While the syscall is blocked and no side effects have yet taken place.
>   4. While the syscall is blocked but with some side effects already having
>      taken place (e.g. a partial read or write).
>   5. After the syscall has returned.
>
> And GLIBC wants to act on cancellation in cases 1, 2, and 3 but not in case
> 4 or 5.  The proposed solution follows:
>
>   * Handling case 1 is trivial: do a conditional branch based on whether the
>     thread has received a cancellation request;
>   * Case 2 can be caught by the signal handler determining that the saved
>     program counter (from the ucontext_t) is in some address range beginning
>     just before the "testcancel" and ending with the syscall instruction.
>   * In this case, except for certain syscalls that ALWAYS fail with EINTR
>     even for non-interrupting signals, the kernel will reset the program
>     counter to point at the syscall instruction during signal handling, so
>     that the syscall is restarted when the signal handler returns. So, from
>     the signal handler's standpoint, this looks the same as case 2, and thus
>     it's taken care of.
>   * In this case, the kernel cannot restart the syscall; when it's
>     interrupted by a signal, the kernel must cause the syscall to return
>     with whatever partial result it obtained (e.g. partial read or write).
>   * In this case, the saved program counter points just after the syscall
>     instruction, so the signal handler won't act on cancellation.
>     This one is equal to 4. since the program counter is past the syscall
>     instruction already.

To be 100% clear here, you are fixing important problem #1 by having
deferred cancellation _not_ trigger in cases 4 and 5, because the
signal handler observes that the PC is past the syscall instruction?

> Another case that needs handling is syscalls that fail with EINTR even
> when the signal handler is non-interrupting. In this case, the syscall
> wrapper code can just check the cancellation flag when the errno result
> is EINTR, and act on cancellation if it's set.

Which system calls are affected by this rule, and is it actually
correct to have cancellation trigger when they fail with EINTR?  Can
we be certain that the EINTR was due to the cancellation signal rather
than some other signal delivered first?  (At least for sigsuspend it
is possible to have two signals be delivered simultaneously, if they
were both blocked and pending, and both become unblocked due to the
sigsuspend.  The kernel pushes two signal stack frames.  It would
reduce the odds of this being a problem if the SIGCANCEL handler
masked all other signals while running, but I'm not sure that will
work with it jumping directly to __pthread_unwind under some
conditions, and also I don't think it _completely_ eliminates the
possibility; a second signal could be delivered right after sigreturn
unmasks it, without returning to the caller of the syscall stub first.)

>   1. Remove the enable_asynccancel/disable_asynccancel function usage in
>      syscall definition and instead make them call a common symbol that will
>      check if cancellation is enabled (__syscall_cancel at
>      nptl/libc-cancellation.c), call the arch-specific cancellable
>      entry-point (__syscall_cancel_arch) and cancel the thread when required.
>
>   2. Provide a arch-specific symbol that contains global markers. These
>      markers will be used in SIGCANCEL handler to check if the interruption
>      has been called in a valid syscall and if the syscalls has been
>      completed or not.
>      A default version is provided (sysdeps/unix/sysv/linux/syscall_cancel.c),
>      however the markers may not be set on correct expected places depeding
>      of how INTERNAL_SYSCALL_NCS is implemented by the underlying architecture.
>      In this case arch-specific implementation should be provided.
>
>   3. Rewrite SIGCANCEL asynchronous handler to check for both cancelling type
>      and if current IP from signal handler falls between the global markes
>      and act accordingly (sigcancel_handler at nptl/nptl-init.c).
>
>   4. Adjust nptl/pthread_cancel.c to send an signal instead of acting
>      directly. This avoid synchronization issues when updating the
>      cancellation status and also focus the logic on signal handler and
>      cancellation syscall code.
>
>   5. Adjust pthread code to replace CANCEL_ASYNC/CANCEL_RESET calls to
>      appropriated cancelable futex syscalls.
>
>   6. Adjust libc code to replace LIBC_CANCEL_ASYNC/LIBC_CANCEL_RESET to
>      appropriated cancelable syscalls.
>
>   7. Adjust 'lowlevellock-futex.h' arch-specific implementations to provide
>      cancelable futex calls (used in libpthread code).

The overall design seems sound to me.

> This patch adds the proposed changes to NPTL.  The code leaves all the ports
> broken without further patches in the list.

Can we find an ordering of the patches in which the tree is never
broken at an intermediate stage?  Perhaps you could introduce the generic
__syscall_cancel(_arch) first, but not change any of the existing
cancellation logic until after all of the port-specific code was in
place?

Below, all the changes which I erased and didn't comment on seem OK to
me.  I am generally pleased to see many system call wrappers get
simpler in the process of fixing this bug.

> --- a/io/creat.c
> +++ b/io/creat.c
...
> -
> -/* __open handles cancellation.  */
> -LIBC_CANCEL_HANDLED ();

It might be clearer to split patch 2 into two patches, one to remove
tst-cancel-wrappers.sh and one to make all the other testing changes,
and then shift all of the removals of LIBC_CANCEL_HANDLED into the
same patch that removes tst-cancel-wrappers.sh.

> --- a/nptl/descr.h
> +++ b/nptl/descr.h
...
> +  /* Bit set if threads is canceled.  */

Grammar: "Bit set if thread is canceled."

(For 100% proper English, it would be "This bit is set if this thread
has been cancelled", but all of the other comments are clipped as
well, so the above is fine.)

> --- a/nptl/libc-cancellation.c
> +++ b/nptl/libc-cancellation.c
...
> +#include <setjmp.h>
> +#include <stdlib.h>

Why are these additional #includes necessary?

...
> +  volatile struct pthread *pd = (volatile struct pthread *) self;

Why is it necessary for this pointer to be volatile?  It appears that
we only ever access pd->cancelhandling; which loads need to be
forced to go to memory, and should they also be atomic?

> +  /* If cancellation is not enabled, call the syscall directly.  */
> +  if (pd->cancelhandling & CANCELSTATE_BITMASK)

It is unfortunate that the one-bit flag that means "cancellation is
disabled" is named CANCELSTATE_BITMASK instead of, I dunno,
CANCEL_DISABLED_BITMASK maybe.  You didn't introduce that, but please
consider a follow-up patch that renames CANCELSTATE_BIT(MASK) and also
CANCELTYPE_BIT(MASK) [the latter to "CANCEL_ASYNC_BIT(MASK)" perhaps].

> +  if ((result == -EINTR)
> +      && (pd->cancelhandling & CANCELED_BITMASK)
> +      && !(pd->cancelhandling & CANCELSTATE_BITMASK))
> +    __syscall_do_cancel ();

I thought you said this treatment was only applied to system calls
that _always_ fail with EINTR, even when interrupted by SA_RESTART
signals.  This is doing it for system calls interrupted by
non-SA_RESTART signals as well.  You also change SIGCANCEL to be a
SA_RESTART signal in this patch, but it still could happen that we
have SIGCANCEL and some other non-SA_RESTART signal arrive
simultaneously enough that they interrupt the same system call, and
then it fails with EINTR and everything is confused.

I think you need to check over the entire design with "what if
SIGCANCEL and some other signal are delivered as nested interruptions
to the same system call" in mind, in fact.  The dangerous case that I
see is when the _other_ signal causes the system call to be
interrupted after producing some side effects.  Can the SIGCANCEL
handler know that this has happened or is about to happen?

> --- a/nptl/nptl-init.c
> +++ b/nptl/nptl-init.c
>  sigcancel_handler (int sig, siginfo_t *si, void *ctx)
>  {
> +  INTERNAL_SYSCALL_DECL (err);
> +  pid_t pid = INTERNAL_SYSCALL_CALL (getpid, err);
> +
>    /* Safety check.  It would be possible to call this function for
>       other signals and send a signal from another process.  This is not
>       correct and might even be a security problem.  Try to catch as
>       many incorrect invocations as possible.  */
>    if (sig != SIGCANCEL
> -      || si->si_pid != __getpid()
> +      || si->si_pid != pid
>        || si->si_code != SI_TKILL)

Why is this change necessary?

> +  volatile struct pthread *pd = (volatile struct pthread *) self;

Same question as above: why does this need to be volatile, does it
actually do the job, should we instead be using atomics?

> +  /* Add SIGCANCEL on ignored sigmask to avoid the handler to be called
> +     again.  */
> +  sigset_t *set = UCONTEXT_SIGMASK (ctx);
> +  __sigaddset (set, SIGCANCEL);

Screwing with the signal mask that will be restored by sigreturn seems
unsafe.  Could we instead return early if CANCELED_BITMASK and/or
EXITING_BITMASK has already been set?

> +  /* Check if asynchronous cancellation mode is set and if interrupted
                                                       ^^^
This 'and' should be 'or'.

> +      THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
> +      THREAD_SETMEM (self, result, PTHREAD_CANCELED);

I think these ought to be done inside __do_cancel, since several other
places may call __do_cancel.

> +      INTERNAL_SYSCALL_CALL (rt_sigprocmask, err, SIG_SETMASK, set, NULL,
> +                          _NSIG / 8);

See above in re screwing with the signal mask.

> +      __do_cancel ();
> +      return;
>      }
>  }

This 'return' should be unnecessary on two counts: we're about to fall
off the end of the function anyway, and __do_cancel ends by calling
__pthread_unwind which does not return.

--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
...
> -  /* Make sure we get no more cancellations.  */
> -  THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
> +  /* Make sure we get no more cancellations by clearing the cancel
> +     state.  */
> +  int oldval = THREAD_GETMEM (self, cancelhandling);
> +  while (1)
> +    {
> +      int newval = (oldval | CANCELSTATE_BITMASK);
> +      newval &= ~(CANCELTYPE_BITMASK);

Disabled cancellation state is specified to take precedence over
asynchronous cancellation type, so it should be enough to atomically
set CANCELSTATE_BIT, at which point the CAS loop would be unnecessary.

> --- a/nptl/pthread_cancel.c
> +++ b/nptl/pthread_cancel.c
...
> +  /* Avoid signaling when thread attempts cancel itself (pthread_kill
> +     is expensive).  */
> +  if (pd == THREAD_SELF && !(pd->cancelhandling & CANCELTYPE_BITMASK))
> +    return 0;

It is not obvious why this is correct.  The answer is that
pthread_cancel is not itself a cancellation point, so, when
cancellation is deferred, a self-cancel is _not_ supposed to take
effect immediately; the signal handler would have no effect, and the
next cancellation point will check the flag anyway.  I suggest instead

    if (pd == THREAD_SELF)
      {
         if (pd->cancelhandling & CANCELTYPE_BITMASK)
           __do_cancel ();
         /* pthread_cancel is not itself a cancellation point;
            the next cancellation point will check the flag anyway,
            so there is no need to send the cancellation signal.  */
        return 0;
     }
     return __pthread_kill (th, SIGCANCEL);

> --- a/nptl/pthread_create.c
> +++ b/nptl/pthread_create.c
...
>    /* If the parent was running cancellation handlers while creating
>       the thread the new thread inherited the signal mask.  Reset the
>       cancellation signal mask.  */

If the cancellation handler exited early when EXITING_BIT was set, and
it didn't mess with the signal mask, we wouldn't need to do this, either.

> -       int oldtype = CANCEL_ASYNC ();
> +       int ct;
> +       __pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &ct);

I don't understand the logic in this part of the code at all so I am
going to trust you that this is the correct change.  It seems like
it's using SIGCANCEL for something other than cancellation, which
seems unwise and maybe should be changed in a follow-up.

> --- a/nptl/pthread_join_common.c
> +++ b/nptl/pthread_join_common.c
...
> -      int oldtype = CANCEL_ASYNC ();
> +      int ct;
> +      __pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &ct);
>
>        if (abstime != NULL)
>       result = lll_timedwait_tid (pd->tid, abstime);
>        else
>       lll_wait_tid (pd->tid);
>
> -      CANCEL_RESET (oldtype);
> +      __pthread_setcanceltype (ct, NULL);

Maybe we should have lll_(timed)wait_tid_cancel rather than this?

> --- a/sysdeps/unix/sysdep.h
> +++ b/sysdeps/unix/sysdep.h
...
> +/* The loader does not need to handle thread cancellation, use direct
> +   syscall instead.  */

A stronger assertion would be better:

/* The loader should never make cancellable system calls.  Remap them
   to direct system calls.  */

Also, is this hack still necessary after I went through and made the
loader explicitly use _nocancel operations?

> --- a/sysdeps/unix/sysv/linux/pthread_kill.c
> +++ b/sysdeps/unix/sysv/linux/pthread_kill.c
...
> -  /* Disallow sending the signal we use for cancellation, timers,
> -     for the setxid implementation.  */
> -  if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID)
> +  /* Disallow sending the signal we use for setxid implementation.  */
> +  if (signo == SIGSETXID)
>      return EINVAL;

Now applications can call pthread_kill(thr, SIGCANCEL) themselves,
can't they?  That seems unsafe.  Also this has since been changed to
use __is_internal_signal, I think.  We need an __internal_pthread_kill
or something.

> --- a/sysdeps/unix/sysv/linux/socketcall.h
> +++ b/sysdeps/unix/sysv/linux/socketcall.h
...
> +#define __SOCKETCALL_CANCEL1(__name, __a1) \
> +  SYSCALL_CANCEL_NCS (socketcall, __name, \
> +     ((long int [1]) { (long int) __a1 }))

Blech, which architectures still require us to use socketcall?

> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/syscall_cancel.c
...
> +#define ADD_LABEL(__label)		\
> +  asm volatile (			\
> +    ".global " __label "\t\n"		\
> +    ".type " __label ",\%function\t\n"       \
> +    __label ":\n");

This makes me extremely nervous.  Specifically, I do not trust the
compiler to not move these around, even though they're volatile.  I
would actually prefer an .S file for every architecture.

Do we have a concrete reason to believe they really will always be
where they're supposed to be?  "It compiled fine with the compiler I
have right now" is not enough, I'm afraid.

> --- a/sysdeps/unix/sysv/linux/sysdep.h
> +++ b/sysdeps/unix/sysv/linux/sysdep.h
...
> +/* Check error from cancellable syscall and set errno accordingly.
> +   Linux uses a negative return value to indicate syscall errors
> +   and since version 2.1 the return value of a system call might be
> +   negative even if the call succeeded (e.g., the `lseek' system call
> +   might return a large offset).
> +   Current contract is kernel make sure the no syscall returns a value
> +   in -1 .. -4095 as a valid result so we can savely test with -4095.  */
> +#define SYSCALL_CANCEL_RET(__ret)		\
> +  ({						\
> +    if (__ret > -4096UL)			\
> +      {						\
> +	__set_errno (-__ret);			\
> +	__ret = -1;				\
> +      }						\
> +    __ret;					\
> +   })

Don't we already have this somewhere under another name?

zw

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 04/21] nptl: x86_64: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 ` [PATCH v2 04/21] nptl: x86_64: " Adhemerval Zanella
@ 2018-05-07  2:49   ` Zack Weinberg
  2018-05-08 17:55     ` Adhemerval Zanella
  0 siblings, 1 reply; 45+ messages in thread
From: Zack Weinberg @ 2018-05-07  2:49 UTC (permalink / raw)
  To: libc-alpha; +Cc: adhemerval.zanella

On 26 Feb 2018, Adhemerval Zanella wrote:
> This patches adds the x86_64 modification required for the BZ#12683.
> It basically provide the required ucontext_get_pc symbol and remove
> the arch-specific libc-cancellation implementations.

These changes all look fine to me.

>   lock;orl $4, %fs:776
>
> Where with patch changes it now compiles to:
>
>   mov %fs:16,%rax
>   lock;orl $4, 776(%rax)

That might actually be faster on some microarchitectures due to not
having multiple unusual prefixes on one instruction.  I wouldn't worry
about it.

> In fact all x86_64 THREAD_ATOMIC_* macros
> do not respect the input descr and possible will fail when used with
> a 'descr' difference than THREAD_SELF.

Maybe we should correct or remove all of them, then?  They sound like
they're bugs waiting to happen.

zw

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 06/21] nptl: i386: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 ` [PATCH v2 06/21] nptl: i386: " Adhemerval Zanella
@ 2018-05-07  2:49   ` Zack Weinberg
  2018-05-08 17:56     ` Adhemerval Zanella
  0 siblings, 1 reply; 45+ messages in thread
From: Zack Weinberg @ 2018-05-07  2:49 UTC (permalink / raw)
  To: libc-alpha; +Cc: adhemerval.zanella

On 26 Feb 2018, Adhemerval Zanella wrote:
> This patch adds the i386 modifications required for the BZ#12683.
> It basically provides the required ucontext_get_pc symbol, add the
> cancelable syscall wrapper and fix a thread atomic update macro.

This also seems fine.

> On i386 an arch-specific cancellation implementation is required
> because depending of the glibc configuration and underlying kernel
> the syscall may be done using a vDSO symbol (__kernel_vsyscall).
...
> Also, since glibc supports i486, the old 'int 0x80' should be used
> in the syscall wrapper.  One option could make minimum default chip
> to pentium II (which implements sysenter) or add a runtime check
> on syscall_cancel.S to use 'int 0x80' or sysenter.

If I remember correctly, there can be only one 'sysenter' instruction
in the entire user address space, due to awkward limitations of the
interface it presents to the kernel.  That was why __kernel_vsyscall
was added in the first place.

We can probably live with using int 0x80 for these syscalls that may
well be blocking anyway.

> Similar to x86_64, it also remove bogus arch-specific
> THREAD_ATOMIC_BIT_SET where it always reference to current thread
> instead of the one referenced by input 'descr' argument.

Same comment as for x86_64 -- shouldn't we get rid of or repair _all_ of
the THREAD_ATOMIC_ macros that don't honor their arguments?

zw

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 01/21] powerpc: Create stackframe information on syscall
  2018-05-07  2:49   ` Zack Weinberg
@ 2018-05-07 13:57     ` Adhemerval Zanella
  0 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-05-07 13:57 UTC (permalink / raw)
  To: Zack Weinberg, libc-alpha



On 06/05/2018 23:49, Zack Weinberg wrote:
> On 26 Feb 2018, Adhemerval Zanella wrote:
>> This patch adds a minimal stackframe creation on powerpc syscall
>> implementation so backtrace works correctly on a signal handler.
> 
> I don't know powerpc well enough to know if this should be necessary.
> I think one of the powerpc arch maintainers should comment.  I do have
> a couple questions:
> 
>> +#ifdef __powerpc64__
>> +	stdu r1, -FRAME_MIN_SIZE (r1)
>> +	cfi_adjust_cfa_offset (FRAME_MIN_SIZE)
>> +#else
>> +	stwu r1,-16(1)
>> +	cfi_def_cfa_offset (16)
>> +#endif
> 
> Why does this use cfa_adjust_cfa_offset for 64-bit but _def_ for 32-bit?

I am not well versed in CFI definition, so I was basically followed what
compiler is spilling in a usual function call back when I coded it.

> 
>> +#ifdef __powerpc64__
>> +	addi r1, r1, FRAME_MIN_SIZE
>> +#else
>> +	addi r1,r1,16
>> +#endif
> 
> If FRAME_MIN_SIZE were defined for ppc32, we could reduce the
> ifdeffage here.
> 
>> +	cfi_def_cfa_offset (0)
>>       sc
>>       PSEUDO_RET
> 
> Shouldn't the stack adjustments be undone _after_ the 'sc'
> instruction?  Actually, is it possible that a single
> cfi_def_cfa_offset (0) at the beginning of the function is all that's
> really needed here?  It seems like backtrace should be able to handle
> leaf frames in general...

Indeed the single 'cfi_def_cfa_offset (0)' is suffice, I will change the
patch accordingly in next iteration.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 02/21] nptl: Fix testcases for new pthread cancellation mechanism
  2018-05-07  2:49   ` Zack Weinberg
@ 2018-05-07 17:13     ` Adhemerval Zanella
  2018-05-08 13:35       ` Zack Weinberg
  0 siblings, 1 reply; 45+ messages in thread
From: Adhemerval Zanella @ 2018-05-07 17:13 UTC (permalink / raw)
  To: Zack Weinberg, libc-alpha



On 06/05/2018 23:49, Zack Weinberg wrote:
> On 26 Feb 2018, Adhemerval Zanella wrote:
>> With upcoming fix for BZ#12683, pthread cancellation does not act for:
>>
>>   1. If syscall is blocked but with some side effects already having
>>      taken place (e.g. a partial read or write).
>>   2. After the syscall has returned.
>>
>> The main change is due the fact programs need to act in syscalls with
>> side-effects (for instance, to avoid leak of allocated resources or
>> handle partial read/write).
>>
>> This patch changes the NPTL testcase that assumes the old behavior and
>> also remove the tst-cancel-wrappers.sh test (which checks for symbols
>> that will not exist anymore).
> 
> It's OK and expected that we have to adjust test cases that were
> expecting the old behavior ...
> 
>> For tst-cancel{2,3} case it remove the pipe close because it might
>> cause the write syscall to return with side effects if the close is
>> executed before the pthread cancel.
> 
> ... however, this change appears to be wrong.  If cancellation is
> broken, these tests will now deadlock rather than failing cleanly.

On current cancellation implementation the thread will finish regardless
and sigcancel_handler will act whether there is side-effects or not
(the pipe close). The issue is cancellation should not happen if syscall
returns but some side effects already took place, in this case the pipe
close.

> 
> If I understand correctly, the problem you're trying to avoid is that
> the 'tf' thread could conceivably receive the closed-pipe event before
> the cancellation signal, even though the 'do_test' thread triggers the
> cancellation signal first.  I don't know of any way to fix this 100%,
> but I think it would be good enough to use pthread_timedjoin_np to
> sleep for a hundred milliseconds or so in the 'do_test' thread, and
> then close the pipe if the 'tf' thread is still alive.

Yes, although for this specific case I am not sure if this could happen
in practice.  I assume if a thread issues a 'signal' followed by a 'close', 
the signal target thread will receive the events in a ordered manner, i.e, 
the signal handler will be activated before the syscall sees any 
side-effects (the close).  It seems to be Linux behaviour, but I am not
sure if a different system might act differently.

And I try to avoid the timing check, such as pthread_timedjoin_np,
because they tend to quite fragile in practice for such cases (due either 
to system load when testing glibc, machine performance, etc.).

I will remove the close removal changes in next iteration.

> 
> (tst-cancel4.c appears to be trying to ensure that cancellations are
> pending with a pthread_barrier_t, but as far as I know there's no
> guarantee that if a thread does
> 
>    pthread_cancel(th);
>    pthread_barrier_wait(ba);
> 
> where 'th' also waits on 'ba', the SIGCANCEL will actually be
> delivered before the barrier unblocks, either.  Feh.)
> 
>> It also changes how to call the read syscall on tst-backtrace{5,6}
>> to use syscall instead of read cancelable syscall to avoid need to
>> handle the cancelable bridge function calls.  It requires a change
>> on powerpc syscall implementation to create a stackframe, since
>> powerpc backtrace rely on such information.
> 
> It doesn't look technically difficult to me to handle an additional
> stack frame or two in the trace.  They're always going to be there,
> aren't they?  In the new world order, the stack trace will always be
> 
>  0  handle_signal
>  1  <signal trampoline>
>  2  __syscall_cancel_arch
>  3  __syscall_cancel
>  4  read
>  5  fn
>  6  fn
>  7  fn
>  8  do_test
> 
> won't it?  I think teaching the backtrace logic about this would be
> better than needing to use a raw syscall() and then mess with the
> PowerPC implementation of syscall().  I might feel differently about
> this change if __read_nocancel were a public API, but it isn't...

With your current suggestion to powerpc syscall bits, there is no need
to actually change the powerpc syscall implementation besides an
additional CFI mechanism.  But I do not mind to change the testcase on
the bz12683 fix itself, the only advantage I see is by using indirect
syscall there is no need to actually change it again.

> 
>> Checked on i686-linux-gnu, x86_64-linux-gnu, x86_64-linux-gnux32,
>> aarch64-linux-gnu, arm-linux-gnueabihf, powerpc64le-linux-gnu,
>> powerpc-linux-gnu, sparcv9-linux-gnu, and sparc64-linux-gnu.
> 
> When you say checked, do you mean you actually ran the test cases, or
> did you just compile them (perhaps with a cross-compiler)?

It is a full make check on native machines.

> 
>>       * nptl/Makefile [$(run-built-tests) = yes] (tests-special): Remove
>>       tst-cancel-wrappers.sh.
>>       * nptl/tst-cancel-wrappers.sh: Remove file.
> 
> This part is OK.
> 
>>       * nptl/tst-cancel4.c (tf_write): Handle cancelled syscall with
>>       side-effects.
>>       (tf_send): Likewise.
> 
> This part is also OK.  I think the test can still fail spuriously due
> to races, but this one can't deadlock, at least, so we can live with it.
> 
>>       * sysdeps/unix/sysv/linux/powerpc/syscall.S (syscall): Create stack
>>       frame.
> 
> This ChangeLog entry belongs to patch 1.

Ack. I will remove it.

> 
> zw
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 07/21] nptl: powerpc: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-02-26 21:03 ` [PATCH v2 07/21] nptl: powerpc: " Adhemerval Zanella
@ 2018-05-07 19:25   ` Tulio Magno Quites Machado Filho
  2018-05-08 18:07     ` Adhemerval Zanella
  0 siblings, 1 reply; 45+ messages in thread
From: Tulio Magno Quites Machado Filho @ 2018-05-07 19:25 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha

Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:

> This patches adds the powerpc64 modification required for the BZ#12683.
> It basically adds the required __pthread_get_pc function and a arch
> specific syscall_cancel implementation.
>
> The powerpc requires an arch-specific syscall_cancel because
> INTERNAL_SYSCALL_NCS adds a mfcr just after the sc instruction to get
> the CR0.SO bit information from kernel (which signals the error
> return status).  So for cancelled syscalls with side effects,
> __pthread_get_pc will point to mcfr and thus invalidating the checks
> on sigcancel_handler.
>
> Checked on powerpc64le-linux-gnu and powerpc-linux-gnu.
>
> 	[BZ #12683]
> 	* sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S: New file.
> 	* sysdeps/unix/sysv/linux/powerpc/sysdep-cancel.h
> 	(__pthread_get_pc): New function.

This entry is outdated.  Both the file name and the function name need to be
updated.

> diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S b/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S
> new file mode 100644
> index 0000000..2e56c72
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S
> @@ -0,0 +1,64 @@
> +/* Cancellable syscall wrapper.  Linux/powerpc version.
> +   Copyright (C) 2017 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 [r3] __syscall_cancel_arch (int *cancelhandling [r3],
> +					long int nr   [r4],
> +					long int arg1 [r5],
> +					long int arg2 [r6],
> +					long int arg3 [r7],
> +					long int arg4 [r8],
> +					long int arg5 [r9],
> +					long int arg6 [r10])  */
> +
> +ENTRY (__syscall_cancel_arch)
> +
> +	.globl __syscall_cancel_arch_start
> +	.type  __syscall_cancel_arch_start,@function
> +__syscall_cancel_arch_start:
> +
> +	/* if (*cancelhandling & CANCELED_BITMASK)
> +	     __syscall_do_cancel()  */
> +	lwz     r0,0(r3)
> +	rldicl. r0,r0,62,63
> +	beq     1f
> +	b       __syscall_do_cancel

Should this be a Branch & Link?

-- 
Tulio Magno


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 02/21] nptl: Fix testcases for new pthread cancellation mechanism
  2018-05-07 17:13     ` Adhemerval Zanella
@ 2018-05-08 13:35       ` Zack Weinberg
  2018-05-08 17:26         ` Adhemerval Zanella
  0 siblings, 1 reply; 45+ messages in thread
From: Zack Weinberg @ 2018-05-08 13:35 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library

On Mon, May 7, 2018 at 1:13 PM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> On 06/05/2018 23:49, Zack Weinberg wrote:
>> On 26 Feb 2018, Adhemerval Zanella wrote:
>>> For tst-cancel{2,3} case it remove the pipe close because it might
>>> cause the write syscall to return with side effects if the close is
>>> executed before the pthread cancel.
>>
>> ... however, this change appears to be wrong.  If cancellation is
>> broken, these tests will now deadlock rather than failing cleanly.
>
> On current cancellation implementation the thread will finish regardless
> and sigcancel_handler will act whether there is side-effects or not
> (the pipe close). The issue is cancellation should not happen if syscall
> returns but some side effects already took place, in this case the pipe
> close.

I think maybe I didn't explain clearly enough what I'm worried about
here.  What the test case does _when cancellation works_ is sensible.
But this is a test case, it also needs to behave sensibly when
cancellation _doesn't_ work.  Imagine a new port where, for some
reason, the cancellation mechanism is so broken that read/write aren't
acting as cancellation points at all. Without the close,
tst-cancel{2,3} will block forever in read/write.  We have the
test-driver timeout as a backstop, but we shouldn't rely on it.

> Yes, although for this specific case I am not sure if this could happen
> in practice.  I assume if a thread issues a 'signal' followed by a 'close',
> the signal target thread will receive the events in a ordered manner, i.e,
> the signal handler will be activated before the syscall sees any
> side-effects (the close).  It seems to be Linux behaviour, but I am not
> sure if a different system might act differently.

I don't think POSIX makes any requirements, but yes, in practice the
signal should always arrive first.

> And I try to avoid the timing check, such as pthread_timedjoin_np,
> because they tend to quite fragile in practice for such cases (due either
> to system load when testing glibc, machine performance, etc.).

This is reasonable.

For the new cancellation mechanism in general, we don't have a good
way of arranging for SIGCANCEL to arrive at exactly the critical
points within the syscall sequence, do we?  I am tempted to try to
write a test case that scripts gdb and single-steps through a call to
open() and fires SIGCANCEL at each instruction.

>> won't it?  I think teaching the backtrace logic about this would be
>> better than needing to use a raw syscall() and then mess with the
>> PowerPC implementation of syscall().  I might feel differently about
>> this change if __read_nocancel were a public API, but it isn't...
>
> With your current suggestion to powerpc syscall bits, there is no need
> to actually change the powerpc syscall implementation besides an
> additional CFI mechanism.  But I do not mind to change the testcase on
> the bz12683 fix itself, the only advantage I see is by using indirect
> syscall there is no need to actually change it again.

I don't feel especially strongly about this now we have a way that
doesn't add actual instructions to powerpc syscall().

zw

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 03/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-05-07  2:49   ` Zack Weinberg
@ 2018-05-08 17:11     ` Adhemerval Zanella
  0 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-05-08 17:11 UTC (permalink / raw)
  To: Zack Weinberg, libc-alpha



On 06/05/2018 23:49, Zack Weinberg wrote:

Hi Zack,

First, thank you for the throughfully review on this patch.

> On 26 Feb 2018, Adhemerval Zanella wrote:
>> This patches fixes some race conditions in NPTL cancellation code by
>> redefining how cancellable syscalls are defined and handled.  Current
>> approach is to enable asynchronous cancellation prior to making the syscall
>> and restore the previous cancellation type once the syscall returns.
>>
>> As decribed in BZ#12683, this approach shows 2 important problems:
>>
>>   1. Cancellation can act after the syscall has returned from kernel, but
>>      before userspace saves the return value.  It might result in a resource
>>      leak if the syscall allocated a resource or a side effect (partial
>>      read/write), and there is no way to program handle it with cancellation
>>      handlers.
>>
>>   2. If a signal is handled while the thread is blocked at a cancellable
>>      syscall, the entire signal handler runs with asynchronous cancellation
>>      enabled.  This can lead to issues if the signal handler call functions
>>      which are async-signal-safe but not async-cancel-safe.
>>
>> For cancellation to work correctly, there are 5 points at which the
>> cancellation signal could arrive:
>>
>>   1. Before the final "testcancel" and before the syscall is made.
>>   2. Between the "testcancel" and the syscall.
>>   3. While the syscall is blocked and no side effects have yet taken place.
>>   4. While the syscall is blocked but with some side effects already having
>>      taken place (e.g. a partial read or write).
>>   5. After the syscall has returned.
>>
>> And GLIBC wants to act on cancellation in cases 1, 2, and 3 but not in case
>> 4 or 5.  The proposed solution follows:
>>
>>   * Handling case 1 is trivial: do a conditional branch based on whether the
>>     thread has received a cancellation request;
>>   * Case 2 can be caught by the signal handler determining that the saved
>>     program counter (from the ucontext_t) is in some address range beginning
>>     just before the "testcancel" and ending with the syscall instruction.
>>   * In this case, except for certain syscalls that ALWAYS fail with EINTR
>>     even for non-interrupting signals, the kernel will reset the program
>>     counter to point at the syscall instruction during signal handling, so
>>     that the syscall is restarted when the signal handler returns. So, from
>>     the signal handler's standpoint, this looks the same as case 2, and thus
>>     it's taken care of.
>>   * In this case, the kernel cannot restart the syscall; when it's
>>     interrupted by a signal, the kernel must cause the syscall to return
>>     with whatever partial result it obtained (e.g. partial read or write).
>>   * In this case, the saved program counter points just after the syscall
>>     instruction, so the signal handler won't act on cancellation.
>>     This one is equal to 4. since the program counter is past the syscall
>>     instruction already.
> 
> To be 100% clear here, you are fixing important problem #1 by having
> deferred cancellation _not_ trigger in cases 4 and 5, because the
> signal handler observes that the PC is past the syscall instruction?

Yes.

> 
>> Another case that needs handling is syscalls that fail with EINTR even
>> when the signal handler is non-interrupting. In this case, the syscall
>> wrapper code can just check the cancellation flag when the errno result
>> is EINTR, and act on cancellation if it's set.
> 
> Which system calls are affected by this rule, and is it actually
> correct to have cancellation trigger when they fail with EINTR? 

The best description I have is from man pages related to signal [1] in
the 'Interruption of system calls and library functions by signal handlers'
part.

[1] http://man7.org/linux/man-pages/man7/signal.7.html

And I think cancellation should happen int his case because it falls on 
the semantic that another thread explicit called pthread_cancel, it is
the underlying system behaviour that is not allowing libc to explicit 
cancel the thread.

> Can we be certain that the EINTR was due to the cancellation signal rather
> than some other signal delivered first?  (At least for sigsuspend it
> is possible to have two signals be delivered simultaneously, if they
> were both blocked and pending, and both become unblocked due to the
> sigsuspend.  The kernel pushes two signal stack frames.  It would
> reduce the odds of this being a problem if the SIGCANCEL handler
> masked all other signals while running, but I'm not sure that will
> work with it jumping directly to __pthread_unwind under some
> conditions, and also I don't think it _completely_ eliminates the
> possibility; a second signal could be delivered right after sigreturn
> unmasks it, without returning to the caller of the syscall stub first.)

By inspecting the CANCELED_BIT in thread cancelhandling mask:

nptl/libc-cancellation.c:

 50   if ((result == -EINTR)
 51       && (pd->cancelhandling & CANCELED_BITMASK)
 52       && !(pd->cancelhandling & CANCELSTATE_BITMASK))
 53     __syscall_do_cancel ();

Which is atomic set on pthread_cancel:

nptl/pthread_cancel.c:

 40 
 41   THREAD_ATOMIC_BIT_SET (pd, cancelhandling, CANCELED_BIT);
 42 

So for the case where the thread is indeed cancelled by pthread_cancel,
cancelhandling should have CANCELED bit set and if kernel deliver other
signal first and cancellation signal handler it not called, the code on
libc-cancellation should handle it.

> 
>>   1. Remove the enable_asynccancel/disable_asynccancel function usage in
>>      syscall definition and instead make them call a common symbol that will
>>      check if cancellation is enabled (__syscall_cancel at
>>      nptl/libc-cancellation.c), call the arch-specific cancellable
>>      entry-point (__syscall_cancel_arch) and cancel the thread when required.
>>
>>   2. Provide a arch-specific symbol that contains global markers. These
>>      markers will be used in SIGCANCEL handler to check if the interruption
>>      has been called in a valid syscall and if the syscalls has been
>>      completed or not.
>>      A default version is provided (sysdeps/unix/sysv/linux/syscall_cancel.c),
>>      however the markers may not be set on correct expected places depeding
>>      of how INTERNAL_SYSCALL_NCS is implemented by the underlying architecture.
>>      In this case arch-specific implementation should be provided.
>>
>>   3. Rewrite SIGCANCEL asynchronous handler to check for both cancelling type
>>      and if current IP from signal handler falls between the global markes
>>      and act accordingly (sigcancel_handler at nptl/nptl-init.c).
>>
>>   4. Adjust nptl/pthread_cancel.c to send an signal instead of acting
>>      directly. This avoid synchronization issues when updating the
>>      cancellation status and also focus the logic on signal handler and
>>      cancellation syscall code.
>>
>>   5. Adjust pthread code to replace CANCEL_ASYNC/CANCEL_RESET calls to
>>      appropriated cancelable futex syscalls.
>>
>>   6. Adjust libc code to replace LIBC_CANCEL_ASYNC/LIBC_CANCEL_RESET to
>>      appropriated cancelable syscalls.
>>
>>   7. Adjust 'lowlevellock-futex.h' arch-specific implementations to provide
>>      cancelable futex calls (used in libpthread code).
> 
> The overall design seems sound to me.
> 
>> This patch adds the proposed changes to NPTL.  The code leaves all the ports
>> broken without further patches in the list.
> 
> Can we find an ordering of the patches in which the tree is never
> broken at an intermediate stage?  Perhaps you could introduce the generic
> __syscall_cancel(_arch) first, but not change any of the existing
> cancellation logic until after all of the port-specific code was in
> place?

I think I can try to split this one two or more patches and make the actual fix 
tied with the first architecture changed (x86_64 currently). The x86_64 its the
only architectures that provides a *cancellation* re-implementation in assembly
(originally as optimization (?)), and I think we split it on a preliminary
clean-up patch. But I am not sure I can make the tree stable if we just apply
some architectures fixes, instead of all of them.

> 
> Below, all the changes which I erased and didn't comment on seem OK to
> me.  I am generally pleased to see many system call wrappers get
> simpler in the process of fixing this bug.
> 
>> --- a/io/creat.c
>> +++ b/io/creat.c
> ...
>> -
>> -/* __open handles cancellation.  */
>> -LIBC_CANCEL_HANDLED ();
> 
> It might be clearer to split patch 2 into two patches, one to remove
> tst-cancel-wrappers.sh and one to make all the other testing changes,
> and then shift all of the removals of LIBC_CANCEL_HANDLED into the
> same patch that removes tst-cancel-wrappers.sh.

This sounds reasonable, I will change it.

> 
>> --- a/nptl/descr.h
>> +++ b/nptl/descr.h
> ...
>> +  /* Bit set if threads is canceled.  */
> 
> Grammar: "Bit set if thread is canceled."
> 
> (For 100% proper English, it would be "This bit is set if this thread
> has been cancelled", but all of the other comments are clipped as
> well, so the above is fine.)

Ack.

> 
>> --- a/nptl/libc-cancellation.c
>> +++ b/nptl/libc-cancellation.c
> ...
>> +#include <setjmp.h>
>> +#include <stdlib.h>
> 
> Why are these additional #includes necessary?

They are not, I will remove them.

> 
> ...
>> +  volatile struct pthread *pd = (volatile struct pthread *) self;
> 
> Why is it necessary for this pointer to be volatile?  It appears that
> we only ever access pd->cancelhandling; which loads need to be
> forced to go to memory, and should they also be atomic?

If I recall correctly this came from a previous review, however I can't
recall why exactly it was required. Thinking twice I see no reason in
fact to use volatile here.  I will remove it.

> 
>> +  /* If cancellation is not enabled, call the syscall directly.  */
>> +  if (pd->cancelhandling & CANCELSTATE_BITMASK)
> 
> It is unfortunate that the one-bit flag that means "cancellation is
> disabled" is named CANCELSTATE_BITMASK instead of, I dunno,
> CANCEL_DISABLED_BITMASK maybe.  You didn't introduce that, but please
> consider a follow-up patch that renames CANCELSTATE_BIT(MASK) and also
> CANCELTYPE_BIT(MASK) [the latter to "CANCEL_ASYNC_BIT(MASK)" perhaps].

In fact in my bz12683 repo I have 4 more patches that refactor the cancellation
mask altogether [1].

[1] https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/azanella/bz12683

> 
>> +  if ((result == -EINTR)
>> +      && (pd->cancelhandling & CANCELED_BITMASK)
>> +      && !(pd->cancelhandling & CANCELSTATE_BITMASK))
>> +    __syscall_do_cancel ();
> 
> I thought you said this treatment was only applied to system calls
> that _always_ fail with EINTR, even when interrupted by SA_RESTART
> signals.  This is doing it for system calls interrupted by
> non-SA_RESTART signals as well.  You also change SIGCANCEL to be a
> SA_RESTART signal in this patch, but it still could happen that we
> have SIGCANCEL and some other non-SA_RESTART signal arrive
> simultaneously enough that they interrupt the same system call, and
> then it fails with EINTR and everything is confused.
> 
> I think you need to check over the entire design with "what if
> SIGCANCEL and some other signal are delivered as nested interruptions
> to the same system call" in mind, in fact.  The dangerous case that I
> see is when the _other_ signal causes the system call to be
> interrupted after producing some side effects.  Can the SIGCANCEL
> handler know that this has happened or is about to happen?

It is still handling only the cancellation case, since it checks the
cancelhandling bit that is set only if a thread calls pthread_cancel.
My understanding is nested interruptions should not be a problem: either
cancel sighandler is activated first which cancels the thread if syscall
does not have a side-effect or the syscall returns with EINTR and
with a cancellation pending (cancelhandling & CANCELED_BITMASK).

However I think we can improve the cancel handling (and potentially
simplifying the synchronization code on cancelhandling mask) by masking
all signals while handling SIGCANCEL.

> 
>> --- a/nptl/nptl-init.c
>> +++ b/nptl/nptl-init.c
>>  sigcancel_handler (int sig, siginfo_t *si, void *ctx)
>>  {
>> +  INTERNAL_SYSCALL_DECL (err);
>> +  pid_t pid = INTERNAL_SYSCALL_CALL (getpid, err);
>> +
>>    /* Safety check.  It would be possible to call this function for
>>       other signals and send a signal from another process.  This is not
>>       correct and might even be a security problem.  Try to catch as
>>       many incorrect invocations as possible.  */
>>    if (sig != SIGCANCEL
>> -      || si->si_pid != __getpid()
>> +      || si->si_pid != pid
>>        || si->si_code != SI_TKILL)
> 
> Why is this change necessary?

This code was before getpid cache removal (c579f48edba8) and I did not catch
it on my rebases.  I will remove it.

> 
>> +  volatile struct pthread *pd = (volatile struct pthread *) self;
> 
> Same question as above: why does this need to be volatile, does it
> actually do the job, should we instead be using atomics?

Same as before, I will remove it.

> 
>> +  /* Add SIGCANCEL on ignored sigmask to avoid the handler to be called
>> +     again.  */
>> +  sigset_t *set = UCONTEXT_SIGMASK (ctx);
>> +  __sigaddset (set, SIGCANCEL);
> 
> Screwing with the signal mask that will be restored by sigreturn seems
> unsafe.  Could we instead return early if CANCELED_BITMASK and/or
> EXITING_BITMASK has already been set?
> 
>> +  /* Check if asynchronous cancellation mode is set and if interrupted
>                                                        ^^^
> This 'and' should be 'or'.

Ack.

> 
>> +      THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
>> +      THREAD_SETMEM (self, result, PTHREAD_CANCELED);
> 
> I think these ought to be done inside __do_cancel, since several other
> places may call __do_cancel.

Indeed and the 'THREAD_SETMEM (self, result, PTHREAD_CANCELED)' here is superflous
(since __do_cancel already does it).

> 
>> +      INTERNAL_SYSCALL_CALL (rt_sigprocmask, err, SIG_SETMASK, set, NULL,
>> +                          _NSIG / 8);
> 
> See above in re screwing with the signal mask.
> 
>> +      __do_cancel ();
>> +      return;
>>      }
>>  }
> 
> This 'return' should be unnecessary on two counts: we're about to fall
> off the end of the function anyway, and __do_cancel ends by calling
> __pthread_unwind which does not return.

Indeed and __do_cancel is already marked as noreturn.  I will remove it.

> 
> --- a/nptl/pthreadP.h
> +++ b/nptl/pthreadP.h
> ...
>> -  /* Make sure we get no more cancellations.  */
>> -  THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
>> +  /* Make sure we get no more cancellations by clearing the cancel
>> +     state.  */
>> +  int oldval = THREAD_GETMEM (self, cancelhandling);
>> +  while (1)
>> +    {
>> +      int newval = (oldval | CANCELSTATE_BITMASK);
>> +      newval &= ~(CANCELTYPE_BITMASK);
> 
> Disabled cancellation state is specified to take precedence over
> asynchronous cancellation type, so it should be enough to atomically
> set CANCELSTATE_BIT, at which point the CAS loop would be unnecessary.

Right, this seems unnecessary.

> 
>> --- a/nptl/pthread_cancel.c
>> +++ b/nptl/pthread_cancel.c
> ...
>> +  /* Avoid signaling when thread attempts cancel itself (pthread_kill
>> +     is expensive).  */
>> +  if (pd == THREAD_SELF && !(pd->cancelhandling & CANCELTYPE_BITMASK))
>> +    return 0;
> 
> It is not obvious why this is correct.  The answer is that
> pthread_cancel is not itself a cancellation point, so, when
> cancellation is deferred, a self-cancel is _not_ supposed to take
> effect immediately; the signal handler would have no effect, and the
> next cancellation point will check the flag anyway.  I suggest instead
> 
>     if (pd == THREAD_SELF)
>       {
>          if (pd->cancelhandling & CANCELTYPE_BITMASK)
>            __do_cancel ();
>          /* pthread_cancel is not itself a cancellation point;
>             the next cancellation point will check the flag anyway,
>             so there is no need to send the cancellation signal.  */
>         return 0;
>      }
>      return __pthread_kill (th, SIGCANCEL);

I tried you suggestion, but it seems to trigger a regression which I think it
is unrelated to the patch:

>>> info threads
  Id   Target Id         Frame
* 1    LWP 28018 "ld-linux-x86-64" __GI___syscall_cancel_arch (ch=ch@entry=0x7ffff7ff2a48, nr=nr@entry=202, a1=a1@entry=140737345771984, a2=a2@entry=0, a3=28023, a4=a4@entry=0, a5=0, a6=0) at ../sysdeps/unix/sysv/linux/syscall_cancel.c:63
  3    LWP 28023 "ld-linux-x86-64" __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
  5    LWP 28025 "ld-linux-x86-64" __lll_unlock_wake () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:371
  7    LWP 28027 "ld-linux-x86-64" __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
  9    LWP 28029 "ld-linux-x86-64" __lll_unlock_wake () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:371
  11   LWP 28031 "ld-linux-x86-64" __lll_unlock_wake () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:371
  13   LWP 28033 "ld-linux-x86-64" __lll_unlock_wake () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:371
  15   LWP 28035 "ld-linux-x86-64" __lll_unlock_wake () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:371
  17   LWP 28037 "ld-linux-x86-64" __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
  19   LWP 28039 "ld-linux-x86-64" 0x00007ffff7bc3d95 in __GI___pthread_mutex_lock (mutex=0x7ffff7ffd990 <_rtld_local+2352>) at ../nptl/pthread_mutex_lock.c:113
  21   LWP 28041 "ld-linux-x86-64" __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135

The process seems to stuck on unwind operation:

#4  0x00007ffff71f9a13 in uw_frame_state_for (context=context@entry=0x7ffff71e9c20, fs=fs@entry=0x7ffff71e9a70) at /home/azanella/Projects/glibc/ports/src/gcc/libgcc/unwind-dw2.c:1249
#5  0x00007ffff71fac80 in uw_init_context_1 (context=context@entry=0x7ffff71e9c20, outer_cfa=outer_cfa@entry=0x7ffff71e9e50, outer_ra=0x7ffff7bca390 <__GI___pthread_unwind+64>) at /home/azanella/Projects/glibc/ports/src/gcc/libgcc/unwind-dw2.c:1578
#6  0x00007ffff71fb426 in _Unwind_ForcedUnwind (exc=0x7ffff71ead70, stop=stop@entry=0x7ffff7bca220 <unwind_stop>, stop_argument=0x7ffff71e9e80) at /home/azanella/Projects/glibc/ports/src/gcc/libgcc/unwind.inc:201
#7  0x00007ffff7bca390 in __GI___pthread_unwind (buf=<optimized out>) at unwind.c:121
#8  0x00007ffff7bc8b41 in __do_cancel () at pthreadP.h:302
#9  __pthread_cancel (th=140737339369216) at pthread_cancel.c:60
#10 0x000000000040174d in ?? ()
#11 0x0000000000000000 in ?? ()

It does not happen on powerpc or sparc as far I can check. I did not dig into, but
I think it would be safer to use current mechanism to pthread_cancel always by
signaling the thread with pthread_kill and we can revise this later why is
failing with your suggestion on x86.

> 
>> --- a/nptl/pthread_create.c
>> +++ b/nptl/pthread_create.c
> ...
>>    /* If the parent was running cancellation handlers while creating
>>       the thread the new thread inherited the signal mask.  Reset the
>>       cancellation signal mask.  */
> 
> If the cancellation handler exited early when EXITING_BIT was set, and
> it didn't mess with the signal mask, we wouldn't need to do this, either.
> 
>> -       int oldtype = CANCEL_ASYNC ();
>> +       int ct;
>> +       __pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &ct);
> 
> I don't understand the logic in this part of the code at all so I am
> going to trust you that this is the correct change.  It seems like
> it's using SIGCANCEL for something other than cancellation, which
> seems unwise and maybe should be changed in a follow-up.

I think we can follow up this on subsequent patches, since the change 
is just to adjust CANCEL_ASYNC macro removal.

> 
>> --- a/nptl/pthread_join_common.c
>> +++ b/nptl/pthread_join_common.c
> ...
>> -      int oldtype = CANCEL_ASYNC ();
>> +      int ct;
>> +      __pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &ct);
>>
>>        if (abstime != NULL)
>>       result = lll_timedwait_tid (pd->tid, abstime);
>>        else
>>       lll_wait_tid (pd->tid);
>>
>> -      CANCEL_RESET (oldtype);
>> +      __pthread_setcanceltype (ct, NULL);
> 
> Maybe we should have lll_(timed)wait_tid_cancel rather than this?

Both lll_timedwait_tid and lll_wait_tid are already a cancellation point, the
idea here is to just to enable asynchronous cancellation since pthread_join
is a cancellation entrypoint (and nptl/libc-cancellation.c call the syscall
directly if cancellation is disabled).

> 
>> --- a/sysdeps/unix/sysdep.h
>> +++ b/sysdeps/unix/sysdep.h
> ...
>> +/* The loader does not need to handle thread cancellation, use direct
>> +   syscall instead.  */
> 
> A stronger assertion would be better:
> 
> /* The loader should never make cancellable system calls.  Remap them
>    to direct system calls.  */

Ack, I changed to your suggestion.

> 
> Also, is this hack still necessary after I went through and made the
> loader explicitly use _nocancel operations?

I need to actually check, but I presume that once the patch go in, loader build
would not require to pull objects that might pull the libc-cancellation.

> 
>> --- a/sysdeps/unix/sysv/linux/pthread_kill.c
>> +++ b/sysdeps/unix/sysv/linux/pthread_kill.c
> ...
>> -  /* Disallow sending the signal we use for cancellation, timers,
>> -     for the setxid implementation.  */
>> -  if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID)
>> +  /* Disallow sending the signal we use for setxid implementation.  */
>> +  if (signo == SIGSETXID)
>>      return EINVAL;
> 
> Now applications can call pthread_kill(thr, SIGCANCEL) themselves,
> can't they?  That seems unsafe.  Also this has since been changed to
> use __is_internal_signal, I think.  We need an __internal_pthread_kill
> or something.

Yes, I will change to call an internal symbol.

> 
>> --- a/sysdeps/unix/sysv/linux/socketcall.h
>> +++ b/sysdeps/unix/sysv/linux/socketcall.h
> ...
>> +#define __SOCKETCALL_CANCEL1(__name, __a1) \
>> +  SYSCALL_CANCEL_NCS (socketcall, __name, \
>> +     ((long int [1]) { (long int) __a1 }))
> 
> Blech, which architectures still require us to use socketcall?

The one I recall, i386, m68k, s390, and sparc (some socket operations are wire-up
in recent kernels for some architectures).

> 
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/syscall_cancel.c
> ...
>> +#define ADD_LABEL(__label)		\
>> +  asm volatile (			\
>> +    ".global " __label "\t\n"		\
>> +    ".type " __label ",\%function\t\n"       \
>> +    __label ":\n");
> 
> This makes me extremely nervous.  Specifically, I do not trust the
> compiler to not move these around, even though they're volatile.  I
> would actually prefer an .S file for every architecture.
> 
> Do we have a concrete reason to believe they really will always be
> where they're supposed to be?  "It compiled fine with the compiler I
> have right now" is not enough, I'm afraid.

For the architectures that I am using the C implementation (riscv, mips64, 
nios2, m68k, alpha, ia64, arm, and aarch64) two different gcc version
generates the expected code (gcc6 and gcc7). My understanding is the
volatile asm should not move the ADD_LABEL macro other C declaration,
but I give you that depending on how the architecture defines
INTERNAL_SYSCALL_NCS_CALL, the labels might no in right position.

I created it to easier the port adjustments (since for some architectures
I don't have much experience with ABI), but I give you I don't have a 
strong preference here. The main advantage I see is it simplifies a lot the
required boilerplate on some ABIs for PIC/non-PIC code.

> 
>> --- a/sysdeps/unix/sysv/linux/sysdep.h
>> +++ b/sysdeps/unix/sysv/linux/sysdep.h
> ...
>> +/* Check error from cancellable syscall and set errno accordingly.
>> +   Linux uses a negative return value to indicate syscall errors
>> +   and since version 2.1 the return value of a system call might be
>> +   negative even if the call succeeded (e.g., the `lseek' system call
>> +   might return a large offset).
>> +   Current contract is kernel make sure the no syscall returns a value
>> +   in -1 .. -4095 as a valid result so we can savely test with -4095.  */
>> +#define SYSCALL_CANCEL_RET(__ret)		\
>> +  ({						\
>> +    if (__ret > -4096UL)			\
>> +      {						\
>> +	__set_errno (-__ret);			\
>> +	__ret = -1;				\
>> +      }						\
>> +    __ret;					\
>> +   })
> 
> Don't we already have this somewhere under another name?

Not really, we have the INTERNAL_SYSCALL_ERROR_P macro which check the
error from the INTERNAL_SYSCALL_DECL (err).  The issues is some some kernel
abis (alpha and sparc for instance) either it does check the return code 
(alpha) or it expects the expecial kernel abi register (sparc). I added this
one for consistency.


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 02/21] nptl: Fix testcases for new pthread cancellation mechanism
  2018-05-08 13:35       ` Zack Weinberg
@ 2018-05-08 17:26         ` Adhemerval Zanella
  0 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-05-08 17:26 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: GNU C Library



On 08/05/2018 10:35, Zack Weinberg wrote:
> On Mon, May 7, 2018 at 1:13 PM, Adhemerval Zanella
> <adhemerval.zanella@linaro.org> wrote:
>> On 06/05/2018 23:49, Zack Weinberg wrote:
>>> On 26 Feb 2018, Adhemerval Zanella wrote:
>>>> For tst-cancel{2,3} case it remove the pipe close because it might
>>>> cause the write syscall to return with side effects if the close is
>>>> executed before the pthread cancel.
>>>
>>> ... however, this change appears to be wrong.  If cancellation is
>>> broken, these tests will now deadlock rather than failing cleanly.
>>
>> On current cancellation implementation the thread will finish regardless
>> and sigcancel_handler will act whether there is side-effects or not
>> (the pipe close). The issue is cancellation should not happen if syscall
>> returns but some side effects already took place, in this case the pipe
>> close.
> 
> I think maybe I didn't explain clearly enough what I'm worried about
> here.  What the test case does _when cancellation works_ is sensible.
> But this is a test case, it also needs to behave sensibly when
> cancellation _doesn't_ work.  Imagine a new port where, for some
> reason, the cancellation mechanism is so broken that read/write aren't
> acting as cancellation points at all. Without the close,
> tst-cancel{2,3} will block forever in read/write.  We have the
> test-driver timeout as a backstop, but we shouldn't rely on it.

Well, adding a timing mechanism (either by alarm, pthread_timedjoin, etc)
is basically what the test-driver backstop is actually doing, with the
advantage it is another process no susceptible to possible memory 
corruptions or other execution failures.  I don't see much gain in
add more hardening in test itself.

> 
>> Yes, although for this specific case I am not sure if this could happen
>> in practice.  I assume if a thread issues a 'signal' followed by a 'close',
>> the signal target thread will receive the events in a ordered manner, i.e,
>> the signal handler will be activated before the syscall sees any
>> side-effects (the close).  It seems to be Linux behaviour, but I am not
>> sure if a different system might act differently.
> 
> I don't think POSIX makes any requirements, but yes, in practice the
> signal should always arrive first.
> 
>> And I try to avoid the timing check, such as pthread_timedjoin_np,
>> because they tend to quite fragile in practice for such cases (due either
>> to system load when testing glibc, machine performance, etc.).
> 
> This is reasonable.
> 
> For the new cancellation mechanism in general, we don't have a good
> way of arranging for SIGCANCEL to arrive at exactly the critical
> points within the syscall sequence, do we?  I am tempted to try to
> write a test case that scripts gdb and single-steps through a call to
> open() and fires SIGCANCEL at each instruction.

I can't really think any explicit way to actually check it, a gdb/ptrace
is the close think I can think off as well.

> 
>>> won't it?  I think teaching the backtrace logic about this would be
>>> better than needing to use a raw syscall() and then mess with the
>>> PowerPC implementation of syscall().  I might feel differently about
>>> this change if __read_nocancel were a public API, but it isn't...
>>
>> With your current suggestion to powerpc syscall bits, there is no need
>> to actually change the powerpc syscall implementation besides an
>> additional CFI mechanism.  But I do not mind to change the testcase on
>> the bz12683 fix itself, the only advantage I see is by using indirect
>> syscall there is no need to actually change it again.
> 
> I don't feel especially strongly about this now we have a way that
> doesn't add actual instructions to powerpc syscall().
> 
> zw
> 

Right, I will my current version on next version.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 04/21] nptl: x86_64: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-05-07  2:49   ` Zack Weinberg
@ 2018-05-08 17:55     ` Adhemerval Zanella
  0 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-05-08 17:55 UTC (permalink / raw)
  To: Zack Weinberg, libc-alpha



On 06/05/2018 23:49, Zack Weinberg wrote:
> On 26 Feb 2018, Adhemerval Zanella wrote:
>> This patches adds the x86_64 modification required for the BZ#12683.
>> It basically provide the required ucontext_get_pc symbol and remove
>> the arch-specific libc-cancellation implementations.
> 
> These changes all look fine to me.
> 
>>   lock;orl $4, %fs:776
>>
>> Where with patch changes it now compiles to:
>>
>>   mov %fs:16,%rax
>>   lock;orl $4, 776(%rax)
> 
> That might actually be faster on some microarchitectures due to not
> having multiple unusual prefixes on one instruction.  I wouldn't worry
> about it.
> 
>> In fact all x86_64 THREAD_ATOMIC_* macros
>> do not respect the input descr and possible will fail when used with
>> a 'descr' difference than THREAD_SELF.
> 
> Maybe we should correct or remove all of them, then?  They sound like
> they're bugs waiting to happen.
> 
> zw
> 

Right, I will fix in on an extra patch then.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 06/21] nptl: i386: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-05-07  2:49   ` Zack Weinberg
@ 2018-05-08 17:56     ` Adhemerval Zanella
  0 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-05-08 17:56 UTC (permalink / raw)
  To: Zack Weinberg, libc-alpha



On 06/05/2018 23:49, Zack Weinberg wrote:
> On 26 Feb 2018, Adhemerval Zanella wrote:
>> This patch adds the i386 modifications required for the BZ#12683.
>> It basically provides the required ucontext_get_pc symbol, add the
>> cancelable syscall wrapper and fix a thread atomic update macro.
> 
> This also seems fine.
> 
>> On i386 an arch-specific cancellation implementation is required
>> because depending of the glibc configuration and underlying kernel
>> the syscall may be done using a vDSO symbol (__kernel_vsyscall).
> ...
>> Also, since glibc supports i486, the old 'int 0x80' should be used
>> in the syscall wrapper.  One option could make minimum default chip
>> to pentium II (which implements sysenter) or add a runtime check
>> on syscall_cancel.S to use 'int 0x80' or sysenter.
> 
> If I remember correctly, there can be only one 'sysenter' instruction
> in the entire user address space, due to awkward limitations of the
> interface it presents to the kernel.  That was why __kernel_vsyscall
> was added in the first place.
> 
> We can probably live with using int 0x80 for these syscalls that may
> well be blocking anyway.
> 
>> Similar to x86_64, it also remove bogus arch-specific
>> THREAD_ATOMIC_BIT_SET where it always reference to current thread
>> instead of the one referenced by input 'descr' argument.
> 
> Same comment as for x86_64 -- shouldn't we get rid of or repair _all_ of
> the THREAD_ATOMIC_ macros that don't honor their arguments?
> 
> zw
> 

Alright, I will remove then in an extra patch as well.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 07/21] nptl: powerpc: Fix Race conditions in pthread cancellation (BZ#12683)
  2018-05-07 19:25   ` Tulio Magno Quites Machado Filho
@ 2018-05-08 18:07     ` Adhemerval Zanella
  0 siblings, 0 replies; 45+ messages in thread
From: Adhemerval Zanella @ 2018-05-08 18:07 UTC (permalink / raw)
  To: Tulio Magno Quites Machado Filho, libc-alpha



On 07/05/2018 16:25, Tulio Magno Quites Machado Filho wrote:
> Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
> 
>> This patches adds the powerpc64 modification required for the BZ#12683.
>> It basically adds the required __pthread_get_pc function and a arch
>> specific syscall_cancel implementation.
>>
>> The powerpc requires an arch-specific syscall_cancel because
>> INTERNAL_SYSCALL_NCS adds a mfcr just after the sc instruction to get
>> the CR0.SO bit information from kernel (which signals the error
>> return status).  So for cancelled syscalls with side effects,
>> __pthread_get_pc will point to mcfr and thus invalidating the checks
>> on sigcancel_handler.
>>
>> Checked on powerpc64le-linux-gnu and powerpc-linux-gnu.
>>
>> 	[BZ #12683]
>> 	* sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S: New file.
>> 	* sysdeps/unix/sysv/linux/powerpc/sysdep-cancel.h
>> 	(__pthread_get_pc): New function.
> 
> This entry is outdated.  Both the file name and the function name need to be
> updated.

Ack.

> 
>> diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S b/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S
>> new file mode 100644
>> index 0000000..2e56c72
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S
>> @@ -0,0 +1,64 @@
>> +/* Cancellable syscall wrapper.  Linux/powerpc version.
>> +   Copyright (C) 2017 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 [r3] __syscall_cancel_arch (int *cancelhandling [r3],
>> +					long int nr   [r4],
>> +					long int arg1 [r5],
>> +					long int arg2 [r6],
>> +					long int arg3 [r7],
>> +					long int arg4 [r8],
>> +					long int arg5 [r9],
>> +					long int arg6 [r10])  */
>> +
>> +ENTRY (__syscall_cancel_arch)
>> +
>> +	.globl __syscall_cancel_arch_start
>> +	.type  __syscall_cancel_arch_start,@function
>> +__syscall_cancel_arch_start:
>> +
>> +	/* if (*cancelhandling & CANCELED_BITMASK)
>> +	     __syscall_do_cancel()  */
>> +	lwz     r0,0(r3)
>> +	rldicl. r0,r0,62,63
>> +	beq     1f
>> +	b       __syscall_do_cancel
> 
> Should this be a Branch & Link?
> 

Right, I think ABI really mandates branch & link even for no-return calls.
I will change it.

^ permalink raw reply	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2018-05-08 18:08 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-26 21:03 [PATCH v2 00/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 01/21] powerpc: Create stackframe information on syscall Adhemerval Zanella
2018-02-26 21:41   ` Andreas Schwab
2018-02-27 12:05     ` Adhemerval Zanella
2018-05-07  2:49   ` Zack Weinberg
2018-05-07 13:57     ` Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 02/21] nptl: Fix testcases for new pthread cancellation mechanism Adhemerval Zanella
2018-02-26 21:43   ` Andreas Schwab
2018-02-27 12:05     ` Adhemerval Zanella
2018-05-07  2:49   ` Zack Weinberg
2018-05-07 17:13     ` Adhemerval Zanella
2018-05-08 13:35       ` Zack Weinberg
2018-05-08 17:26         ` Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 03/21] nptl: Fix Race conditions in pthread cancellation (BZ#12683) Adhemerval Zanella
2018-04-27 12:20   ` Zack Weinberg
2018-04-27 12:25     ` Adhemerval Zanella
2018-05-07  2:48       ` Zack Weinberg
2018-05-07  2:49   ` Zack Weinberg
2018-05-08 17:11     ` Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 04/21] nptl: x86_64: " Adhemerval Zanella
2018-05-07  2:49   ` Zack Weinberg
2018-05-08 17:55     ` Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 05/21] nptl: x32: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 06/21] nptl: i386: " Adhemerval Zanella
2018-05-07  2:49   ` Zack Weinberg
2018-05-08 17:56     ` Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 07/21] nptl: powerpc: " Adhemerval Zanella
2018-05-07 19:25   ` Tulio Magno Quites Machado Filho
2018-05-08 18:07     ` Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 08/21] nptl: aarch64: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 09/21] nptl: arm: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 10/21] nptl: s390: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 11/21] nptl: ia64: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 12/21] nptl: alpha: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 13/21] nptl: m68k: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 14/21] nptl: microblaze: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 15/21] nptl: tile: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 16/21] nptl: sparc: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 17/21] nptl: nios2: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 18/21] nptl: sh: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 19/21] nptl: mips: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 20/21] nptl: hppa: " Adhemerval Zanella
2018-02-26 21:03 ` [PATCH v2 21/21] nptl: riscv: " Adhemerval Zanella
2018-02-27  1:16   ` DJ Delorie
2018-02-27 13:03     ` Adhemerval Zanella

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).