Back to index

glibc  2.9
libc-cancellation.c
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003, 2005 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 <stdlib.h>
00022 #include "pthreadP.h"
00023 #include <atomic.h>
00024 #include <bits/libc-lock.h>
00025 
00026 
00027 #ifndef NOT_IN_libc
00028 
00029 /* The next two functions are similar to pthread_setcanceltype() but
00030    more specialized for the use in the cancelable functions like write().
00031    They do not need to check parameters etc.  */
00032 int
00033 attribute_hidden
00034 __libc_enable_asynccancel (void)
00035 {
00036   struct pthread *self = THREAD_SELF;
00037   int oldval = THREAD_GETMEM (self, cancelhandling);
00038 
00039   while (1)
00040     {
00041       int newval = oldval | CANCELTYPE_BITMASK;
00042 
00043       if (__builtin_expect ((oldval & CANCELED_BITMASK) != 0, 0))
00044        {
00045          /* If we are already exiting or if PTHREAD_CANCEL_DISABLED,
00046             stop right here.  */
00047          if ((oldval & (EXITING_BITMASK | CANCELSTATE_BITMASK)) != 0)
00048            break;
00049 
00050          int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
00051                                             newval, oldval);
00052          if (__builtin_expect (curval != oldval, 0))
00053            {
00054              /* Somebody else modified the word, try again.  */
00055              oldval = curval;
00056              continue;
00057            }
00058 
00059          THREAD_SETMEM (self, result, PTHREAD_CANCELED);
00060 
00061          __do_cancel ();
00062 
00063          /* NOTREACHED */
00064        }
00065 
00066       int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
00067                                          oldval);
00068       if (__builtin_expect (curval == oldval, 1))
00069        break;
00070 
00071       /* Prepare the next round.  */
00072       oldval = curval;
00073     }
00074 
00075   return oldval;
00076 }
00077 
00078 
00079 void
00080 internal_function attribute_hidden
00081 __libc_disable_asynccancel (int oldtype)
00082 {
00083   /* If asynchronous cancellation was enabled before we do not have
00084      anything to do.  */
00085   if (oldtype & CANCELTYPE_BITMASK)
00086     return;
00087 
00088   struct pthread *self = THREAD_SELF;
00089   int oldval = THREAD_GETMEM (self, cancelhandling);
00090 
00091   while (1)
00092     {
00093       int newval = oldval & ~CANCELTYPE_BITMASK;
00094 
00095       if (newval == oldval)
00096        break;
00097 
00098       int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
00099                                          oldval);
00100       if (__builtin_expect (curval == oldval, 1))
00101        break;
00102 
00103       /* Prepare the next round.  */
00104       oldval = curval;
00105     }
00106 }
00107 
00108 
00109 void
00110 __libc_cleanup_routine (struct __pthread_cleanup_frame *f)
00111 {
00112   if (f->__do_it)
00113     f->__cancel_routine (f->__cancel_arg);
00114 }
00115 
00116 #endif