1 /* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18 
19 #include "pthreadP.h"
20 
21 
22 void
23 attribute_protected
__pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer,void (* routine)(void *),void * arg)24 __pthread_cleanup_push_defer (
25      struct _pthread_cleanup_buffer *buffer,
26      void (*routine) (void *),
27      void *arg)
28 {
29   struct pthread *self = THREAD_SELF;
30 
31   buffer->__routine = routine;
32   buffer->__arg = arg;
33   buffer->__prev = THREAD_GETMEM (self, cleanup);
34 
35   int cancelhandling = THREAD_GETMEM (self, cancelhandling);
36 
37   /* Disable asynchronous cancellation for now.  */
38   if (__builtin_expect (cancelhandling & CANCELTYPE_BITMASK, 0))
39     while (1)
40       {
41 	int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
42 						cancelhandling
43 						& ~CANCELTYPE_BITMASK,
44 						cancelhandling);
45 	if (__builtin_expect (curval == cancelhandling, 1))
46 	  /* Successfully replaced the value.  */
47 	  break;
48 
49 	/* Prepare for the next round.  */
50 	cancelhandling = curval;
51       }
52 
53   buffer->__canceltype = (cancelhandling & CANCELTYPE_BITMASK
54 			  ? PTHREAD_CANCEL_ASYNCHRONOUS
55 			  : PTHREAD_CANCEL_DEFERRED);
56 
57   THREAD_SETMEM (self, cleanup, buffer);
58 }
strong_alias(__pthread_cleanup_push_defer,_pthread_cleanup_push_defer)59 strong_alias (__pthread_cleanup_push_defer, _pthread_cleanup_push_defer)
60 
61 
62 void
63 attribute_protected
64 __pthread_cleanup_pop_restore (
65      struct _pthread_cleanup_buffer *buffer,
66      int execute)
67 {
68   struct pthread *self = THREAD_SELF;
69 
70   THREAD_SETMEM (self, cleanup, buffer->__prev);
71 
72   int cancelhandling;
73   if (__builtin_expect (buffer->__canceltype != PTHREAD_CANCEL_DEFERRED, 0)
74       && ((cancelhandling = THREAD_GETMEM (self, cancelhandling))
75 	  & CANCELTYPE_BITMASK) == 0)
76     {
77       while (1)
78 	{
79 	  int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
80 						  cancelhandling
81 						  | CANCELTYPE_BITMASK,
82 						  cancelhandling);
83 	  if (__builtin_expect (curval == cancelhandling, 1))
84 	    /* Successfully replaced the value.  */
85 	    break;
86 
87 	  /* Prepare for the next round.  */
88 	  cancelhandling = curval;
89 	}
90 
91       CANCELLATION_P (self);
92     }
93 
94   /* If necessary call the cleanup routine after we removed the
95      current cleanup block from the list.  */
96   if (execute)
97     buffer->__routine (buffer->__arg);
98 }
99 strong_alias (__pthread_cleanup_pop_restore, _pthread_cleanup_pop_restore)
100