2003-06-07  Ulrich Drepper  <drepper@redhat.com>

	* cleanup_routine.c: New file.
	* Versions (libpthread) [GLIBC_2.3.3]: Add __pthread_cleanup_routine.
	* sysdeps/pthread/pthread.h: Add support for fully exception-based
	cleanup handling.
	* Makefile (libpthread-routines): Add cleanup_routine.
	Add more CFLAGS variables to compile with exceptions.  Add comments
	why which file needs unwind tables.
	(tests) [have-forced-unwind==yes]: Add tst-cancelx* and tst-cleanupx*
	tests.
	* tst-cancelx1.c: New file.
	* tst-cancelx2.c: New file.
	* tst-cancelx3.c: New file.
	* tst-cancelx4.c: New file.
	* tst-cancelx5.c: New file.
	* tst-cancelx6.c: New file.
	* tst-cancelx7.c: New file.
	* tst-cancelx8.c: New file.
	* tst-cancelx9.c: New file.
	* tst-cancelx10.c: New file.
	* tst-cancelx11.c: New file.
	* tst-cancelx12.c: New file.
	* tst-cancelx13.c: New file.
	* tst-cancelx14.c: New file.
	* tst-cancelx15.c: New file.
	* tst-cleanupx0.c: New file.
	* tst-cleanupx0.expect: New file.
	* tst-cleanupx1.c: New file.
	* tst-cleanupx2.c: New file.
	* tst-cleanupx3.c: New file.

	* tst-cleanup0.c: Make standard compliant.
	* tst-cleanup1.c: Likewise.

	* sysdeps/unix/sysv/linux/sem_timedwait.c: Add cancellation support.
	* sysdeps/unix/sysv/linux/sem_wait.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise.
	* sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise.
	* sysdeps/i386/tcb-offsets.sym: Add RESULT, CANCELHANDLING, and
	CLEANUP_JMP_BUF.
	* sysdeps/x86_64/tcb-offsets.sym: Likewise.
	* tst-cancel12.c: New file.
	* tst-cancel13.c: New file.
	* tst-cancel14.c: New file.
	* tst-cancel15.c: New file.
	* Makefile (tests): Add tst-cancel12, tst-cancel13, tst-cancel14,
	and tst-cancel15.

	* tst-cancel1.c: Add some comments.

	* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Compute relative
	timeout correctly.
This commit is contained in:
Ulrich Drepper 2003-06-08 05:28:14 +00:00
parent ede0f73aea
commit 7726edc273
40 changed files with 1099 additions and 71 deletions

View file

@ -1,3 +1,59 @@
2003-06-07 Ulrich Drepper <drepper@redhat.com>
* cleanup_routine.c: New file.
* Versions (libpthread) [GLIBC_2.3.3]: Add __pthread_cleanup_routine.
* sysdeps/pthread/pthread.h: Add support for fully exception-based
cleanup handling.
* Makefile (libpthread-routines): Add cleanup_routine.
Add more CFLAGS variables to compile with exceptions. Add comments
why which file needs unwind tables.
(tests) [have-forced-unwind==yes]: Add tst-cancelx* and tst-cleanupx*
tests.
* tst-cancelx1.c: New file.
* tst-cancelx2.c: New file.
* tst-cancelx3.c: New file.
* tst-cancelx4.c: New file.
* tst-cancelx5.c: New file.
* tst-cancelx6.c: New file.
* tst-cancelx7.c: New file.
* tst-cancelx8.c: New file.
* tst-cancelx9.c: New file.
* tst-cancelx10.c: New file.
* tst-cancelx11.c: New file.
* tst-cancelx12.c: New file.
* tst-cancelx13.c: New file.
* tst-cancelx14.c: New file.
* tst-cancelx15.c: New file.
* tst-cleanupx0.c: New file.
* tst-cleanupx0.expect: New file.
* tst-cleanupx1.c: New file.
* tst-cleanupx2.c: New file.
* tst-cleanupx3.c: New file.
* tst-cleanup0.c: Make standard compliant.
* tst-cleanup1.c: Likewise.
* sysdeps/unix/sysv/linux/sem_timedwait.c: Add cancellation support.
* sysdeps/unix/sysv/linux/sem_wait.c: Likewise.
* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise.
* sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise.
* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise.
* sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise.
* sysdeps/i386/tcb-offsets.sym: Add RESULT, CANCELHANDLING, and
CLEANUP_JMP_BUF.
* sysdeps/x86_64/tcb-offsets.sym: Likewise.
* tst-cancel12.c: New file.
* tst-cancel13.c: New file.
* tst-cancel14.c: New file.
* tst-cancel15.c: New file.
* Makefile (tests): Add tst-cancel12, tst-cancel13, tst-cancel14,
and tst-cancel15.
* tst-cancel1.c: Add some comments.
* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Compute relative
timeout correctly.
2003-06-06 Ulrich Drepper <drepper@redhat.com>
* Makefile (CFLAGS-pthread_cancel.c): Define.

View file

