summaryrefslogtreecommitdiff
path: root/nptl
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-04-12 08:38:14 +0000
committerUlrich Drepper <drepper@redhat.com>2003-04-12 08:38:14 +0000
commit68107ec092e7cc3fcd1f56edf9da8085cffed00d (patch)
tree4297addf21ce4bc6d324a145ecacaf7920b336d4 /nptl
parent09d65ff393e9183eecba1e5cb877e95dbdd3d4a4 (diff)
Update.
* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise.
Diffstat (limited to 'nptl')
-rw-r--r--nptl/ChangeLog1
-rw-r--r--nptl/descr.h24
-rw-r--r--nptl/sysdeps/pthread/pthread.h2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h108
-rw-r--r--nptl/unwind.c30
5 files changed, 132 insertions, 33 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index bbda8c591e..d40118b42d 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -30,6 +30,7 @@
handler interfaces.
* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Add quite a bit of
complication to generate unwind information for syscall wrappers.
+ * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise.
* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Define
__cleanup_fct_attribute.
diff --git a/nptl/descr.h b/nptl/descr.h
index 28b7afa1a1..efb25c7479 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -63,18 +63,19 @@
information. */
struct pthread_unwind_buf
{
+ struct
+ {
+ __jmp_buf jmp_buf;
+ int mask_was_saved;
+ } cancel_jmp_buf[1];
+
union
{
/* This is the placeholder of the public version. */
- void *pad[16];
+ void *pad[4];
struct
{
-#ifdef HAVE_FORCED_UNWIND
- /* First the machine-specific unwind info. */
- struct _Unwind_Exception exc;
-#endif
-
/* Pointer to the previous cleanup buffer. */
__pthread_unwind_buf_t *prev;
@@ -87,12 +88,6 @@ struct pthread_unwind_buf
int canceltype;
} data;
} priv;
-
- struct
- {
- __jmp_buf jmp_buf;
- int mask_was_saved;
- } cancel_jmp_buf[1];
};
@@ -226,6 +221,11 @@ struct pthread
/* Next descriptor with a pending event. */
struct pthread *nextevent;
+#ifdef HAVE_FORCED_UNWIND
+ /* Machine-specific unwind info. */
+ struct _Unwind_Exception exc;
+#endif
+
/* If nonzero pointer to area allocated for the stack and its
size. */
void *stackblock;
diff --git a/nptl/sysdeps/pthread/pthread.h b/nptl/sysdeps/pthread/pthread.h
index 5373b80dcf..1c59e1ea2e 100644
--- a/nptl/sysdeps/pthread/pthread.h
+++ b/nptl/sysdeps/pthread/pthread.h
@@ -385,12 +385,12 @@ extern void pthread_testcancel (void) __THROW;
typedef struct
{
- void *__pad[16];
struct
{
__jmp_buf __cancel_jmp_buf;
int __mask_was_saved;
} __cancel_jmp_buf[1];
+ void *__pad[4];
} __pthread_unwind_buf_t __attribute__ ((__aligned__));
/* No special attributes by default. */
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
index fde001d4a6..7e7bc49073 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
@@ -29,6 +29,7 @@
# define PSEUDO(name, syscall_name, args) \
.text; \
ENTRY (name) \
+ L(name##START): \
SINGLE_THREAD_P; \
jne L(pseudo_cancel); \
DO_CALL (syscall_name, args); \
@@ -54,7 +55,100 @@
RESTSTK_##args \
cmpq $-4095, %rax; \
jae SYSCALL_ERROR_LABEL; \
- L(pseudo_end):
+ L(pseudo_end): \
+ \
+ /* Create unwinding information for the syscall wrapper. */ \
+ .section .eh_frame,"a",@progbits; \
+ L(STARTFRAME): \
+ /* Length of the CIE. */ \
+ .long L(ENDCIE)-L(STARTCIE); \
+ L(STARTCIE): \
+ /* CIE ID. */ \
+ .long 0; \
+ /* Version number. */ \
+ .byte 1; \
+ /* NUL-terminated augmentation string. Note "z" means there is an \
+ augmentation value later on. */ \
+ .string "zR"; \
+ /* Code alignment factor. */ \
+ .uleb128 1; \
+ /* Data alignment factor. */ \
+ .sleb128 -8; \
+ /* Return address register column. */ \
+ .byte 16; \
+ /* Augmentation value length. */ \
+ .uleb128 1; \
+ /* Encoding: DW_EH_PE_pcrel + DW_EH_PE_sdata4. */ \
+ .byte 0x1b; \
+ /* Start of the table initialization. */ \
+ .byte 0xc; \
+ .uleb128 7; \
+ .uleb128 8; \
+ .byte 0x90; \
+ .uleb128 1; \
+ .align 8; \
+ L(ENDCIE): \
+ /* Length of the FDE. */ \
+ .long L(ENDFDE)-L(STARTFDE); \
+ L(STARTFDE): \
+ /* CIE pointer. */ \
+ .long L(STARTFDE)-L(STARTFRAME); \
+ /* PC-relative start address of the code. */ \
+ .long L(name##START)-.; \
+ /* Length of the code. */ \
+ .long L(name##END)-L(name##START); \
+ /* No augmentation data. */ \
+ .uleb128 0; \
+ /* The rest of the code depends on the number of parameters the syscall \
+ takes. */ \
+ EH_FRAME_##args(name); \
+ .align 4; \
+ L(ENDFDE): \
+ .previous
+
+# define EH_FRAME_0(name) \
+ .byte 4; \
+ .long L(SAVESTK)-L(name##START); \
+ .byte 14; \
+ .uleb128 32; \
+ .byte 4; \
+ .long L(RESTSTK)-L(SAVESTK); \
+ .byte 14; \
+ .uleb128 8; \
+ .align 8
+
+# define EH_FRAME_1(name) EH_FRAME_0 (name)
+# define EH_FRAME_2(name) EH_FRAME_1 (name)
+
+# define EH_FRAME_3(name) \
+ .byte 4; \
+ .long L(SAVESTK)-L(name##START); \
+ .byte 14; \
+ .uleb128 48; \
+ .byte 4; \
+ .long L(RESTSTK)-L(SAVESTK); \
+ .byte 14; \
+ .uleb128 8; \
+ .align 8
+
+# define EH_FRAME_4(name) EH_FRAME_3 (name)
+
+# define EH_FRAME_5(name) \
+ .byte 4; \
+ .long L(SAVESTK)-L(name##START); \
+ .byte 14; \
+ .uleb128 64; \
+ .byte 4; \
+ .long L(RESTSTK)-L(SAVESTK); \
+ .byte 14; \
+ .uleb128 8; \
+ .align 8
+
+# define EH_FRAME_6(name) EH_FRAME_5 (name)
+
+
+# undef ASM_SIZE_DIRECTIVE
+# define ASM_SIZE_DIRECTIVE(name) L(name##END): .size name,.-name;
# define PUSHARGS_0 /* Nothing. */
# define PUSHARGS_1 PUSHARGS_0 movq %rdi, 8(%rsp);
@@ -73,20 +167,20 @@
# define POPARGS_6 POPARGS_5 movq 48(%rsp), %r9;
/* We always have to align the stack before calling a function. */
-# define SAVESTK_0 subq $24, %rsp;
+# define SAVESTK_0 subq $24, %rsp; L(SAVESTK):
# define SAVESTK_1 SAVESTK_0
# define SAVESTK_2 SAVESTK_1
-# define SAVESTK_3 subq $40, %rsp;
+# define SAVESTK_3 subq $40, %rsp; L(SAVESTK):
# define SAVESTK_4 SAVESTK_3
-# define SAVESTK_5 subq $56, %rsp;
+# define SAVESTK_5 subq $56, %rsp; L(SAVESTK):
# define SAVESTK_6 SAVESTK_5
-# define RESTSTK_0 addq $24,%rsp;
+# define RESTSTK_0 addq $24,%rsp; L(RESTSTK):
# define RESTSTK_1 RESTSTK_0
# define RESTSTK_2 RESTSTK_1
-# define RESTSTK_3 addq $40, %rsp;
+# define RESTSTK_3 addq $40, %rsp; L(RESTSTK):
# define RESTSTK_4 RESTSTK_3
-# define RESTSTK_5 addq $56, %rsp;
+# define RESTSTK_5 addq $56, %rsp; L(RESTSTK):
# define RESTSTK_6 RESTSTK_5
# ifdef IS_IN_libpthread
diff --git a/nptl/unwind.c b/nptl/unwind.c
index 46c896d5b3..7529174d5a 100644
--- a/nptl/unwind.c
+++ b/nptl/unwind.c
@@ -69,28 +69,32 @@ __pthread_unwind (__pthread_unwind_buf_t *buf)
struct _pthread_cleanup_buffer *oldp = ibuf->priv.data.cleanup;
struct _pthread_cleanup_buffer *curp = THREAD_GETMEM (self, cleanup);
- while (curp != oldp)
+ if (curp != oldp)
{
- /* Pointer to the next element. */
- struct _pthread_cleanup_buffer *nextp = curp->__prev;
+ do
+ {
+ /* Pointer to the next element. */
+ struct _pthread_cleanup_buffer *nextp = curp->__prev;
- /* Call the handler. */
- curp->__routine (curp->__arg);
+ /* Call the handler. */
+ curp->__routine (curp->__arg);
- /* To the next. */
- curp = nextp;
- }
+ /* To the next. */
+ curp = nextp;
+ }
+ while (curp != oldp);
- /* Mark the current element as handled. */
- THREAD_SETMEM (self, cleanup, curp);
+ /* Mark the current element as handled. */
+ THREAD_SETMEM (self, cleanup, curp);
+ }
#ifdef HAVE_FORCED_UNWIND
/* This is not a catchable exception, so don't provide any details about
the exception type. We do need to initialize the field though. */
- ibuf->priv.data.exc.exception_class = 0;
- ibuf->priv.data.exc.exception_cleanup = unwind_cleanup;
+ THREAD_SETMEM (self, exc.exception_class, 0);
+ THREAD_SETMEM (self, exc.exception_cleanup, unwind_cleanup);
- _Unwind_ForcedUnwind (&ibuf->priv.data.exc, unwind_stop, ibuf);
+ _Unwind_ForcedUnwind (&self->exc, unwind_stop, ibuf);
#else
/* We simply jump to the registered setjmp buffer. */
__libc_longjmp ((struct __jmp_buf_tag *) ibuf->cancel_jmp_buf, 1);