1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
/* Pthread cancellation syscall bridge. Default Linux version.
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
<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;
}
|