@ -116,7 +116,8 @@ libpthread-routines = init events version \
sigaction \
herrno res pt-allocrtsig \
pthread_kill_other_threads \
pthread_getaffinity pthread_setaffinity
pthread_getaffinity pthread_setaffinity \
cleanup_routine
libpthread-shared-only-routines = version pt-allocrtsig
libpthread-static-only-routines = pthread_atfork
@ -124,16 +125,41 @@ libpthread-static-only-routines = pthread_atfork
libpthread-nonshared = pthread_atfork
CFLAGS-pthread_atfork.c = -DNOT_IN_libc
# Since cancellation handling is in large parts handled using exceptions
# we have to compile some files with exception handling enabled, some
# even with asynchronous unwind tables.
# init.c contains sigcancel_handler().
CFLAGS-init.c = -fexceptions -fasynchronous-unwind-tables
# The unwind code itself,
CFLAGS-unwind.c = -fexceptions
# The following three functions must be async-cancel safe.
CFLAGS-pthread_cancel.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-pthread_setcancelstate.c = -fexceptions -fasynchronous-unwind-tables
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
# be executed. Therefore exceptions have to be thrown through this
# function.
CFLAGS-pthread_exit.c = -fexceptions
# The following are cancellation points. Some of the functions can
# block and therefore temporarily enable asynchronous cancellation.
# Those must be compiled asynchronous unwind tables.
CFLAGS-pthread_testcancel.c = -fexceptions
CFLAGS-pthread_join.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-pthread_timedjoin.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-pthread_cond_wait.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-pthread_cond_timedwait.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-pthread_cancel.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-cancellation.c = -fasynchronous-unwind-tables
CFLAGS-libc-cancellation.c = -fasynchronous-unwind-tables
CFLAGS-sem_wait.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-sem_timedwait.c = -fexceptions -fasynchronous-unwind-tables
# Don't generate deps for calls with no sources. See sysdeps/unix/Makefile.
omit-deps = $(unix-syscalls:%=ptw-%)
@ -165,7 +191,7 @@ tests = tst-attr1 tst-attr2 \
tst-atfork1 \
tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \
tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \
tst-cancel11 \
tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \
tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 \
tst-flock1 tst-flock2 \
tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \
@ -192,6 +218,12 @@ LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst
include ../Makeconfig
ifeq ($(have-forced-unwind),yes)
tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \
tst-cancelx6 tst-cancelx7 tst-cancelx8 tst-cancelx9 tst-cancelx10 \
tst-cancelx11 tst-cancelx12 tst-cancelx13 tst-cancelx14 tst-cancelx15\
tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3
endif
ifeq ($(build-shared),yes)
tests += tst-atfork2 tst-tls3
endif
@ -292,6 +324,23 @@ CFLAGS-pthread_self.os += -fomit-frame-pointer
CFLAGS-tst-unload.c += -DPREFIX=\"$(objpfx)\"
# Run the cancellation and cleanup tests also for the modern, exception-based
# implementation. For this we have to pass the -fexceptions parameter.
CFLAGS-tst-cancelx2.c += -fexceptions
CFLAGS-tst-cancelx3.c += -fexceptions
CFLAGS-tst-cancelx4.c += -fexceptions
CFLAGS-tst-cancelx5.c += -fexceptions
CFLAGS-tst-cancelx6.c += -fexceptions
CFLAGS-tst-cancelx7.c += -fexceptions
CFLAGS-tst-cancelx8.c += -fexceptions
CFLAGS-tst-cancelx9.c += -fexceptions
CFLAGS-tst-cancelx10.c += -fexceptions
CFLAGS-tst-cancelx11.c += -fexceptions
CFLAGS-tst-cleanupx0.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-tst-cleanupx1.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-tst-cleanupx2.c += -fexceptions
CFLAGS-tst-cleanupx3.c += -fexceptions
tst-cancel7-ARGS = --command "$(built-program-cmd)"
tst-umask1-ARGS = $(objpfx)tst-umask1.temp

View file

