3 #include "pthread_impl.h"
6 hidden
long __cancel(), __syscall_cp_asm(), __syscall_cp_c();
10 pthread_t self
= __pthread_self();
11 if (self
->canceldisable
== PTHREAD_CANCEL_ENABLE
|| self
->cancelasync
)
12 pthread_exit(PTHREAD_CANCELED
);
13 self
->canceldisable
= PTHREAD_CANCEL_DISABLE
;
17 long __syscall_cp_asm(volatile void *, syscall_arg_t
,
18 syscall_arg_t
, syscall_arg_t
, syscall_arg_t
,
19 syscall_arg_t
, syscall_arg_t
, syscall_arg_t
);
21 long __syscall_cp_c(syscall_arg_t nr
,
22 syscall_arg_t u
, syscall_arg_t v
, syscall_arg_t w
,
23 syscall_arg_t x
, syscall_arg_t y
, syscall_arg_t z
)
29 if ((st
=(self
=__pthread_self())->canceldisable
)
30 && (st
==PTHREAD_CANCEL_DISABLE
|| nr
==SYS_close
))
31 return __syscall(nr
, u
, v
, w
, x
, y
, z
);
33 r
= __syscall_cp_asm(&self
->cancel
, nr
, u
, v
, w
, x
, y
, z
);
34 if (r
==-EINTR
&& nr
!=SYS_close
&& self
->cancel
&&
35 self
->canceldisable
!= PTHREAD_CANCEL_DISABLE
)
40 static void _sigaddset(sigset_t
*set
, int sig
)
43 set
->__bits
[s
/8/sizeof *set
->__bits
] |= 1UL<<(s
&8*sizeof *set
->__bits
-1);
46 extern hidden
const char __cp_begin
[1], __cp_end
[1], __cp_cancel
[1];
48 static void cancel_handler(int sig
, siginfo_t
*si
, void *ctx
)
50 pthread_t self
= __pthread_self();
52 uintptr_t pc
= uc
->uc_mcontext
.MC_PC
;
55 if (!self
->cancel
|| self
->canceldisable
== PTHREAD_CANCEL_DISABLE
) return;
57 _sigaddset(&uc
->uc_sigmask
, SIGCANCEL
);
59 if (self
->cancelasync
) {
60 pthread_sigmask(SIG_SETMASK
, &uc
->uc_sigmask
, 0);
64 if (pc
>= (uintptr_t)__cp_begin
&& pc
< (uintptr_t)__cp_end
) {
65 uc
->uc_mcontext
.MC_PC
= (uintptr_t)__cp_cancel
;
67 uc
->uc_mcontext
.MC_GOT
= CANCEL_GOT
;
72 __syscall(SYS_tkill
, self
->tid
, SIGCANCEL
);
77 pthread_t self
= __pthread_self();
78 if (self
->cancel
&& !self
->canceldisable
)
82 static void init_cancellation()
84 struct sigaction sa
= {
85 .sa_flags
= SA_SIGINFO
| SA_RESTART
| SA_ONSTACK
,
86 .sa_sigaction
= cancel_handler
88 memset(&sa
.sa_mask
, -1, _NSIG
/8);
89 __libc_sigaction(SIGCANCEL
, &sa
, 0);
92 int pthread_cancel(pthread_t t
)
99 a_store(&t
->cancel
, 1);
100 if (t
== pthread_self()) {
101 if (t
->canceldisable
== PTHREAD_CANCEL_ENABLE
&& t
->cancelasync
)
102 pthread_exit(PTHREAD_CANCELED
);
105 return pthread_kill(t
, SIGCANCEL
);