public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Florian Weimer <fw@deneb.enyo.de>
To: Adhemerval Zanella via Libc-alpha <libc-alpha@sourceware.org>
Subject: Re: [PATCH 2/3] nptl: Move cancel state out of cancelhandling
Date: Sat, 16 May 2020 20:38:25 +0200	[thread overview]
Message-ID: <87imgvn2se.fsf@mid.deneb.enyo.de> (raw)
In-Reply-To: <20200401142439.1906574-2-adhemerval.zanella@linaro.org> (Adhemerval Zanella via Libc-alpha's message of "Wed, 1 Apr 2020 11:24:38 -0300")

* Adhemerval Zanella via Libc-alpha:

> The thread cancellation state is not accessed concurrently internally
> neither the pthread interface allows changing the state of a different
> thread than its own.
>
> The code is also simplified: the CANCELLATION_P is replaced with a
> internal pthread_testcancel call and the CANCELSTATE_BIT{MASK} is
> removed.
>
> Checked on x86_64-linux-gnu.

Please use the more elaborate commit message.  It is helpful.

> diff --git a/nptl/descr.h b/nptl/descr.h
> index 9dcf480bdf..61665bf859 100644
> --- a/nptl/descr.h
> +++ b/nptl/descr.h

> @@ -394,6 +388,9 @@ struct pthread
>    /* Indicates whether is a C11 thread created by thrd_creat.  */
>    bool c11;
>  
> +  /* Thread cancel state (enable, disable).  */
> +  unsigned char cancelstate;
> +

Please document the permitted values in the comment.

> diff --git a/nptl/pthread_setcancelstate.c b/nptl/pthread_setcancelstate.c
> index 4d7f413e19..aa1c8073a8 100644
> --- a/nptl/pthread_setcancelstate.c
> +++ b/nptl/pthread_setcancelstate.c
> @@ -31,39 +31,9 @@ __pthread_setcancelstate (int state, int *oldstate)
>  
>    self = THREAD_SELF;
>  
> -  int oldval = THREAD_GETMEM (self, cancelhandling);
> -  while (1)
> -    {
> -      int newval = (state == PTHREAD_CANCEL_DISABLE
> -		    ? oldval | CANCELSTATE_BITMASK
> -		    : oldval & ~CANCELSTATE_BITMASK);
> -
> -      /* Store the old value.  */
> -      if (oldstate != NULL)
> -	*oldstate = ((oldval & CANCELSTATE_BITMASK)
> -		     ? PTHREAD_CANCEL_DISABLE : PTHREAD_CANCEL_ENABLE);
> -
> -      /* Avoid doing unnecessary work.  The atomic operation can
> -	 potentially be expensive if the memory has to be locked and
> -	 remote cache lines have to be invalidated.  */
> -      if (oldval == newval)
> -	break;
> -
> -      /* Update the cancel handling word.  This has to be done
> -	 atomically since other bits could be modified as well.  */
> -      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
> -					      oldval);
> -      if (__glibc_likely (curval == oldval))
> -	{
> -	  if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
> -	    __do_cancel ();
> -
> -	  break;
> -	}
> -
> -      /* Prepare for the next round.  */
> -      oldval = curval;
> -    }
> +  if (oldstate != NULL)
> +    *oldstate = self->cancelstate;
> +  self->cancelstate = state;
>  
>    return 0;
>  }

I've re-read the old code and I think this checks for cancellation
even in the absence of a race (i.e., if the CAS succeeds).  I still
think we should preserve this behavior, also for symmetry with this
code below:

> diff --git a/nptl/pthread_setcanceltype.c b/nptl/pthread_setcanceltype.c
> index fcaae8abc7..cc0507ae04 100644
> --- a/nptl/pthread_setcanceltype.c
> +++ b/nptl/pthread_setcanceltype.c
> @@ -53,7 +53,8 @@ __pthread_setcanceltype (int type, int *oldtype)
>  					      oldval);
>        if (__glibc_likely (curval == oldval))
>  	{
> -	  if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
> +	  if (self->cancelstate == PTHREAD_CANCEL_ENABLE
> +	      && CANCEL_CANCELED_AND_ASYNCHRONOUS (newval))
>  	    {
>  	      THREAD_SETMEM (self, result, PTHREAD_CANCELED);
>  	      __do_cancel ();

> diff --git a/nptl/pthread_testcancel.c b/nptl/pthread_testcancel.c
> index 30408c2008..3ffff4ebef 100644
> --- a/nptl/pthread_testcancel.c
> +++ b/nptl/pthread_testcancel.c
> @@ -23,7 +23,16 @@
>  void
>  __pthread_testcancel (void)
>  {
> -  CANCELLATION_P (THREAD_SELF);
> +  struct pthread *self = THREAD_SELF;
> +  int cancelhandling = THREAD_GETMEM (self, cancelhandling);
> +  if (self->cancelstate == PTHREAD_CANCEL_ENABLE
> +      && (cancelhandling & (CANCELED_BITMASK | EXITING_BITMASK
> +			    | TERMINATED_BITMASK))
> +	  == CANCELED_BITMASK)
> +    {
> +      THREAD_SETMEM (self, result, PTHREAD_CANCELED);
> +      __do_cancel ();
> +    }
>  }
>  strong_alias (__pthread_testcancel, pthread_testcancel)
>  hidden_def (__pthread_testcancel)

I think you can write this as 

   self->cancelstate == PTHREAD_CANCEL_ENABLE
   && (cancelhandling & CANCELED_BITMASK)
   && !(cancelhandling & EXITING_BITMASK)
   && !(cancelhandling & TERMINATED_BITMASK)

and GCC will do the right thing.  I find this variant easier to read,
but I don't have a strong preference.

  parent reply	other threads:[~2020-05-16 18:38 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-01 14:24 [PATCH 1/3] nptl: Remove x86_64 cancellation assembly implementations Adhemerval Zanella
2020-04-01 14:24 ` [PATCH 2/3] nptl: Move cancel state out of cancelhandling Adhemerval Zanella
2020-04-16 14:18   ` Adhemerval Zanella
2020-04-22 14:11   ` Florian Weimer
2020-04-23 19:30     ` Adhemerval Zanella
2020-04-24 13:21       ` Florian Weimer
2020-04-30 11:11         ` Adhemerval Zanella
2020-05-12 14:47           ` Adhemerval Zanella
2020-05-12 14:57             ` Florian Weimer
2020-05-16 18:38   ` Florian Weimer [this message]
2020-05-20 14:51     ` Adhemerval Zanella
2020-04-01 14:24 ` [PATCH 3/3] nptl: Move cancel type " Adhemerval Zanella
2020-04-16 14:18   ` Adhemerval Zanella
2020-04-02 12:23 ` [PATCH 1/3] nptl: Remove x86_64 cancellation assembly implementations Adhemerval Zanella
2020-04-02 12:27 ` H.J. Lu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87imgvn2se.fsf@mid.deneb.enyo.de \
    --to=fw@deneb.enyo.de \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).