@ -216,6 +216,7 @@ libpthread {
__pthread_register_cancel; __pthread_unregister_cancel;
__pthread_register_cancel_defer; __pthread_unregister_cancel_restore;
__pthread_unwind_next;
__pthread_cleanup_routine;
# New affinity interfaces.
pthread_getaffinity_np; pthread_setaffinity_np;

28
nptl/cleanup_routine.c Normal file
View file

@ -0,0 +1,28 @@
/* Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <pthread.h>
void
__pthread_cleanup_routine (struct __pthread_cleanup_frame *f)
{
if (f->__do_it)
f->__cancel_routine (f->__cancel_arg);
}

View file

@ -1,7 +1,10 @@
#include <sysdep.h>
#include <tls.h>
RESULT offsetof (struct pthread, result)
TID offsetof (struct pthread, tid)
CANCELHANDLING offsetof (struct pthread, cancelhandling)
CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf)
MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
SYSINFO_OFFSET offsetof (tcbhead_t, sysinfo)
CLEANUP offsetof (struct pthread, cleanup)

View file

@ -419,14 +419,132 @@ typedef struct
#endif
/* Structure to hold the cleanup handler information. */
struct __pthread_cleanup_frame
{
void (*__cancel_routine) (void *);
void *__cancel_arg;
int __do_it;
int __cancel_type;
};
#if defined __GNUC__ && defined __EXCEPTIONS
# ifdef __cplusplus
/* Class to handle cancellation handler invocation. */
class __pthread_cleanup_class
{
void (*__cancel_routine) (void *);
void *__cancel_arg;
int __do_it;
int __cancel_type;
public:
__pthread_cleanup_class (void (*__fct) (void *), void *__arg)
: __cancel_routine (__fct), __cancel_arg (__arg), __do_it (1) { }
~__pthread_cleanup_class () { if (__do_it) __cancel_routine (__cancel_arg); }
__setdoit (int __newval) { __do_it = __newval; }
__defer () { pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED,
&__cancel_type);
__restore () const { pthread_setcanceltype (__cancel_type, 0);
};
/* Install a cleanup handler: ROUTINE will be called with arguments ARG
when the thread is cancelled or calls pthread_exit. ROUTINE will also
when the thread is canceled or calls pthread_exit. ROUTINE will also
be called with arguments ARG when the matching pthread_cleanup_pop
is executed with non-zero EXECUTE argument.
pthread_cleanup_push and pthread_cleanup_pop are macros and must always
be used in matching pairs at the same nesting level of braces. */
#define pthread_cleanup_push(routine, arg) \
# define pthread_cleanup_push(routine, arg) \
do { \
__pthread_cleanup_class __clframe (routine, arg)
/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
If EXECUTE is non-zero, the handler function is called. */
# define pthread_cleanup_pop(execute) \
__clframe.__setdoit (execute); \
} while (0)
# ifdef __USE_GNU
/* Install a cleanup handler as pthread_cleanup_push does, but also
saves the current cancellation type and sets it to deferred
cancellation. */
# define pthread_cleanup_push_defer_np(routine, arg) \
do { \
__pthread_cleanup_class __clframe (routine, arg); \
__clframe.__defer ()
/* Remove a cleanup handler as pthread_cleanup_pop does, but also
restores the cancellation type that was in effect when the matching
pthread_cleanup_push_defer was called. */
# define pthread_cleanup_pop_restore_np(execute) \
__clframe.__restore (); \
__clframe.__setdoit (execute); \
} while (0)
# endif
# else
/* Function called to call the cleanup handler. As an extern inline
function the compiler is free to decide inlining the change when
needed or fall back on the copy which must exist somewhere
else. */
extern inline void
__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame)
{
if (__frame->__do_it)
__frame->__cancel_routine (__frame->__cancel_arg);
}
/* Install a cleanup handler: ROUTINE will be called with arguments ARG
when the thread is canceled or calls pthread_exit. ROUTINE will also
be called with arguments ARG when the matching pthread_cleanup_pop
is executed with non-zero EXECUTE argument.
pthread_cleanup_push and pthread_cleanup_pop are macros and must always
be used in matching pairs at the same nesting level of braces. */
# define pthread_cleanup_push(routine, arg) \
do { \
struct __pthread_cleanup_frame __clframe \
__attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \
= { .__cancel_routine = (routine), .__cancel_arg = (arg), \
.__do_it = 1 };
/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
If EXECUTE is non-zero, the handler function is called. */
# define pthread_cleanup_pop(execute) \
__clframe.__do_it = (execute); \
} while (0)
# ifdef __USE_GNU
/* Install a cleanup handler as pthread_cleanup_push does, but also
saves the current cancellation type and sets it to deferred
cancellation. */
# define pthread_cleanup_push_defer_np(routine, arg) \
do { \
struct __pthread_cleanup_frame __clframe \
__attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \
= { .__cancel_routine = (routine), .__cancel_arg = (arg), \
.__do_it = 1 }; \
(void) pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, \
&__clframe.__cancel_type)
/* Remove a cleanup handler as pthread_cleanup_pop does, but also
restores the cancellation type that was in effect when the matching
pthread_cleanup_push_defer was called. */
# define pthread_cleanup_pop_restore_np(execute) \
(void) pthread_setcanceltype (__clframe.__cancel_type, NULL); \
__clframe.__do_it = (execute); \
} while (0)
# endif
# endif
#else
/* Install a cleanup handler: ROUTINE will be called with arguments ARG
when the thread is canceled or calls pthread_exit. ROUTINE will also
be called with arguments ARG when the matching pthread_cleanup_pop
is executed with non-zero EXECUTE argument.
pthread_cleanup_push and pthread_cleanup_pop are macros and must always
be used in matching pairs at the same nesting level of braces. */
# define pthread_cleanup_push(routine, arg) \
do { \
__pthread_unwind_buf_t __cancel_buf; \
void (*__cancel_routine) (void *) = (routine); \
@ -447,7 +565,7 @@ extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf)
/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
If EXECUTE is non-zero, the handler function is called. */
#define pthread_cleanup_pop(execute) \
# define pthread_cleanup_pop(execute) \
} while (0); \
__pthread_unregister_cancel (&__cancel_buf); \
if (execute) \
@ -456,11 +574,11 @@ extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf)
extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf)
__cleanup_fct_attribute;
#ifdef __USE_GNU
# ifdef __USE_GNU
/* Install a cleanup handler as pthread_cleanup_push does, but also
saves the current cancellation type and sets it to deferred
cancellation. */
# define pthread_cleanup_push_defer(routine, arg) \
# define pthread_cleanup_push_defer_np(routine, arg) \
do { \
__pthread_unwind_buf_t __cancel_buf; \
void (*__cancel_routine) (void *) = (routine); \
@ -482,7 +600,7 @@ extern void __pthread_register_cancel_defer (__pthread_unwind_buf_t *__buf)
/* Remove a cleanup handler as pthread_cleanup_pop does, but also
restores the cancellation type that was in effect when the matching
pthread_cleanup_push_defer was called. */
# define pthread_cleanup_pop_cleanup(execute) \
# define pthread_cleanup_pop_restore_np(execute) \
} while (0); \
__pthread_unregister_cancel_restore (&__cancel_buf); \
if (execute) \
@ -490,15 +608,16 @@ extern void __pthread_register_cancel_defer (__pthread_unwind_buf_t *__buf)
} while (0)
extern void __pthread_unregister_cancel_restore (__pthread_unwind_buf_t *__buf)
__cleanup_fct_attribute;
#endif
# endif
/* Internal interface to initiate cleanup. */
extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
__cleanup_fct_attribute __attribute ((__noreturn__))
#ifndef SHARED
# ifndef SHARED
__attribute ((__weak__))
#endif
# endif
;
#endif
/* Function used in the macros. */
struct __jmp_buf_tag;

