Unify source for async cancel handling.

Unify all three places where we enable async cancellation for
syscalls.  Optimize a bit.
This commit is contained in:
Ulrich Drepper 2009-05-16 14:55:59 -07:00
parent 7afc8bfcbb
commit cba0ca7925
4 changed files with 12 additions and 189 deletions

View File

@ -1,5 +1,10 @@
2009-05-16 Ulrich Drepper <drepper@redhat.com>
* cancellation.c (__pthread_disable_asynccancel): Remove unnecessary
test.
* libc-cancellation.c: Use <nptl/cancellation.c: to define the code.
* sysdeps/pthread/librt-cancellation.c: Likewise.
[BZ #9924]
* nptl-init.c: Renamed from init.c.
* Makefile: Change all occurences of init.c to nptl-init.c.

View File

@ -78,9 +78,6 @@ __pthread_disable_asynccancel (int oldtype)
{
newval = oldval & ~CANCELTYPE_BITMASK;
if (newval == oldval)
break;
int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
oldval);
if (__builtin_expect (curval == oldval, 1))

View File

@ -17,106 +17,12 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <setjmp.h>
#include <stdlib.h>
#include "pthreadP.h"
#include <atomic.h>
#include <bits/libc-lock.h>
#ifndef NOT_IN_libc
/* The next two functions are similar to pthread_setcanceltype() but
more specialized for the use in the cancelable functions like write().
They do not need to check parameters etc. */
int
attribute_hidden
__libc_enable_asynccancel (void)
{
struct pthread *self = THREAD_SELF;
int oldval = THREAD_GETMEM (self, cancelhandling);
while (1)
{
int newval = oldval | CANCELTYPE_BITMASK;
if (__builtin_expect ((oldval & CANCELED_BITMASK) != 0, 0))
{
/* If we are already exiting or if PTHREAD_CANCEL_DISABLED,
stop right here. */
if ((oldval & (EXITING_BITMASK | CANCELSTATE_BITMASK)) != 0)
break;
int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
newval, oldval);
if (__builtin_expect (curval != oldval, 0))
{
/* Somebody else modified the word, try again. */
oldval = curval;
continue;
}
THREAD_SETMEM (self, result, PTHREAD_CANCELED);
__do_cancel ();
/* NOTREACHED */
}
int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
oldval);
if (__builtin_expect (curval == oldval, 1))
break;
/* Prepare the next round. */
oldval = curval;
}
return oldval;
}
void
internal_function attribute_hidden
__libc_disable_asynccancel (int oldtype)
{
/* If asynchronous cancellation was enabled before we do not have
anything to do. */
if (oldtype & CANCELTYPE_BITMASK)
return;
struct pthread *self = THREAD_SELF;
int newval;
int oldval = THREAD_GETMEM (self, cancelhandling);
while (1)
{
newval = oldval & ~CANCELTYPE_BITMASK;
if (newval == oldval)
break;
int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
oldval);
if (__builtin_expect (curval == oldval, 1))
break;
/* Prepare the next round. */
oldval = curval;
}
/* We cannot return when we are being canceled. Upon return the
thread might be things which would have to be undone. The
following loop should loop until the cancellation signal is
delivered. */
while (__builtin_expect ((newval & (CANCELING_BITMASK | CANCELED_BITMASK))
== CANCELING_BITMASK, 0))
{
lll_futex_wait (&self->cancelhandling, newval, LLL_PRIVATE);
newval = THREAD_GETMEM (self, cancelhandling);
}
}
#define __pthread_enable_asynccancel __libc_enable_asynccancel
#define __pthread_disable_asynccancel __libc_disable_asynccancel
#include <nptl/cancellation.c>
void
@ -125,5 +31,3 @@ __libc_cleanup_routine (struct __pthread_cleanup_frame *f)
if (f->__do_it)
f->__cancel_routine (f->__cancel_arg);
}
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
/* Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@ -17,92 +17,9 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
#include "pthreadP.h"
#include "atomic.h"
#ifdef IS_IN_librt
/* The next two functions are similar to pthread_setcanceltype() but
more specialized for the use in the cancelable functions like write().
They do not need to check parameters etc. */
int
attribute_hidden
__librt_enable_asynccancel (void)
{
struct pthread *self = THREAD_SELF;
int oldval = THREAD_GETMEM (self, cancelhandling);
while (1)
{
int newval = oldval | CANCELTYPE_BITMASK;
if (__builtin_expect ((oldval & CANCELED_BITMASK) != 0, 0))
{
/* If we are already exiting or if PTHREAD_CANCEL_DISABLED,
stop right here. */
if ((oldval & (EXITING_BITMASK | CANCELSTATE_BITMASK)) != 0)
break;
int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
newval, oldval);
if (__builtin_expect (curval != oldval, 0))
{
/* Somebody else modified the word, try again. */
oldval = curval;
continue;
}
THREAD_SETMEM (self, result, PTHREAD_CANCELED);
__do_cancel ();
/* NOTREACHED */
}
int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
oldval);
if (__builtin_expect (curval == oldval, 1))
break;
/* Prepare the next round. */
oldval = curval;
}
return oldval;
}
void
internal_function attribute_hidden
__librt_disable_asynccancel (int oldtype)
{
/* If asynchronous cancellation was enabled before we do not have
anything to do. */
if (oldtype & CANCELTYPE_BITMASK)
return;
struct pthread *self = THREAD_SELF;
int oldval = THREAD_GETMEM (self, cancelhandling);
while (1)
{
int newval = oldval & ~CANCELTYPE_BITMASK;
if (newval == oldval)
break;
int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
oldval);
if (__builtin_expect (curval == oldval, 1))
break;
/* Prepare the next round. */
oldval = curval;
}
}
#endif
#define __pthread_enable_asynccancel __librt_enable_asynccancel
#define __pthread_disable_asynccancel __librt_disable_asynccancel
#include <nptl/cancellation.c>