-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include <setjmp.h>
#include <stdlib.h>
#include "pthreadP.h"
-#include "atomic.h"
/* The next two functions are similar to pthread_setcanceltype() but
__pthread_enable_asynccancel (void)
{
struct pthread *self = THREAD_SELF;
- int oldval;
+ int oldval = THREAD_GETMEM (self, cancelhandling);
while (1)
{
- oldval = THREAD_GETMEM (self, cancelhandling);
int newval = oldval | CANCELTYPE_BITMASK;
if (newval == oldval)
break;
- if (atomic_compare_and_exchange_acq (&self->cancelhandling, newval,
- oldval) == 0)
+ int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+ oldval);
+ if (__builtin_expect (curval == oldval, 1))
{
if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
{
break;
}
+
+ /* Prepare the next round. */
+ oldval = curval;
}
return oldval;
return;
struct pthread *self = THREAD_SELF;
+ int newval;
+
+ int oldval = THREAD_GETMEM (self, cancelhandling);
while (1)
{
- int oldval = THREAD_GETMEM (self, cancelhandling);
- int newval = oldval & ~CANCELTYPE_BITMASK;
+ newval = oldval & ~CANCELTYPE_BITMASK;
- if (newval == oldval)
+ int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+ oldval);
+ if (__builtin_expect (curval == oldval, 1))
break;
- if (atomic_compare_and_exchange_acq (&self->cancelhandling, newval,
- oldval) == 0)
- 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);
}
}