View file

@ -37,7 +37,14 @@
.globl sem_timedwait
.type sem_timedwait,@function
.align 16
cfi_startproc
sem_timedwait:
/* First check for cancellation. */
movl %gs:CANCELHANDLING, %eax
andl $0xfffffff9, %eax
cmpl $8, %eax
je 10f
movl 4(%esp), %ecx
movl (%ecx), %eax
@ -54,19 +61,28 @@ sem_timedwait:
/* Check whether the timeout value is valid. */
1: pushl %esi
cfi_adjust_cfa_offset(4)
pushl %edi
cfi_adjust_cfa_offset(4)
pushl %ebx
subl $8, %esp
cfi_adjust_cfa_offset(4)
subl $12, %esp
cfi_adjust_cfa_offset(12)
movl %esp, %esi
movl 28(%esp), %edi
movl 32(%esp), %edi
cfi_offset(7, -12) /* %edi */
/* Check for invalid nanosecond field. */
cmpl $1000000000, 4(%edi)
movl $EINVAL, %eax
movl $EINVAL, %esi
cfi_offset(6, -8) /* %esi */
jae 6f
7: xorl %ecx, %ecx
cfi_offset(3, -16) /* %ebx */
7: call __pthread_enable_asynccancel
movl %eax, 8(%esp)
xorl %ecx, %ecx
movl %esp, %ebx
movl %ecx, %edx
movl $SYS_gettimeofday, %eax
@ -84,20 +100,25 @@ sem_timedwait:
addl $1000000000, %edx
subl $1, %ecx
5: testl %ecx, %ecx
movl $ETIMEDOUT, %eax
movl $ETIMEDOUT, %esi
js 6f /* Time is already up. */
movl %ecx, (%esp) /* Store relative timeout. */
movl %edx, 4(%esp)
movl 24(%esp), %ebx
movl 28(%esp), %ebx
xorl %ecx, %ecx
movl %esp, %esi
movl $SYS_futex, %eax
xorl %edx, %edx
ENTER_KERNEL
movl %eax, %esi
testl %eax, %eax
movl 8(%esp), %eax
call __pthread_disable_asynccancel
testl %esi, %esi
je,pt 9f
cmpl $-EWOULDBLOCK, %eax
cmpl $-EWOULDBLOCK, %esi
jne 3f
9: movl (%ebx), %eax
@ -109,14 +130,27 @@ sem_timedwait:
cmpxchgl %ecx, (%ebx)
jne,pn 8b
addl $8, %esp
addl $12, %esp
cfi_adjust_cfa_offset(-12)
xorl %eax, %eax
popl %ebx
cfi_adjust_cfa_offset(-4)
cfi_restore(3)
popl %edi
cfi_adjust_cfa_offset(-4)
cfi_restore(7)
popl %esi
cfi_adjust_cfa_offset(-4)
cfi_restore(6)
cfi_adjust_cfa_offset(-4)
cfi_restore(6)
ret
3: negl %eax
cfi_adjust_cfa_offset(24)
cfi_offset(6, -8) /* %esi */
cfi_offset(7, -12) /* %edi */
cfi_offset(3, -16) /* %ebx */
3: negl %esi
6:
#ifdef PIC
call __i686.get_pc_thunk.bx
@ -128,17 +162,31 @@ sem_timedwait:
#if USE___THREAD
movl %gs:0, %edx
subl errno@gottpoff(%ebx), %edx
movl %eax, (%edx)
movl %esi, (%edx)
#else
movl %eax, %edx
call __errno_location@plt
movl %edx, (%eax)
movl %esi, (%eax)
#endif
addl $8, %esp
addl $12, %esp
cfi_adjust_cfa_offset(-12)
orl $-1, %eax
popl %ebx
cfi_adjust_cfa_offset(-4)
cfi_restore(3)
popl %edi
cfi_adjust_cfa_offset(-4)
cfi_restore(7)
popl %esi
cfi_adjust_cfa_offset(-4)
cfi_restore(6)
ret
10: /* Canceled. */
movl $0xffffffff, %gs:RESULT
LOCK
orl $0x10, %gs:CANCELHANDLING
movl %gs:CLEANUP_JMP_BUF, %eax
jmp __pthread_unwind
cfi_endproc
.size sem_timedwait,.-sem_timedwait

