Blame nptl/pthread_setcanceltype.c

Packit Service 82fcde
/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <errno.h>
Packit Service 82fcde
#include "pthreadP.h"
Packit Service 82fcde
#include <atomic.h>
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
__pthread_setcanceltype (int type, int *oldtype)
Packit Service 82fcde
{
Packit Service 82fcde
  if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS)
Packit Service 82fcde
    return EINVAL;
Packit Service 82fcde
Packit Service 82fcde
#ifndef SIGCANCEL
Packit Service 82fcde
  if (type == PTHREAD_CANCEL_ASYNCHRONOUS)
Packit Service 82fcde
    return ENOTSUP;
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
  volatile struct pthread *self = THREAD_SELF;
Packit Service 82fcde
Packit Service 82fcde
  int oldval = THREAD_GETMEM (self, cancelhandling);
Packit Service 82fcde
  while (1)
Packit Service 82fcde
    {
Packit Service 82fcde
      int newval = (type == PTHREAD_CANCEL_ASYNCHRONOUS
Packit Service 82fcde
		    ? oldval | CANCELTYPE_BITMASK
Packit Service 82fcde
		    : oldval & ~CANCELTYPE_BITMASK);
Packit Service 82fcde
Packit Service 82fcde
      /* Store the old value.  */
Packit Service 82fcde
      if (oldtype != NULL)
Packit Service 82fcde
	*oldtype = ((oldval & CANCELTYPE_BITMASK)
Packit Service 82fcde
		    ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED);
Packit Service 82fcde
Packit Service 82fcde
      /* Avoid doing unnecessary work.  The atomic operation can
Packit Service 82fcde
	 potentially be expensive if the memory has to be locked and
Packit Service 82fcde
	 remote cache lines have to be invalidated.  */
Packit Service 82fcde
      if (oldval == newval)
Packit Service 82fcde
	break;
Packit Service 82fcde
Packit Service 82fcde
      /* Update the cancel handling word.  This has to be done
Packit Service 82fcde
	 atomically since other bits could be modified as well.  */
Packit Service 82fcde
      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
Packit Service 82fcde
					      oldval);
Packit Service 82fcde
      if (__glibc_likely (curval == oldval))
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
Packit Service 82fcde
	    {
Packit Service 82fcde
	      THREAD_SETMEM (self, result, PTHREAD_CANCELED);
Packit Service 82fcde
	      __do_cancel ();
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  break;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      /* Prepare for the next round.  */
Packit Service 82fcde
      oldval = curval;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
strong_alias (__pthread_setcanceltype, pthread_setcanceltype)