Support cancellation in librt.
[kopensolaris-gnu/glibc.git] / linuxthreads / sysdeps / unix / sysv / linux / ia64 / sysdep-cancel.h
1 /* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <sysdep.h>
21 #include <tls.h>
22 #ifndef __ASSEMBLER__
23 # include <linuxthreads/internals.h>
24 #endif
25
26 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
27
28 # undef PSEUDO
29 # define PSEUDO(name, syscall_name, args)                                     \
30 .text;                                                                        \
31 ENTRY (name)                                                                  \
32      adds r14 = MULTIPLE_THREADS_OFFSET, r13;;                                \
33      ld4 r14 = [r14];                                                         \
34      mov r15 = SYS_ify(syscall_name);;                                        \
35      cmp4.ne p6, p7 = 0, r14;                                                 \
36 (p6) br.cond.spnt .Lpseudo_cancel;;                                           \
37      break __BREAK_SYSCALL;;                                                  \
38      cmp.eq p6,p0=-1,r10;                                                     \
39 (p6) br.cond.spnt.few __syscall_error;                                        \
40      ret;;                                                                    \
41 .Lpseudo_cancel:                                                              \
42      .prologue;                                                               \
43      .regstk args, 5, args, 0;                                                \
44      .save ar.pfs, loc0;                                                      \
45      alloc loc0 = ar.pfs, args, 5, args, 0;                                   \
46      .save rp, loc1;                                                          \
47      mov loc1 = rp;;                                                          \
48      .body;                                                                   \
49      CENABLE;;                                                                \
50      mov loc2 = r8;                                                           \
51      COPY_ARGS_##args                                                         \
52      mov r15 = SYS_ify(syscall_name);                                         \
53      break __BREAK_SYSCALL;;                                                  \
54      mov loc3 = r8;                                                           \
55      mov loc4 = r10;                                                          \
56      mov out0 = loc2;                                                         \
57      CDISABLE;;                                                               \
58      cmp.eq p6,p0=-1,loc4;                                                    \
59 (p6) br.cond.spnt.few __syscall_error_##args;                                 \
60      mov r8 = loc3;                                                           \
61      mov rp = loc1;                                                           \
62      mov ar.pfs = loc0;                                                       \
63 .Lpseudo_end:                                                                 \
64      ret;                                                                     \
65      .endp name;                                                              \
66 .section .gnu.linkonce.t.__syscall_error_##args, "ax";                        \
67      .align 32;                                                               \
68      .proc __syscall_error_##args;                                            \
69      .global __syscall_error_##args;                                          \
70      .hidden __syscall_error_##args;                                          \
71 __syscall_error_##args:                                                       \
72      .prologue;                                                               \
73      .regstk args, 5, args, 0;                                                \
74      .save ar.pfs, loc0;                                                      \
75      .save rp, loc1;                                                          \
76      .body;                                                                   \
77      mov loc4 = r1;;                                                          \
78      br.call.sptk.many b0 = __errno_location;;                                \
79      st4 [r8] = loc3;                                                         \
80      mov r1 = loc4;                                                           \
81      mov rp = loc1;                                                           \
82      mov r8 = -1;                                                             \
83      mov ar.pfs = loc0
84
85 # ifdef IS_IN_libpthread
86 #  define CENABLE       br.call.sptk.many b0 = __pthread_enable_asynccancel
87 #  define CDISABLE      br.call.sptk.many b0 = __pthread_disable_asynccancel
88 # elif !defined NOT_IN_libc
89 #  define CENABLE       br.call.sptk.many b0 = __libc_enable_asynccancel
90 #  define CDISABLE      br.call.sptk.many b0 = __libc_disable_asynccancel
91 # else
92 #  define CENABLE       br.call.sptk.many b0 = __librt_enable_asynccancel
93 #  define CDISABLE      br.call.sptk.many b0 = __librt_disable_asynccancel
94 # endif
95
96 #define COPY_ARGS_0     /* Nothing */
97 #define COPY_ARGS_1     COPY_ARGS_0 mov out0 = in0;
98 #define COPY_ARGS_2     COPY_ARGS_1 mov out1 = in1;
99 #define COPY_ARGS_3     COPY_ARGS_2 mov out2 = in2;
100 #define COPY_ARGS_4     COPY_ARGS_3 mov out3 = in3;
101 #define COPY_ARGS_5     COPY_ARGS_4 mov out4 = in4;
102 #define COPY_ARGS_6     COPY_ARGS_5 mov out5 = in5;
103 #define COPY_ARGS_7     COPY_ARGS_6 mov out6 = in6;
104
105 # ifndef __ASSEMBLER__
106 #  define SINGLE_THREAD_P \
107   __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1)
108 # else
109 #  define SINGLE_THREAD_P \
110   adds r14 = MULTIPLE_THREADS_OFFSET, r13 ;; ld4 r14 = [r14] ;; cmp4.ne p6, p7 = 0, r14
111 # endif
112
113 #elif !defined __ASSEMBLER__
114
115 /* This code should never be used but we define it anyhow.  */
116 # define SINGLE_THREAD_P (1)
117
118 #endif