View file

@ -36,12 +36,25 @@
.globl __new_sem_wait
.type __new_sem_wait,@function
.align 16
cfi_startproc
__new_sem_wait:
/* First check for cancellation. */
movl %gs:CANCELHANDLING, %eax
andl $0xfffffff9, %eax
cmpl $8, %eax
je 5f
pushl %ebx
cfi_adjust_cfa_offset(4)
pushl %esi
cfi_adjust_cfa_offset(4)
subl $4, %esp
cfi_adjust_cfa_offset(4)
movl 12(%esp), %ebx
movl 16(%esp), %ebx
cfi_offset(3, -8) /* %ebx */
cfi_offset(6, -12) /* %esi */
3: movl (%ebx), %eax
2: testl %eax, %eax
je,pn 1f
@ -52,21 +65,35 @@ __new_sem_wait:
jne,pn 2b
xorl %eax, %eax
popl %esi
popl %ebx
movl 4(%esp), %esi
cfi_restore(6)
movl 8(%esp), %ebx
cfi_restore(3)
addl $12, %esp
cfi_adjust_cfa_offset(-12)
ret
1: xorl %esi, %esi
cfi_adjust_cfa_offset(8)
cfi_offset(3, -8) /* %ebx */
cfi_offset(6, -12) /* %esi */
1: call __pthread_enable_asynccancel
movl %eax, (%esp)
xorl %esi, %esi
movl $SYS_futex, %eax
movl %esi, %ecx
movl %esi, %edx
ENTER_KERNEL
movl %eax, %esi
testl %eax, %eax
movl (%esp), %eax
call __pthread_disable_asynccancel
testl %esi, %esi
je 3b
cmpl $-EWOULDBLOCK, %eax
cmpl $-EWOULDBLOCK, %esi
je 3b
negl %eax
negl %esi
#ifdef PIC
call __i686.get_pc_thunk.bx
#else
@ -77,16 +104,27 @@ __new_sem_wait:
#if USE___THREAD
movl %gs:0, %edx
subl errno@gottpoff(%ebx), %edx
movl %eax, (%edx)
movl %esi, (%edx)
#else
movl %eax, %edx
call __errno_location@plt
movl %edx, (%eax)
movl %esi, (%eax)
#endif
orl $-1, %eax
popl %esi
popl %ebx
movl 4(%esp), %esi
cfi_restore(6)
movl 8(%esp), %ebx
cfi_restore(3)
addl $12, %esp
cfi_adjust_cfa_offset(-12)
ret
5: /* Canceled. */
movl $0xffffffff, %gs:RESULT
LOCK
orl $0x10, %gs:CANCELHANDLING
movl %gs:CLEANUP_JMP_BUF, %eax
jmp __pthread_unwind
cfi_endproc
.size __new_sem_wait,.-__new_sem_wait
versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1)
#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)

View file

@ -24,12 +24,16 @@
#include <internaltypes.h>
#include <semaphore.h>
#include <pthreadP.h>
#include <shlib-compat.h>
int
sem_timedwait (sem_t *sem, const struct timespec *abstime)
{
/* First check for cancellation. */
CANCELLATION_P (THREAD_SELF);
int *futex = (int *) sem;
int val;
int err;
@ -71,7 +75,15 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
/* Do wait. */
rt.tv_sec = sec;
rt.tv_nsec = nsec;
/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();
err = lll_futex_timed_wait (futex, 0, &rt);
/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);
if (err != 0 && err != -EWOULDBLOCK)
goto error_return;

View file

@ -24,12 +24,16 @@
#include <internaltypes.h>
#include <semaphore.h>
#include <pthreadP.h>
#include <shlib-compat.h>
int
__new_sem_wait (sem_t *sem)
{
/* First check for cancellation. */
CANCELLATION_P (THREAD_SELF);
int *futex = (int *) sem;
int val;
int err;
@ -43,7 +47,13 @@ __new_sem_wait (sem_t *sem)
return 0;
}
/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();
err = lll_futex_wait (futex, 0);
/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);
}
while (err == 0 || err == -EWOULDBLOCK);

View file

