(root)/
glibc-2.38/
nptl/
libc-cleanup.c
       1  /* Copyright (C) 2002-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include "pthreadP.h"
      19  #include <tls.h>
      20  #include <libc-lock.h>
      21  
      22  void
      23  __libc_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer)
      24  {
      25    struct pthread *self = THREAD_SELF;
      26  
      27    buffer->__prev = THREAD_GETMEM (self, cleanup);
      28  
      29    int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
      30  
      31    /* Disable asynchronous cancellation for now.  */
      32    if (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK))
      33      {
      34        int newval;
      35        do
      36  	{
      37  	  newval = cancelhandling & ~CANCELTYPE_BITMASK;
      38  	}
      39        while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
      40  						    &cancelhandling,
      41  						    newval));
      42      }
      43  
      44    buffer->__canceltype = (cancelhandling & CANCELTYPE_BITMASK
      45  			  ? PTHREAD_CANCEL_ASYNCHRONOUS
      46  			  : PTHREAD_CANCEL_DEFERRED);
      47  
      48    THREAD_SETMEM (self, cleanup, buffer);
      49  }
      50  libc_hidden_def (__libc_cleanup_push_defer)
      51  
      52  void
      53  __libc_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer)
      54  {
      55    struct pthread *self = THREAD_SELF;
      56  
      57    THREAD_SETMEM (self, cleanup, buffer->__prev);
      58  
      59    int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
      60    if (buffer->__canceltype != PTHREAD_CANCEL_DEFERRED
      61        && (cancelhandling & CANCELTYPE_BITMASK) == 0)
      62      {
      63        int newval;
      64        do
      65  	{
      66  	  newval = cancelhandling | CANCELTYPE_BITMASK;
      67  	}
      68        while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
      69  						    &cancelhandling, newval));
      70  
      71        if (cancel_enabled_and_canceled (cancelhandling))
      72  	{
      73  	  self->result = PTHREAD_CANCELED;
      74  	  __do_cancel ();
      75  	}
      76      }
      77  }
      78  libc_hidden_def (__libc_cleanup_pop_restore)