mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
Declare __pthread_unwind. Define __do_cancel to use it. Declare old cleanup handler installation functions.
This commit is contained in:
@ -22,34 +22,26 @@
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_pthread_cleanup_push (buffer, routine, arg)
|
__cleanup_fct_attribute
|
||||||
struct _pthread_cleanup_buffer *buffer;
|
__pthread_register_cancel (__pthread_unwind_buf_t *buf)
|
||||||
void (*routine) (void *);
|
|
||||||
void *arg;
|
|
||||||
{
|
{
|
||||||
|
struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf;
|
||||||
struct pthread *self = THREAD_SELF;
|
struct pthread *self = THREAD_SELF;
|
||||||
|
|
||||||
buffer->__routine = routine;
|
/* Store old info. */
|
||||||
buffer->__arg = arg;
|
ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
|
||||||
buffer->__prev = THREAD_GETMEM (self, cleanup);
|
ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup);
|
||||||
|
|
||||||
THREAD_SETMEM (self, cleanup, buffer);
|
/* Store the new cleanup handler info. */
|
||||||
|
THREAD_SETMEM (self, cleanup_jmp_buf, buf);
|
||||||
}
|
}
|
||||||
strong_alias (_pthread_cleanup_push, __pthread_cleanup_push)
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_pthread_cleanup_pop (buffer, execute)
|
__cleanup_fct_attribute
|
||||||
struct _pthread_cleanup_buffer *buffer;
|
__pthread_unregister_cancel (__pthread_unwind_buf_t *buf)
|
||||||
int execute;
|
|
||||||
{
|
{
|
||||||
struct pthread *self __attribute ((unused)) = THREAD_SELF;
|
struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf;
|
||||||
|
|
||||||
THREAD_SETMEM (self, cleanup, buffer->__prev);
|
THREAD_SETMEM (THREAD_SELF, cleanup_jmp_buf, ibuf->priv.data.prev);
|
||||||
|
|
||||||
/* If necessary call the cleanup routine after we removed the
|
|
||||||
current cleanup block from the list. */
|
|
||||||
if (execute)
|
|
||||||
buffer->__routine (buffer->__arg);
|
|
||||||
}
|
}
|
||||||
strong_alias (_pthread_cleanup_pop, __pthread_cleanup_pop)
|
|
||||||
|
55
nptl/cleanup_compat.c
Normal file
55
nptl/cleanup_compat.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/* 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.
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include "pthreadP.h"
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_pthread_cleanup_push (buffer, routine, arg)
|
||||||
|
struct _pthread_cleanup_buffer *buffer;
|
||||||
|
void (*routine) (void *);
|
||||||
|
void *arg;
|
||||||
|
{
|
||||||
|
struct pthread *self = THREAD_SELF;
|
||||||
|
|
||||||
|
buffer->__routine = routine;
|
||||||
|
buffer->__arg = arg;
|
||||||
|
buffer->__prev = THREAD_GETMEM (self, cleanup);
|
||||||
|
|
||||||
|
THREAD_SETMEM (self, cleanup, buffer);
|
||||||
|
}
|
||||||
|
strong_alias (_pthread_cleanup_push, __pthread_cleanup_push)
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_pthread_cleanup_pop (buffer, execute)
|
||||||
|
struct _pthread_cleanup_buffer *buffer;
|
||||||
|
int execute;
|
||||||
|
{
|
||||||
|
struct pthread *self __attribute ((unused)) = THREAD_SELF;
|
||||||
|
|
||||||
|
THREAD_SETMEM (self, cleanup, buffer->__prev);
|
||||||
|
|
||||||
|
/* If necessary call the cleanup routine after we removed the
|
||||||
|
current cleanup block from the list. */
|
||||||
|
if (execute)
|
||||||
|
buffer->__routine (buffer->__arg);
|
||||||
|
}
|
||||||
|
strong_alias (_pthread_cleanup_pop, __pthread_cleanup_pop)
|
@ -17,20 +17,20 @@
|
|||||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
02111-1307 USA. */
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include "pthreadP.h"
|
#include "pthreadP.h"
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_pthread_cleanup_push_defer (buffer, routine, arg)
|
__cleanup_fct_attribute
|
||||||
struct _pthread_cleanup_buffer *buffer;
|
__pthread_register_cancel_defer (__pthread_unwind_buf_t *buf)
|
||||||
void (*routine) (void *);
|
|
||||||
void *arg;
|
|
||||||
{
|
{
|
||||||
|
struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf;
|
||||||
struct pthread *self = THREAD_SELF;
|
struct pthread *self = THREAD_SELF;
|
||||||
|
|
||||||
buffer->__routine = routine;
|
/* Store old info. */
|
||||||
buffer->__arg = arg;
|
ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
|
||||||
buffer->__prev = THREAD_GETMEM (self, cleanup);
|
ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup);
|
||||||
|
|
||||||
int cancelhandling = THREAD_GETMEM (self, cancelhandling);
|
int cancelhandling = THREAD_GETMEM (self, cancelhandling);
|
||||||
|
|
||||||
@ -38,61 +38,55 @@ _pthread_cleanup_push_defer (buffer, routine, arg)
|
|||||||
if (__builtin_expect (cancelhandling & CANCELTYPE_BITMASK, 0))
|
if (__builtin_expect (cancelhandling & CANCELTYPE_BITMASK, 0))
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int newval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
|
int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
|
||||||
cancelhandling
|
cancelhandling
|
||||||
& ~CANCELTYPE_BITMASK,
|
& ~CANCELTYPE_BITMASK,
|
||||||
cancelhandling);
|
cancelhandling);
|
||||||
if (__builtin_expect (newval == cancelhandling, 1))
|
if (__builtin_expect (curval == cancelhandling, 1))
|
||||||
/* Successfully replaced the value. */
|
/* Successfully replaced the value. */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Prepare for the next round. */
|
/* Prepare for the next round. */
|
||||||
cancelhandling = newval;
|
cancelhandling = curval;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer->__canceltype = (cancelhandling & CANCELTYPE_BITMASK
|
ibuf->priv.data.canceltype = (cancelhandling & CANCELTYPE_BITMASK
|
||||||
? PTHREAD_CANCEL_ASYNCHRONOUS
|
? PTHREAD_CANCEL_ASYNCHRONOUS
|
||||||
: PTHREAD_CANCEL_DEFERRED);
|
: PTHREAD_CANCEL_DEFERRED);
|
||||||
|
|
||||||
THREAD_SETMEM (self, cleanup, buffer);
|
/* Store the new cleanup handler info. */
|
||||||
|
THREAD_SETMEM (self, cleanup_jmp_buf, buf);
|
||||||
}
|
}
|
||||||
strong_alias (_pthread_cleanup_push_defer, __pthread_cleanup_push_defer)
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_pthread_cleanup_pop_restore (buffer, execute)
|
__cleanup_fct_attribute
|
||||||
struct _pthread_cleanup_buffer *buffer;
|
__pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf)
|
||||||
int execute;
|
|
||||||
{
|
{
|
||||||
struct pthread *self = THREAD_SELF;
|
struct pthread *self = THREAD_SELF;
|
||||||
|
struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf;
|
||||||
|
|
||||||
THREAD_SETMEM (self, cleanup, buffer->__prev);
|
THREAD_SETMEM (self, cleanup_jmp_buf, ibuf->priv.data.prev);
|
||||||
|
|
||||||
int cancelhandling;
|
int cancelhandling;
|
||||||
if (__builtin_expect (buffer->__canceltype != PTHREAD_CANCEL_DEFERRED, 0)
|
if (ibuf->priv.data.canceltype != PTHREAD_CANCEL_DEFERRED
|
||||||
&& ((cancelhandling = THREAD_GETMEM (self, cancelhandling))
|
&& ((cancelhandling = THREAD_GETMEM (self, cancelhandling))
|
||||||
& CANCELTYPE_BITMASK) == 0)
|
& CANCELTYPE_BITMASK) == 0)
|
||||||
{
|
{
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int newval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
|
int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
|
||||||
cancelhandling
|
cancelhandling
|
||||||
| CANCELTYPE_BITMASK,
|
| CANCELTYPE_BITMASK,
|
||||||
cancelhandling);
|
cancelhandling);
|
||||||
if (__builtin_expect (newval == cancelhandling, 1))
|
if (__builtin_expect (curval == cancelhandling, 1))
|
||||||
/* Successfully replaced the value. */
|
/* Successfully replaced the value. */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Prepare for the next round. */
|
/* Prepare for the next round. */
|
||||||
cancelhandling = newval;
|
cancelhandling = curval;
|
||||||
}
|
}
|
||||||
|
|
||||||
CANCELLATION_P (self);
|
CANCELLATION_P (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If necessary call the cleanup routine after we removed the
|
|
||||||
current cleanup block from the list. */
|
|
||||||
if (execute)
|
|
||||||
buffer->__routine (buffer->__arg);
|
|
||||||
}
|
}
|
||||||
strong_alias (_pthread_cleanup_pop_restore, __pthread_cleanup_pop_restore)
|
|
||||||
|
98
nptl/cleanup_defer_compat.c
Normal file
98
nptl/cleanup_defer_compat.c
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/* 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.
|
||||||
|
|
||||||
|
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 "pthreadP.h"
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_pthread_cleanup_push_defer (buffer, routine, arg)
|
||||||
|
struct _pthread_cleanup_buffer *buffer;
|
||||||
|
void (*routine) (void *);
|
||||||
|
void *arg;
|
||||||
|
{
|
||||||
|
struct pthread *self = THREAD_SELF;
|
||||||
|
|
||||||
|
buffer->__routine = routine;
|
||||||
|
buffer->__arg = arg;
|
||||||
|
buffer->__prev = THREAD_GETMEM (self, cleanup);
|
||||||
|
|
||||||
|
int cancelhandling = THREAD_GETMEM (self, cancelhandling);
|
||||||
|
|
||||||
|
/* Disable asynchronous cancellation for now. */
|
||||||
|
if (__builtin_expect (cancelhandling & CANCELTYPE_BITMASK, 0))
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
|
||||||
|
cancelhandling
|
||||||
|
& ~CANCELTYPE_BITMASK,
|
||||||
|
cancelhandling);
|
||||||
|
if (__builtin_expect (curval == cancelhandling, 1))
|
||||||
|
/* Successfully replaced the value. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Prepare for the next round. */
|
||||||
|
cancelhandling = curval;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->__canceltype = (cancelhandling & CANCELTYPE_BITMASK
|
||||||
|
? PTHREAD_CANCEL_ASYNCHRONOUS
|
||||||
|
: PTHREAD_CANCEL_DEFERRED);
|
||||||
|
|
||||||
|
THREAD_SETMEM (self, cleanup, buffer);
|
||||||
|
}
|
||||||
|
strong_alias (_pthread_cleanup_push_defer, __pthread_cleanup_push_defer)
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_pthread_cleanup_pop_restore (buffer, execute)
|
||||||
|
struct _pthread_cleanup_buffer *buffer;
|
||||||
|
int execute;
|
||||||
|
{
|
||||||
|
struct pthread *self = THREAD_SELF;
|
||||||
|
|
||||||
|
THREAD_SETMEM (self, cleanup, buffer->__prev);
|
||||||
|
|
||||||
|
int cancelhandling;
|
||||||
|
if (__builtin_expect (buffer->__canceltype != PTHREAD_CANCEL_DEFERRED, 0)
|
||||||
|
&& ((cancelhandling = THREAD_GETMEM (self, cancelhandling))
|
||||||
|
& CANCELTYPE_BITMASK) == 0)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
|
||||||
|
cancelhandling
|
||||||
|
| CANCELTYPE_BITMASK,
|
||||||
|
cancelhandling);
|
||||||
|
if (__builtin_expect (curval == cancelhandling, 1))
|
||||||
|
/* Successfully replaced the value. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Prepare for the next round. */
|
||||||
|
cancelhandling = curval;
|
||||||
|
}
|
||||||
|
|
||||||
|
CANCELLATION_P (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If necessary call the cleanup routine after we removed the
|
||||||
|
current cleanup block from the list. */
|
||||||
|
if (execute)
|
||||||
|
buffer->__routine (buffer->__arg);
|
||||||
|
}
|
||||||
|
strong_alias (_pthread_cleanup_pop_restore, __pthread_cleanup_pop_restore)
|
50
nptl/descr.h
50
nptl/descr.h
@ -32,6 +32,9 @@
|
|||||||
#include <dl-sysdep.h>
|
#include <dl-sysdep.h>
|
||||||
#include "../nptl_db/thread_db.h"
|
#include "../nptl_db/thread_db.h"
|
||||||
#include <tls.h>
|
#include <tls.h>
|
||||||
|
#ifdef HAVE_FORCED_UNWIND
|
||||||
|
# include <unwind.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef TCB_ALIGNMENT
|
#ifndef TCB_ALIGNMENT
|
||||||
@ -54,6 +57,45 @@
|
|||||||
/ PTHREAD_KEY_2NDLEVEL_SIZE)
|
/ PTHREAD_KEY_2NDLEVEL_SIZE)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Internal version of the buffer to store cancellation handler
|
||||||
|
information. */
|
||||||
|
struct pthread_unwind_buf
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
/* This is the placeholder of the public version. */
|
||||||
|
void *pad[16];
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* Backward compatibility: state of the old-style cleanup
|
||||||
|
handler at the time of the previous new-style cleanup handler
|
||||||
|
installment. */
|
||||||
|
struct _pthread_cleanup_buffer *cleanup;
|
||||||
|
|
||||||
|
/* Cancellation type before the push call. */
|
||||||
|
int canceltype;
|
||||||
|
} data;
|
||||||
|
} priv;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
__jmp_buf jmp_buf;
|
||||||
|
int mask_was_saved;
|
||||||
|
} cancel_jmp_buf[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Thread descriptor data structure. */
|
/* Thread descriptor data structure. */
|
||||||
struct pthread
|
struct pthread
|
||||||
{
|
{
|
||||||
@ -86,6 +128,10 @@ struct pthread
|
|||||||
/* List of cleanup buffers. */
|
/* List of cleanup buffers. */
|
||||||
struct _pthread_cleanup_buffer *cleanup;
|
struct _pthread_cleanup_buffer *cleanup;
|
||||||
|
|
||||||
|
/* Unwind information. */
|
||||||
|
__pthread_unwind_buf_t *cleanup_jmp_buf;
|
||||||
|
#define HAVE_CLEANUP_JMP_BUF
|
||||||
|
|
||||||
/* Flags determining processing of cancellation. */
|
/* Flags determining processing of cancellation. */
|
||||||
int cancelhandling;
|
int cancelhandling;
|
||||||
/* Bit set if cancellation is disabled. */
|
/* Bit set if cancellation is disabled. */
|
||||||
@ -160,10 +206,6 @@ struct pthread
|
|||||||
/* Check whether a thread is detached. */
|
/* Check whether a thread is detached. */
|
||||||
#define IS_DETACHED(pd) ((pd)->joinid == (pd))
|
#define IS_DETACHED(pd) ((pd)->joinid == (pd))
|
||||||
|
|
||||||
/* Setjmp buffer to be used if try/finally is not available. */
|
|
||||||
sigjmp_buf cancelbuf;
|
|
||||||
#define HAVE_CANCELBUF 1
|
|
||||||
|
|
||||||
/* Flags. Including those copied from the thread attribute. */
|
/* Flags. Including those copied from the thread attribute. */
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
|
@ -19,10 +19,12 @@
|
|||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <pthreadP.h>
|
#include <pthreadP.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <shlib-compat.h>
|
#include <shlib-compat.h>
|
||||||
#include <atomic.h>
|
#include <atomic.h>
|
||||||
|
#include <sysdep.h>
|
||||||
|
|
||||||
|
|
||||||
/* Pointers to the libc functions. */
|
/* Pointers to the libc functions. */
|
||||||
@ -170,3 +172,11 @@ FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate),
|
|||||||
0)
|
0)
|
||||||
|
|
||||||
FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0)
|
FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0)
|
||||||
|
|
||||||
|
FORWARD2(__pthread_unwind,
|
||||||
|
void attribute_hidden __attribute ((noreturn)) __cleanup_fct_attribute,
|
||||||
|
(__pthread_unwind_buf_t *buf), (buf), {
|
||||||
|
/* We cannot call abort() here. */
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
INTERNAL_SYSCALL (kill, err, 1, SIGKILL);
|
||||||
|
})
|
||||||
|
@ -121,7 +121,8 @@ static struct pthread_functions pthread_functions =
|
|||||||
.ptr___pthread_setspecific = __pthread_setspecific_internal,
|
.ptr___pthread_setspecific = __pthread_setspecific_internal,
|
||||||
.ptr__pthread_cleanup_push_defer = __pthread_cleanup_push_defer,
|
.ptr__pthread_cleanup_push_defer = __pthread_cleanup_push_defer,
|
||||||
.ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore,
|
.ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore,
|
||||||
.ptr_nthreads = &__nptl_nthreads
|
.ptr_nthreads = &__nptl_nthreads,
|
||||||
|
.ptr___pthread_unwind = &__pthread_unwind
|
||||||
};
|
};
|
||||||
# define ptr_pthread_functions &pthread_functions
|
# define ptr_pthread_functions &pthread_functions
|
||||||
#else
|
#else
|
||||||
|
@ -94,6 +94,29 @@ extern int __pthread_debug attribute_hidden;
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
extern void __pthread_unwind (__pthread_unwind_buf_t *__buf)
|
||||||
|
__cleanup_fct_attribute __attribute ((__noreturn__))
|
||||||
|
#ifndef SHARED
|
||||||
|
weak_function
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Called when a thread reacts on a cancellation request. */
|
||||||
|
static inline void
|
||||||
|
__attribute ((noreturn))
|
||||||
|
__do_cancel (void)
|
||||||
|
{
|
||||||
|
struct pthread *self = THREAD_SELF;
|
||||||
|
|
||||||
|
/* Make sure we get no more cancellations. */
|
||||||
|
THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
|
||||||
|
|
||||||
|
__pthread_unwind ((__pthread_unwind_buf_t *)
|
||||||
|
THREAD_GETMEM (self, cleanup_jmp_buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Set cancellation mode to asynchronous. */
|
/* Set cancellation mode to asynchronous. */
|
||||||
#define CANCEL_ASYNC() \
|
#define CANCEL_ASYNC() \
|
||||||
__pthread_enable_asynccancel ()
|
__pthread_enable_asynccancel ()
|
||||||
@ -143,38 +166,6 @@ extern int __pthread_debug attribute_hidden;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* This function is responsible for calling all registered cleanup
|
|
||||||
handlers and then terminate the thread. This includes dellocating
|
|
||||||
the thread-specific data. The implementation is complicated by the
|
|
||||||
fact that we have to handle to cancellation handler registration
|
|
||||||
methods: exceptions using try/finally and setjmp.
|
|
||||||
|
|
||||||
The setjmp method is always available. The user might compile some
|
|
||||||
code which uses this method because no modern compiler is
|
|
||||||
available. So we have to handle these first since we cannot call
|
|
||||||
the cleanup handlers if the stack frames are gone. At the same
|
|
||||||
time this opens a hole for the register exception handler blocks
|
|
||||||
since now they might be in danger of using an overwritten stack
|
|
||||||
frame. The advise is to only use new or only old style cancellation
|
|
||||||
handling. */
|
|
||||||
static inline void
|
|
||||||
__do_cancel (void)
|
|
||||||
{
|
|
||||||
struct pthread *self = THREAD_SELF;
|
|
||||||
|
|
||||||
/* Make sure we get no more cancellations. */
|
|
||||||
THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
|
|
||||||
|
|
||||||
/* Throw an exception. */
|
|
||||||
// XXX TBI
|
|
||||||
|
|
||||||
/* If throwing an exception didn't work try the longjmp. */
|
|
||||||
__libc_longjmp (self->cancelbuf, 1);
|
|
||||||
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Internal prototypes. */
|
/* Internal prototypes. */
|
||||||
|
|
||||||
/* Thread list handling. */
|
/* Thread list handling. */
|
||||||
@ -344,7 +335,6 @@ extern int __pthread_cond_wait_2_0 (pthread_cond_2_0_t *cond,
|
|||||||
pthread_mutex_t *mutex);
|
pthread_mutex_t *mutex);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* The two functions are in libc.so and not exported. */
|
/* The two functions are in libc.so and not exported. */
|
||||||
extern int __libc_enable_asynccancel (void) attribute_hidden;
|
extern int __libc_enable_asynccancel (void) attribute_hidden;
|
||||||
extern void __libc_disable_asynccancel (int oldtype)
|
extern void __libc_disable_asynccancel (int oldtype)
|
||||||
@ -372,4 +362,14 @@ extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer
|
|||||||
extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
|
extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
|
||||||
int execute);
|
int execute);
|
||||||
|
|
||||||
|
/* Old cleanup interfaces, still used in libc.so. */
|
||||||
|
extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
|
||||||
|
void (*routine) (void *), void *arg);
|
||||||
|
extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
|
||||||
|
int execute);
|
||||||
|
extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
|
||||||
|
void (*routine) (void *), void *arg);
|
||||||
|
extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
|
||||||
|
int execute);
|
||||||
|
|
||||||
#endif /* pthreadP.h */
|
#endif /* pthreadP.h */
|
||||||
|
3
nptl/tst-cleanup0.expect
Normal file
3
nptl/tst-cleanup0.expect
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
ch (3)
|
||||||
|
ch (2)
|
||||||
|
ch (1)
|
Reference in New Issue
Block a user