@ -38,7 +38,14 @@
.globl sem_timedwait
.type sem_timedwait,@function
.align 16
cfi_startproc
sem_timedwait:
/* First check for cancellation. */
movl %fs:CANCELHANDLING, %eax
andl $0xfffffff9, %eax
cmpl $8, %eax
je 11f
movl (%rdi), %eax
2: testl %eax, %eax
je 1f
@ -53,18 +60,29 @@ sem_timedwait:
/* Check whether the timeout value is valid. */
1: pushq %r12
cfi_adjust_cfa_offset(8)
pushq %r13
subq $16, %rsp
cfi_adjust_cfa_offset(8)
pushq %r14
cfi_adjust_cfa_offset(8)
subq $24, %rsp
cfi_adjust_cfa_offset(24)
movq %rdi, %r12
cfi_offset(12, -16) /* %r12 */
movq %rsi, %r13
cfi_offset(13, -24) /* %r13 */
/* Check for invalid nanosecond field. */
cmpq $1000000000, 8(%r13)
movl $EINVAL, %eax
movl $EINVAL, %r14d
cfi_offset(14, -24) /* %r14 */
jae 6f
7: xorq %rsi, %rsi
7: call __pthread_enable_asynccancel
movl %eax, 16(%rsp)
xorq %rsi, %rsi
movq %rsp, %rdi
movq $VSYSCALL_ADDR_vgettimeofday, %rax
callq *%rax
@ -74,14 +92,14 @@ sem_timedwait:
movq $1000, %rdi
mul %rdi /* Milli seconds to nano seconds. */
movq (%r13), %rdi
movq 8(%r13), %rdi
movq 8(%r13), %rsi
subq (%rsp), %rdi
subq %rax, %rdi
subq %rax, %rsi
jns 5f
addq $1000000000, %rsi
decq %rdi
5: testq %rdi, %rdi
movl $ETIMEDOUT, %eax
movl $ETIMEDOUT, %r14d
js 6f /* Time is already up. */
movq %rdi, (%rsp) /* Store relative timeout. */
@ -93,38 +111,65 @@ sem_timedwait:
movq $SYS_futex, %rax
xorl %edx, %edx
syscall
movq %rax, %r14
testq %rax, %rax
movl 16(%rsp), %edi
call __pthread_disable_asynccancel
testq %r14, %r14
je 9f
cmpq $-EWOULDBLOCK, %rax
cmpq $-EWOULDBLOCK, %r14
jne 3f
9: movl (%rdi), %eax
9: movl (%r12), %eax
8: testl %eax, %eax
je 7b
leaq -1(%rax), %rcx
LOCK
cmpxchgl %ecx, (%rdi)
cmpxchgl %ecx, (%r12)
jne 8b
xorl %eax, %eax
10: addq $16, %rsp
10: addq $24, %rsp
cfi_adjust_cfa_offset(-24)
popq %r14
cfi_adjust_cfa_offset(-8)
cfi_restore(14)
popq %r13
cfi_adjust_cfa_offset(-8)
cfi_restore(13)
popq %r12
cfi_adjust_cfa_offset(-8)
cfi_restore(12)
retq
3: negq %rax
cfi_adjust_cfa_offset(48)
cfi_offset(12, -16) /* %r12 */
cfi_offset(13, -24) /* %r13 */
cfi_offset(14, -32) /* %r14 */
3: negq %r14
6:
#if USE___THREAD
movq errno@gottpoff(%rip), %rdx
movl %eax, %fs:(%rdx)
movl %r14d, %fs:(%rdx)
#else
movl %eax, %edx
callq __errno_location@plt
movl %edx, (%rax)
movl %r14d, (%rax)
#endif
orl $-1, %eax
jmp 10b
cfi_adjust_cfa_offset(-48)
cfi_restore(14)
cfi_restore(13)
cfi_restore(12)
11: /* Canceled. */
movq $0xffffffffffffffff, %fs:RESULT
LOCK
orl $0x10, %fs:CANCELHANDLING
movq %fs:CLEANUP_JMP_BUF, %rdi
jmp __pthread_unwind
cfi_endproc
.size sem_timedwait,.-sem_timedwait

View file

@ -35,38 +35,86 @@
.globl sem_wait
.type sem_wait,@function
.align 16
cfi_startproc
sem_wait:
3: movl (%rdi), %eax
/* First check for cancellation. */
movl %fs:CANCELHANDLING, %eax
andl $0xfffffff9, %eax
cmpl $8, %eax
je 4f
pushq %r12
cfi_adjust_cfa_offset(8)
cfi_offset(12, -16)
pushq %r13
cfi_adjust_cfa_offset(8)
movq %rdi, %r13
cfi_offset(13, -24)
3: movl (%r13), %eax
2: testl %eax, %eax
je 1f
leaq -1(%rax), %rdx
LOCK
cmpxchgl %edx, (%rdi)
cmpxchgl %edx, (%r13)
jne 2b
xorl %eax, %eax
popq %r13
cfi_adjust_cfa_offset(-8)
cfi_restore(13)
popq %r12
cfi_adjust_cfa_offset(-8)
cfi_restore(12)
retq
1: xorq %r10, %r10
cfi_adjust_cfa_offset(16)
cfi_offset(12, -16)
cfi_offset(13, -24)
1: call __pthread_enable_asynccancel
movl %eax, %r8d
xorq %r10, %r10
movq $SYS_futex, %rax
movq %r13, %rdi
movq %r10, %rsi
movq %r10, %rdx
syscall
movq %rax, %r12
testq %rax, %rax
movl %r8d, %edi
call __pthread_disable_asynccancel
testq %r12, %r12
je 3b
cmpq $-EWOULDBLOCK, %rax
cmpq $-EWOULDBLOCK, %r12
je 3b
negq %rax
negq %r12
#if USE___THREAD
movq errno@gottpoff(%rip), %rdx
movl %eax, %fs:(%rdx)
movl %r12d, %fs:(%rdx)
#else
movl %eax, %edx
callq __errno_location@plt
movl %edx, (%rax)
movl %r12d, (%rax)
#endif
orl $-1, %eax
popq %r13
cfi_adjust_cfa_offset(-8)
cfi_restore(13)
popq %r12
cfi_adjust_cfa_offset(-8)
cfi_restore(12)
retq
4: /* Canceled. */
movq $0xffffffffffffffff, %fs:RESULT
LOCK
orl $0x10, %fs:CANCELHANDLING
movq %fs:CLEANUP_JMP_BUF, %rdi
jmp __pthread_unwind
cfi_endproc
.size sem_wait,.-sem_wait

