(root)/
glibc-2.38/
nptl/
cleanup_defer.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 <stdlib.h>
      19  #include "pthreadP.h"
      20  #include <shlib-compat.h>
      21  
      22  void
      23  __cleanup_fct_attribute
      24  ___pthread_register_cancel_defer (__pthread_unwind_buf_t *buf)
      25  {
      26    struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf;
      27    struct pthread *self = THREAD_SELF;
      28  
      29    /* Store old info.  */
      30    ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
      31    ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup);
      32  
      33    int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
      34    if (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK))
      35      {
      36        int newval;
      37        do
      38  	{
      39  	  newval = cancelhandling & ~CANCELTYPE_BITMASK;
      40  	}
      41        while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
      42  						    &cancelhandling,
      43  						    newval));
      44      }
      45  
      46    ibuf->priv.data.canceltype = (cancelhandling & CANCELTYPE_BITMASK
      47  				? PTHREAD_CANCEL_ASYNCHRONOUS
      48  				: PTHREAD_CANCEL_DEFERRED);
      49  
      50    /* Store the new cleanup handler info.  */
      51    THREAD_SETMEM (self, cleanup_jmp_buf, (struct pthread_unwind_buf *) buf);
      52  }
      53  versioned_symbol (libc, ___pthread_register_cancel_defer,
      54  		  __pthread_register_cancel_defer, GLIBC_2_34);
      55  
      56  #if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_34)
      57  compat_symbol (libpthread, ___pthread_register_cancel_defer,
      58  	       __pthread_register_cancel_defer, GLIBC_2_3_3);
      59  #endif
      60  
      61  void
      62  __cleanup_fct_attribute
      63  ___pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf)
      64  {
      65    struct pthread *self = THREAD_SELF;
      66    struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf;
      67  
      68    THREAD_SETMEM (self, cleanup_jmp_buf, ibuf->priv.data.prev);
      69  
      70    if (ibuf->priv.data.canceltype == PTHREAD_CANCEL_DEFERRED)
      71      return;
      72  
      73    int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
      74    if ((cancelhandling & CANCELTYPE_BITMASK) == 0)
      75      {
      76        int newval;
      77        do
      78  	{
      79  	  newval = cancelhandling | CANCELTYPE_BITMASK;
      80  	}
      81        while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
      82  						    &cancelhandling, newval));
      83  
      84        if (cancel_enabled_and_canceled (cancelhandling))
      85  	{
      86  	  self->result = PTHREAD_CANCELED;
      87  	  __do_cancel ();
      88  	}
      89      }
      90  }
      91  versioned_symbol (libc, ___pthread_unregister_cancel_restore,
      92  		  __pthread_unregister_cancel_restore, GLIBC_2_34);
      93  
      94  #if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_34)
      95  compat_symbol (libpthread, ___pthread_unregister_cancel_restore,
      96  	       __pthread_unregister_cancel_restore, GLIBC_2_3_3);
      97  #endif