Просмотр исходного кода

nptl: cancel the current thread directly instead of via SIGCANCEL

When a thread asynchronously cancels itself, pthread_cancel sent
SIGCANCEL to its own tid via tgkill: a syscall plus a kernel-built
signal frame the unwinder then has to step through. When the target is
the calling thread, run __do_cancel() directly as the handler would,
avoiding the self-signal round trip. glibc does the same since 2.39.

Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
ramin 3 дней назад
Родитель
Сommit
5e6fd08b42
1 измененных файлов с 14 добавлено и 0 удалено
  1. 14 0
      libpthread/nptl/pthread_cancel.c

+ 14 - 0
libpthread/nptl/pthread_cancel.c

@@ -59,6 +59,20 @@ pthread_cancel (
 	 expensive.  */
       if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
 	{
+	  /* Cancelling ourselves needs no signal: deliver the cancellation
+	     directly instead of bouncing through tgkill+SIGCANCEL.  This
+	     avoids the syscall, the kernel-built signal frame and the extra
+	     (signal-frame) unwind step.  */
+	  if (pd == (volatile struct pthread *) THREAD_SELF)
+	    {
+	      if (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling,
+							newval, oldval))
+		goto again;
+	      THREAD_SETMEM (THREAD_SELF, result, PTHREAD_CANCELED);
+	      __do_cancel ();
+	      /* NOTREACHED */
+	    }
+
 	  /* Mark the cancellation as "in progress".  */
 	  if (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling,
 						    oldval | CANCELING_BITMASK,