Add DWARF 2 CFA column which tracks the return address from a signal
handler context.  This value must not correspond to a hard register
and must be out of the range of DWARF_FRAME_REGNUM().

gcc/
        * config/arc/arc.h (DWARF_FRAME_REGNUM): Update definition.
        (DWARF_FRAME_RETURN_COLUMN): Use RETURN_ADDR_REGNUM macro.
        (INCOMING_RETURN_ADDR_RTX): Likewise.
        (DWARF_ALT_FRAME_RETURN_COLUMN): Define.

gcc/testsuite/
        * gcc.target/arc/cancel-1.c: New file.

libgcc/
        * config/arc/linux-unwind.h (arc_fallback_frame_state): Use
        DWARF_ALT_FRAME_RETURN_COLUMN macro.

Signed-off-by: Claudiu Zissulescu <claz...@synopsys.com>
---
 gcc/config/arc/arc.h                    | 11 ++++++---
 gcc/testsuite/gcc.target/arc/cancel-1.c | 31 +++++++++++++++++++++++++
 libgcc/config/arc/linux-unwind.h        |  9 +++----
 3 files changed, 44 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arc/cancel-1.c

diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index 78b5000eeb7..539a1662084 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -1356,7 +1356,7 @@ do { \
    : (REGNO))
 
 /* Use gcc hard register numbering for eh_frame.  */
-#define DWARF_FRAME_REGNUM(REG) (REG)
+#define DWARF_FRAME_REGNUM(REG) ((REG) < 144 ? REG : INVALID_REGNUM)
 
 /* Map register numbers held in the call frame info that gcc has
    collected using DWARF_FRAME_REGNUM to those that should be output
@@ -1370,9 +1370,14 @@ do { \
       : 57 + !!TARGET_MULMAC_32BY16_SET) /* MLO */             \
    : (REGNO))
 
-#define DWARF_FRAME_RETURN_COLUMN      DWARF_FRAME_REGNUM (31)
+/* The DWARF 2 CFA column which tracks the return address.  */
+#define DWARF_FRAME_RETURN_COLUMN RETURN_ADDR_REGNUM
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM)
 
-#define INCOMING_RETURN_ADDR_RTX  gen_rtx_REG (Pmode, 31)
+/* The DWARF 2 CFA column which tracks the return address from a signal handler
+   context.  This value must not correspond to a hard register and must be out
+   of the range of DWARF_FRAME_REGNUM().  */
+#define DWARF_ALT_FRAME_RETURN_COLUMN 144
 
 /* Frame info.  */
 
diff --git a/gcc/testsuite/gcc.target/arc/cancel-1.c 
b/gcc/testsuite/gcc.target/arc/cancel-1.c
new file mode 100644
index 00000000000..e050c538157
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/cancel-1.c
@@ -0,0 +1,31 @@
+/* Test for cleanups with pthread_cancel.  Any issue with libgcc's unwinder
+   will cause this test to spin in pthread_join.  */
+
+/* { dg-do run } */
+/* { dg-require-effective-target pthread } */
+/* { dg-options "-pthread" } */
+
+#include <pthread.h>
+#include <unistd.h>
+#include <stdio.h>
+
+void *thread_loop (void *)
+{
+  while (1)
+    {
+      printf("worker: loop\n");
+      sleep(1);
+    }
+}
+
+int main ()
+{
+  pthread_t thread;
+
+  pthread_create (&thread, 0, thread_loop, 0);
+  sleep(5);
+  pthread_cancel (thread);
+  pthread_join (thread, 0);
+
+  return 0;
+}
diff --git a/libgcc/config/arc/linux-unwind.h b/libgcc/config/arc/linux-unwind.h
index 1d8c0c55883..be42a3163b2 100644
--- a/libgcc/config/arc/linux-unwind.h
+++ b/libgcc/config/arc/linux-unwind.h
@@ -120,10 +120,11 @@ arc_fallback_frame_state (struct _Unwind_Context *context,
        = ((_Unwind_Ptr) &(regs[i])) - new_cfa;
     }
 
-  fs->regs.reg[31].how = REG_SAVED_VAL_OFFSET;
-  fs->regs.reg[31].loc.offset = ((_Unwind_Ptr) (regs[ret])) - new_cfa;
-
-  fs->retaddr_column = 31;
+  fs->signal_frame = 1;
+  fs->retaddr_column = __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__;
+  fs->regs.reg[fs->retaddr_column].how = REG_SAVED_VAL_OFFSET;
+  fs->regs.reg[fs->retaddr_column].loc.offset =
+    ((_Unwind_Ptr) (regs[ret])) - new_cfa;
 
   return _URC_NO_REASON;
 }
-- 
2.31.1

Reply via email to