Back to index

glibc  2.9
librt-cancellation.c
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <setjmp.h>
00021 #include <signal.h>
00022 #include <stdlib.h>
00023 #include "pthreadP.h"
00024 #include "atomic.h"
00025 
00026 
00027 #ifdef IS_IN_librt
00028 /* The next two functions are similar to pthread_setcanceltype() but
00029    more specialized for the use in the cancelable functions like write().
00030    They do not need to check parameters etc.  */
00031 int
00032 attribute_hidden
00033 __librt_enable_asynccancel (void)
00034 {
00035   struct pthread *self = THREAD_SELF;
00036   int oldval = THREAD_GETMEM (self, cancelhandling);
00037 
00038   while (1)
00039     {
00040       int newval = oldval | CANCELTYPE_BITMASK;
00041 
00042       if (__builtin_expect ((oldval & CANCELED_BITMASK) != 0, 0))
00043        {
00044          /* If we are already exiting or if PTHREAD_CANCEL_DISABLED,
00045             stop right here.  */
00046          if ((oldval & (EXITING_BITMASK | CANCELSTATE_BITMASK)) != 0)
00047            break;
00048 
00049          int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
00050                                             newval, oldval);
00051          if (__builtin_expect (curval != oldval, 0))
00052            {
00053              /* Somebody else modified the word, try again.  */
00054              oldval = curval;
00055              continue;
00056            }
00057 
00058          THREAD_SETMEM (self, result, PTHREAD_CANCELED);
00059 
00060          __do_cancel ();
00061 
00062          /* NOTREACHED */
00063        }
00064 
00065       int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
00066                                          oldval);
00067       if (__builtin_expect (curval == oldval, 1))
00068        break;
00069 
00070       /* Prepare the next round.  */
00071       oldval = curval;
00072     }
00073 
00074   return oldval;
00075 }
00076 
00077 
00078 void
00079 internal_function attribute_hidden
00080 __librt_disable_asynccancel (int oldtype)
00081 {
00082   /* If asynchronous cancellation was enabled before we do not have
00083      anything to do.  */
00084   if (oldtype & CANCELTYPE_BITMASK)
00085     return;
00086 
00087   struct pthread *self = THREAD_SELF;
00088   int oldval = THREAD_GETMEM (self, cancelhandling);
00089 
00090   while (1)
00091     {
00092       int newval = oldval & ~CANCELTYPE_BITMASK;
00093 
00094       if (newval == oldval)
00095        break;
00096 
00097       int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
00098                                          oldval);
00099       if (__builtin_expect (curval == oldval, 1))
00100        break;
00101 
00102       /* Prepare the next round.  */
00103       oldval = curval;
00104     }
00105 }
00106 
00107 
00108 #endif