* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise.
This commit is contained in:
Ulrich Drepper 2003-04-12 08:38:14 +00:00
parent 09d65ff393
commit 68107ec092
5 changed files with 132 additions and 33 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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. */

View File

@ -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

View File

@ -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);