sysdep-cancel.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /* cancellable system calls for Linux/HPPA.
  2. Copyright (C) 2003 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. Contributed by Carlos O'Donell <carlos@baldric.uwo.ca>, 2003.
  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. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; if not, see
  15. <http://www.gnu.org/licenses/>. */
  16. #include <sysdep.h>
  17. #ifndef __ASSEMBLER__
  18. # include <linuxthreads/internals.h>
  19. #endif
  20. #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
  21. # ifndef NO_ERROR
  22. # define NO_ERROR -0x1000
  23. # endif
  24. # undef PSEUDO
  25. # define PSEUDO(name, syscall_name, args) \
  26. ENTRY (name) \
  27. SINGLE_THREAD_P ASM_LINE_SEP \
  28. cmpib,<> 0,%ret0,Lpseudo_cancel ASM_LINE_SEP \
  29. nop ASM_LINE_SEP \
  30. DO_CALL(syscall_name, args) ASM_LINE_SEP \
  31. /* DONE! */ ASM_LINE_SEP \
  32. bv 0(2) ASM_LINE_SEP \
  33. nop ASM_LINE_SEP \
  34. Lpseudo_cancel: ASM_LINE_SEP \
  35. /* store return ptr */ ASM_LINE_SEP \
  36. stw %rp, -20(%sr0,%sp) ASM_LINE_SEP \
  37. /* save syscall args */ ASM_LINE_SEP \
  38. PUSHARGS_##args /* MACRO */ ASM_LINE_SEP \
  39. STW_PIC ASM_LINE_SEP \
  40. CENABLE /* FUNC CALL */ ASM_LINE_SEP \
  41. ldo 64(%sp), %sp ASM_LINE_SEP \
  42. ldo -64(%sp), %sp ASM_LINE_SEP \
  43. LDW_PIC ASM_LINE_SEP \
  44. /* restore syscall args */ ASM_LINE_SEP \
  45. POPARGS_##args ASM_LINE_SEP \
  46. /* save r4 in arg0 stack slot */ ASM_LINE_SEP \
  47. stw %r4, -36(%sr0,%sp) ASM_LINE_SEP \
  48. /* save mask from cenable */ ASM_LINE_SEP \
  49. copy %ret0, %r4 ASM_LINE_SEP \
  50. ble 0x100(%sr2,%r0) ASM_LINE_SEP \
  51. ldi SYS_ify (syscall_name), %r20 ASM_LINE_SEP \
  52. LDW_PIC ASM_LINE_SEP \
  53. /* pass mask as arg0 to cdisable */ ASM_LINE_SEP \
  54. copy %r4, %r26 ASM_LINE_SEP \
  55. copy %ret0, %r4 ASM_LINE_SEP \
  56. CDISABLE ASM_LINE_SEP \
  57. ldo 64(%sp), %sp ASM_LINE_SEP \
  58. ldo -64(%sp), %sp ASM_LINE_SEP \
  59. LDW_PIC ASM_LINE_SEP \
  60. /* compare error */ ASM_LINE_SEP \
  61. ldi NO_ERROR,%r1 ASM_LINE_SEP \
  62. /* branch if no error */ ASM_LINE_SEP \
  63. cmpb,>>=,n %r1,%r4,Lpre_end ASM_LINE_SEP \
  64. nop ASM_LINE_SEP \
  65. SYSCALL_ERROR_HANDLER ASM_LINE_SEP \
  66. ldo 64(%sp), %sp ASM_LINE_SEP \
  67. ldo -64(%sp), %sp ASM_LINE_SEP \
  68. /* No need to LDW_PIC */ ASM_LINE_SEP \
  69. /* make syscall res value positive */ ASM_LINE_SEP \
  70. sub %r0, %r4, %r4 ASM_LINE_SEP \
  71. /* store into errno location */ ASM_LINE_SEP \
  72. stw %r4, 0(%sr0,%ret0) ASM_LINE_SEP \
  73. /* return -1 */ ASM_LINE_SEP \
  74. ldo -1(%r0), %ret0 ASM_LINE_SEP \
  75. Lpre_end: ASM_LINE_SEP \
  76. ldw -20(%sr0,%sp), %rp ASM_LINE_SEP \
  77. /* No need to LDW_PIC */ ASM_LINE_SEP \
  78. ldw -36(%sr0,%sp), %r4 ASM_LINE_SEP
  79. /* Save arguments into our frame */
  80. # define PUSHARGS_0 /* nothing to do */
  81. # define PUSHARGS_1 PUSHARGS_0 stw %r26, -36(%sr0,%sp) ASM_LINE_SEP
  82. # define PUSHARGS_2 PUSHARGS_1 stw %r25, -40(%sr0,%sp) ASM_LINE_SEP
  83. # define PUSHARGS_3 PUSHARGS_2 stw %r24, -44(%sr0,%sp) ASM_LINE_SEP
  84. # define PUSHARGS_4 PUSHARGS_3 stw %r23, -48(%sr0,%sp) ASM_LINE_SEP
  85. # define PUSHARGS_5 PUSHARGS_4 /* Args are on the stack... */
  86. # define PUSHARGS_6 PUSHARGS_5
  87. /* Bring them back from the stack */
  88. # define POPARGS_0 /* nothing to do */
  89. # define POPARGS_1 POPARGS_0 ldw -36(%sr0,%sp), %r26 ASM_LINE_SEP
  90. # define POPARGS_2 POPARGS_1 ldw -40(%sr0,%sp), %r25 ASM_LINE_SEP
  91. # define POPARGS_3 POPARGS_2 ldw -44(%sr0,%sp), %r24 ASM_LINE_SEP
  92. # define POPARGS_4 POPARGS_3 ldw -48(%sr0,%sp), %r23 ASM_LINE_SEP
  93. # define POPARGS_5 POPARGS_4 ldw -52(%sr0,%sp), %r22 ASM_LINE_SEP
  94. # define POPARGS_6 POPARGS_5 ldw -54(%sr0,%sp), %r21 ASM_LINE_SEP
  95. # ifdef IS_IN_libpthread
  96. # ifdef __PIC__
  97. # define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \
  98. bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP
  99. # define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \
  100. bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP
  101. # else
  102. # define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \
  103. bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP
  104. # define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \
  105. bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP
  106. # endif
  107. # elif !defined NOT_IN_libc
  108. # ifdef __PIC__
  109. # define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \
  110. bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP
  111. # define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \
  112. bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP
  113. # else
  114. # define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \
  115. bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP
  116. # define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \
  117. bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP
  118. # endif
  119. # else
  120. # ifdef __PIC__
  121. # define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \
  122. bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP
  123. # define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \
  124. bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP
  125. # else
  126. # define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \
  127. bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP
  128. # define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \
  129. bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP
  130. # endif
  131. # endif
  132. /* p_header.multiple_threads is +12 from the pthread_descr struct start,
  133. We could have called __get_cr27() but we really want less overhead */
  134. # define MULTIPLE_THREADS_OFFSET 0xC
  135. /* cr27 has been initialized to 0x0 by kernel */
  136. # define NO_THREAD_CR27 0x0
  137. # ifdef IS_IN_libpthread
  138. # define __local_multiple_threads __pthread_multiple_threads
  139. # elif !defined NOT_IN_libc
  140. # define __local_multiple_threads __libc_multiple_threads
  141. # else
  142. # define __local_multiple_threads __librt_multiple_threads
  143. # endif
  144. # ifndef __ASSEMBLER__
  145. extern int __local_multiple_threads attribute_hidden;
  146. # define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
  147. # else
  148. /* This ALT version requires newer kernel support */
  149. # define SINGLE_THREAD_P_MFCTL \
  150. mfctl %cr27, %ret0 ASM_LINE_SEP \
  151. cmpib,= NO_THREAD_CR27,%ret0,Lstp ASM_LINE_SEP \
  152. nop ASM_LINE_SEP \
  153. ldw MULTIPLE_THREADS_OFFSET(%sr0,%ret0),%ret0 ASM_LINE_SEP \
  154. Lstp: ASM_LINE_SEP
  155. # ifdef __PIC__
  156. /* Slower version uses GOT to get value of __local_multiple_threads */
  157. # define SINGLE_THREAD_P \
  158. addil LT%__local_multiple_threads, %r19 ASM_LINE_SEP \
  159. ldw RT%__local_multiple_threads(%sr0,%r1), %ret0 ASM_LINE_SEP \
  160. ldw 0(%sr0,%ret0), %ret0 ASM_LINE_SEP
  161. # else
  162. /* Slow non-pic version using DP */
  163. # define SINGLE_THREAD_P \
  164. addil LR%__local_multiple_threads-$global$,%r27 ASM_LINE_SEP \
  165. ldw RR%__local_multiple_threads-$global$(%sr0,%r1),%ret0 ASM_LINE_SEP
  166. # endif
  167. # endif
  168. #elif !defined __ASSEMBLER__
  169. /* This code should never be used but we define it anyhow. */
  170. # define SINGLE_THREAD_P (1)
  171. #endif
  172. /* !defined NOT_IN_libc || defined IS_IN_libpthread */