View file

@ -1,7 +1,10 @@
#include <sysdep.h>
#include <tls.h>
RESULT offsetof (struct pthread, result)
TID offsetof (struct pthread, tid)
CANCELHANDLING offsetof (struct pthread, cancelhandling)
CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf)
CLEANUP offsetof (struct pthread, cleanup)
CLEANUP_PREV offsetof (struct _pthread_cleanup_buffer, __prev)
MUTEX_FUTEX offsetof (pthread_mutex_t, __data.__lock)

View file

@ -63,6 +63,8 @@ tf (void *arg)
printf ("setcanceltype failed: %s\n", strerror (err));
exit (1);
}
/* The following code is not standard compliant: the mutex functions
must not be called with asynchronous cancellation enabled. */
err = pthread_mutex_unlock (&m2);
if (err != 0)

127
nptl/tst-cancel12.c Normal file
View file

@ -0,0 +1,127 @@
/* Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static pthread_barrier_t bar;
static sem_t sem;
static void
cleanup (void *arg)
{
static int ncall;
if (++ncall != 1)
{
puts ("second call to cleanup");
exit (1);
}
printf ("cleanup call #%d\n", ncall);
}
static void *
tf (void *arg)
{
pthread_cleanup_push (cleanup, NULL);
int e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("tf: 1st barrier_wait failed");
exit (1);
}
/* This call should block and be cancelable. */
sem_wait (&sem);
pthread_cleanup_pop (0);
puts ("sem_wait returned");
return NULL;
}
static int
do_test (void)
{
pthread_t th;
if (pthread_barrier_init (&bar, NULL, 2) != 0)
{
puts ("barrier_init failed");
exit (1);
}
if (sem_init (&sem, 0, 1) != 0)
{
puts ("sem_init failed");
exit (1);
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
exit (1);
}
/* Check whether cancellation is honored even before sem_wait does
anything. */
if (pthread_cancel (th) != 0)
{
puts ("1st cancel failed");
exit (1);
}
int e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("1st barrier_wait failed");
exit (1);
}
void *r;
if (pthread_join (th, &r) != 0)
{
puts ("join failed");
exit (1);
}
if (r != PTHREAD_CANCELED)
{
puts ("thread not canceled");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

129
nptl/tst-cancel13.c Normal file
View file

@ -0,0 +1,129 @@
/* Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static pthread_barrier_t bar;
static sem_t sem;
static void
cleanup (void *arg)
{
static int ncall;
if (++ncall != 1)
{
puts ("second call to cleanup");
exit (1);
}
printf ("cleanup call #%d\n", ncall);
}
static void *
tf (void *arg)
{
pthread_cleanup_push (cleanup, NULL);
int e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("tf: 1st barrier_wait failed");
exit (1);
}
/* This call should block and be cancelable. */
sem_wait (&sem);
pthread_cleanup_pop (0);
puts ("sem_wait returned");
return NULL;
}
static int
do_test (void)
{
pthread_t th;
if (pthread_barrier_init (&bar, NULL, 2) != 0)
{
puts ("barrier_init failed");
exit (1);
}
if (sem_init (&sem, 0, 0) != 0)
{
puts ("sem_init failed");
exit (1);
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
exit (1);
}
int e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("1st barrier_wait failed");
exit (1);
}
/* Give the child a chance to go to sleep in sem_wait. */
sleep (1);
/* Check whether cancellation is honored when waiting in sem_wait. */
if (pthread_cancel (th) != 0)
{
puts ("1st cancel failed");
exit (1);
}
void *r;
if (pthread_join (th, &r) != 0)
{
puts ("join failed");
exit (1);
}
if (r != PTHREAD_CANCELED)
{
puts ("thread not canceled");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

136
nptl/tst-cancel14.c Normal file
View file

@ -0,0 +1,136 @@
/* Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static pthread_barrier_t bar;
static sem_t sem;
static void
cleanup (void *arg)
{
static int ncall;
if (++ncall != 1)
{
puts ("second call to cleanup");
exit (1);
}
printf ("cleanup call #%d\n", ncall);
}
static void *
tf (void *arg)
{
pthread_cleanup_push (cleanup, NULL);
int e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("tf: 1st barrier_wait failed");
exit (1);
}
struct timeval tv;
(void) gettimeofday (&tv, NULL);
struct timespec ts;
TIMEVAL_TO_TIMESPEC (&tv, &ts);
/* Timeout in 5 seconds. */
ts.tv_sec += 5;
/* This call should block and be cancelable. */
sem_timedwait (&sem, &ts);
pthread_cleanup_pop (0);
puts ("sem_timedwait returned");
return NULL;
}
static int
do_test (void)
{
pthread_t th;
if (pthread_barrier_init (&bar, NULL, 2) != 0)
{
puts ("barrier_init failed");
exit (1);
}
if (sem_init (&sem, 0, 1) != 0)
{
puts ("sem_init failed");
exit (1);
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
exit (1);
}
/* Check whether cancellation is honored even before sem_timedwait does
anything. */
if (pthread_cancel (th) != 0)
{
puts ("1st cancel failed");
exit (1);
}
int e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("1st barrier_wait failed");
exit (1);
}
void *r;
if (pthread_join (th, &r) != 0)
{
puts ("join failed");
exit (1);
}
if (r != PTHREAD_CANCELED)
{
puts ("thread not canceled");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

141
nptl/tst-cancel15.c Normal file
View file

@ -0,0 +1,141 @@
/* Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static pthread_barrier_t bar;
static sem_t sem;
static void
cleanup (void *arg)
{
static int ncall;
if (++ncall != 1)
{
puts ("second call to cleanup");
exit (1);
}
printf ("cleanup call #%d\n", ncall);
}
static void *
tf (void *arg)
{
int e;
pthread_cleanup_push (cleanup, NULL);
e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("tf: 1st barrier_wait failed");
exit (1);
}
struct timeval tv;
(void) gettimeofday (&tv, NULL);
struct timespec ts;
TIMEVAL_TO_TIMESPEC (&tv, &ts);
/* Timeout in 5 seconds. */
ts.tv_sec += 5;
/* This call should block and be cancelable. */
errno = 0;
e = sem_timedwait (&sem, &ts);
pthread_cleanup_pop (0);
printf ("sem_timedwait returned, e = %d, errno = %d\n", e, errno);
return NULL;
}
static int
do_test (void)
{
pthread_t th;
if (pthread_barrier_init (&bar, NULL, 2) != 0)
{
puts ("barrier_init failed");
exit (1);
}
if (sem_init (&sem, 0, 0) != 0)
{
puts ("sem_init failed");
exit (1);
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
exit (1);
}
int e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("1st barrier_wait failed");
exit (1);
}
/* Give the child a chance to go to sleep in sem_wait. */
sleep (1);
/* Check whether cancellation is honored when waiting in sem_timedwait. */
if (pthread_cancel (th) != 0)
{
puts ("1st cancel failed");
exit (1);
}
void *r;
if (pthread_join (th, &r) != 0)
{
puts ("join failed");
exit (1);
}
if (r != PTHREAD_CANCELED)
{
puts ("thread not canceled");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

1
nptl/tst-cancelx1.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel1.c"

1
nptl/tst-cancelx10.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel10.c"

1
nptl/tst-cancelx11.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel11.c"

1
nptl/tst-cancelx12.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel12.c"

1
nptl/tst-cancelx13.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel13.c"

1
nptl/tst-cancelx14.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel14.c"

1
nptl/tst-cancelx15.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel15.c"

1
nptl/tst-cancelx2.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel2.c"

1
nptl/tst-cancelx3.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel3.c"

1
nptl/tst-cancelx4.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel4.c"

1
nptl/tst-cancelx5.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel5.c"

1
nptl/tst-cancelx6.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel6.c"

1
nptl/tst-cancelx7.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel7.c"

1
nptl/tst-cancelx8.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel8.c"

1
nptl/tst-cancelx9.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cancel9.c"

View file

@ -38,10 +38,20 @@ ch (void *arg)
}
static void
endfct (void)
{
/* We force exit right here. */
_exit (global);
}
static int
do_test (void)
{
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
atexit (endfct);
pthread_cancel (pthread_self ());
pthread_cleanup_push (ch, (void *) 1l);
@ -49,7 +59,7 @@ do_test (void)
pthread_cleanup_push (ch, (void *) 3l);
pthread_cancel (pthread_self ());
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_cleanup_pop (1);
@ -57,9 +67,10 @@ do_test (void)
pthread_cleanup_pop (1);
return 0;
return 100;
}
#define EXPECTED_STATUS 9
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2002 Free Software Foundation, Inc.
/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@ -41,7 +41,7 @@ ch (void *arg)
static void *
tf (void *a)
{
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_cancel (pthread_self ());
pthread_cleanup_push (ch, (void *) 1l);
@ -49,7 +49,7 @@ tf (void *a)
pthread_cleanup_push (ch, (void *) 3l);
pthread_cancel (pthread_self ());
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_cleanup_pop (1);

1
nptl/tst-cleanupx0.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cleanup0.c"

View file

@ -0,0 +1,3 @@
ch (3)
ch (2)
ch (1)

1
nptl/tst-cleanupx1.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cleanup1.c"

1
nptl/tst-cleanupx2.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cleanup2.c"

1
nptl/tst-cleanupx3.c Normal file
View file

@ -0,0 +1 @@
#include "tst-cleanup3.c"