/* Architecture specific code for pthread cancellation handling. Copyright (C) 2023 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see . */ #ifndef _NPTL_CANCELLATION_PC_CHECK #define _NPTL_CANCELLATION_PC_CHECK #include /* For syscalls with side-effects (e.g read that might return partial read), the kernel cannot restart the syscall when interrupted by a signal, it must return from the call with whatever partial result. In this case, the saved program counter is set just after the syscall instruction, so the SIGCANCEL handler should not act on cancellation. The __syscall_cancel_arch function, used for all cancellable syscalls, contains two extra markers, __syscall_cancel_arch_start and __syscall_cancel_arch_end. The former points to just before the initial conditional branch that checks if the thread has received a cancellation request, while former points to the instruction after the one responsible to issue the syscall. The function check if the program counter (PC) from ucontext_t CTX is within the start and then end boundary from the __syscall_cancel_arch bridge. Return TRUE if the PC is within the boundary, meaning the syscall does not have any side effects; or FALSE otherwise. */ static __always_inline bool cancellation_pc_check (void *ctx) { /* Both are defined in syscall_cancel.S. */ extern const char __syscall_cancel_arch_start[1]; extern const char __syscall_cancel_arch_end[1]; uintptr_t pc = sigcontext_get_pc (ctx); return pc >= (uintptr_t) __syscall_cancel_arch_start && pc < (uintptr_t) __syscall_cancel_arch_end; } #endif