mirror of
https://sourceware.org/git/glibc.git
synced 2025-04-23 10:27:48 +03:00
74 lines
3.1 KiB
C
74 lines
3.1 KiB
C
/* Pthread cancellation syscall bridge. Default Linux version.
|
|
Copyright (C) 2023-2025 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
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#include <sysdep.h>
|
|
#include <pthreadP.h>
|
|
|
|
#warning "This implementation should be use just as reference or for bootstrapping"
|
|
|
|
/* This is the generic version of the cancellable syscall code which
|
|
adds the label guards (__syscall_cancel_arch_{start,end}) used on SIGCANCEL
|
|
handler to check if the cancelled syscall have side-effects that need to be
|
|
returned to the caller.
|
|
|
|
This implementation should be used as a reference one to document the
|
|
implementation constraints:
|
|
|
|
1. The __syscall_cancel_arch_start should point just before the test
|
|
that thread is already cancelled,
|
|
2. The __syscall_cancel_arch_end should point to the immediate next
|
|
instruction after the syscall one.
|
|
3. It should return the syscall value or a negative result if is has
|
|
failed, similar to INTERNAL_SYSCALL_CALL.
|
|
|
|
The __syscall_cancel_arch_end one is because the kernel will signal
|
|
interrupted syscall with side effects by setting the signal frame program
|
|
counter (on the ucontext_t third argument from SA_SIGINFO signal handler)
|
|
right after the syscall instruction.
|
|
|
|
For some architecture, the INTERNAL_SYSCALL_NCS macro use more instructions
|
|
to get the error condition from kernel (as for powerpc and sparc that
|
|
checks for the conditional register), or uses an out of the line helper
|
|
(ARM thumb), or uses a kernel helper gate (i686 or ia64). In this case
|
|
the architecture should either adjust the macro or provide a custom
|
|
__syscall_cancel_arch implementation. */
|
|
|
|
long int
|
|
__syscall_cancel_arch (volatile int *ch, __syscall_arg_t nr,
|
|
__syscall_arg_t a1, __syscall_arg_t a2,
|
|
__syscall_arg_t a3, __syscall_arg_t a4,
|
|
__syscall_arg_t a5, __syscall_arg_t a6
|
|
__SYSCALL_CANCEL7_ARG_DEF)
|
|
{
|
|
#define ADD_LABEL(__label) \
|
|
asm volatile ( \
|
|
".global " __label "\t\n" \
|
|
__label ":\n");
|
|
|
|
ADD_LABEL ("__syscall_cancel_arch_start");
|
|
if (__glibc_unlikely (*ch & CANCELED_BITMASK))
|
|
__syscall_do_cancel();
|
|
|
|
long int result = INTERNAL_SYSCALL_NCS_CALL (nr, a1, a2, a3, a4, a5, a6
|
|
__SYSCALL_CANCEL7_ARG7);
|
|
ADD_LABEL ("__syscall_cancel_arch_end");
|
|
if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result)))
|
|
return -INTERNAL_SYSCALL_ERRNO (result);
|
|
return result;
|
|
}
|