3 #include "pthread_impl.h"
7 __attribute__((__visibility__("hidden")))
8 long __cancel(), __syscall_cp_asm(), __syscall_cp_c();
12 pthread_t self
= __pthread_self();
13 if (self
->canceldisable
== PTHREAD_CANCEL_ENABLE
|| self
->cancelasync
)
14 pthread_exit(PTHREAD_CANCELED
);
15 self
->canceldisable
= PTHREAD_CANCEL_DISABLE
;
19 long __syscall_cp_asm(volatile void *, syscall_arg_t
,
20 syscall_arg_t
, syscall_arg_t
, syscall_arg_t
,
21 syscall_arg_t
, syscall_arg_t
, syscall_arg_t
);
23 long __syscall_cp_c(syscall_arg_t nr
,
24 syscall_arg_t u
, syscall_arg_t v
, syscall_arg_t w
,
25 syscall_arg_t x
, syscall_arg_t y
, syscall_arg_t z
)
31 if ((st
=(self
=__pthread_self())->canceldisable
)
32 && (st
==PTHREAD_CANCEL_DISABLE
|| nr
==SYS_close
))
33 return __syscall(nr
, u
, v
, w
, x
, y
, z
);
35 r
= __syscall_cp_asm(&self
->cancel
, nr
, u
, v
, w
, x
, y
, z
);
36 if (r
==-EINTR
&& nr
!=SYS_close
&& self
->cancel
&&
37 self
->canceldisable
!= PTHREAD_CANCEL_DISABLE
)
42 static void _sigaddset(sigset_t
*set
, int sig
)
45 set
->__bits
[s
/8/sizeof *set
->__bits
] |= 1UL<<(s
&8*sizeof *set
->__bits
-1);
48 __attribute__((__visibility__("hidden")))
49 extern const char __cp_begin
[1], __cp_end
[1], __cp_cancel
[1];
51 static void cancel_handler(int sig
, siginfo_t
*si
, void *ctx
)
53 pthread_t self
= __pthread_self();
55 uintptr_t pc
= uc
->uc_mcontext
.MC_PC
;
58 if (!self
->cancel
|| self
->canceldisable
== PTHREAD_CANCEL_DISABLE
) return;
60 _sigaddset(&uc
->uc_sigmask
, SIGCANCEL
);
62 if (self
->cancelasync
|| pc
>= (uintptr_t)__cp_begin
&& pc
< (uintptr_t)__cp_end
) {
63 uc
->uc_mcontext
.MC_PC
= (uintptr_t)__cp_cancel
;
67 __syscall(SYS_tkill
, self
->tid
, SIGCANCEL
);
72 pthread_t self
= __pthread_self();
73 if (self
->cancel
&& !self
->canceldisable
)
77 static void init_cancellation()
79 struct sigaction sa
= {
80 .sa_flags
= SA_SIGINFO
| SA_RESTART
,
81 .sa_sigaction
= cancel_handler
83 memset(&sa
.sa_mask
, -1, _NSIG
/8);
84 __libc_sigaction(SIGCANCEL
, &sa
, 0);
87 int pthread_cancel(pthread_t t
)
94 a_store(&t
->cancel
, 1);
95 return pthread_kill(t
, SIGCANCEL
);