sysdep-cancel.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /* Copyright (C) 2014-2016 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library. If not, see
  13. <http://www.gnu.org/licenses/>. */
  14. #include <sysdep.h>
  15. #include <tls.h>
  16. #ifndef __ASSEMBLER__
  17. # include <pthreadP.h>
  18. #endif
  19. #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
  20. # if !defined IS_IN_librt || !defined(PIC)
  21. # define AC_STACK_SIZE 16 /* space for r15, async_cancel arg and 2 temp words */
  22. # define AC_SET_GOT /* empty */
  23. # define AC_RESTORE_GOT /* empty */
  24. # else
  25. # define AC_STACK_SIZE 20 /* extra 4 bytes for r20 */
  26. # define AC_SET_GOT \
  27. swi r20, r1, AC_STACK_SIZE-4; \
  28. mfs r20, rpc; \
  29. addik r20, r20, _GLOBAL_OFFSET_TABLE_+8;
  30. # define AC_RESTORE_GOT \
  31. lwi r20, r1, AC_STACK_SIZE-4;
  32. # endif
  33. # undef PSEUDO
  34. # define PSEUDO(name, syscall_name, args) \
  35. .text; \
  36. ENTRY (name) \
  37. SINGLE_THREAD_P(r12); \
  38. bnei r12, L(pseudo_cancel); \
  39. .globl __##syscall_name##_nocancel; \
  40. .type __##syscall_name##_nocancel,@function; \
  41. __##syscall_name##_nocancel: \
  42. DO_CALL (syscall_name, args); \
  43. addik r4, r0, -4095; \
  44. cmpu r4, r4, r3; \
  45. bgei r4, SYSCALL_ERROR_LABEL; \
  46. rtsd r15, 8; \
  47. nop; \
  48. .size __##syscall_name##_nocancel, .-__##syscall_name##_nocancel; \
  49. L(pseudo_cancel): \
  50. addik r1, r1, -AC_STACK_SIZE; \
  51. swi r15, r1, 0; \
  52. AC_SET_GOT \
  53. DOCARGS_##args \
  54. CENABLE; \
  55. swi r3, r1, 8; \
  56. UNDOCARGS_##args \
  57. DO_CALL (syscall_name, args); \
  58. swi r3, r1, 12; \
  59. lwi r5, r1, 8; \
  60. CDISABLE; \
  61. lwi r3, r1, 12; \
  62. lwi r15, r1, 0; \
  63. AC_RESTORE_GOT \
  64. addik r1, r1, AC_STACK_SIZE; \
  65. addik r4, r0, -4095; \
  66. cmpu r4, r4, r3; \
  67. bgei r4, SYSCALL_ERROR_LABEL; \
  68. rtsd r15, 8; \
  69. nop;
  70. /*
  71. * Macros to save/restore syscall arguments across CENABLE
  72. * The arguments are saved into the caller's stack (original r1 + 4)
  73. */
  74. # define DOCARGS_0
  75. # define DOCARGS_1 swi r5, r1, AC_STACK_SIZE + 4;
  76. # define DOCARGS_2 swi r6, r1, AC_STACK_SIZE + 8; DOCARGS_1
  77. # define DOCARGS_3 swi r7, r1, AC_STACK_SIZE + 12; DOCARGS_2
  78. # define DOCARGS_4 swi r8, r1, AC_STACK_SIZE + 16; DOCARGS_3
  79. # define DOCARGS_5 swi r9, r1, AC_STACK_SIZE + 20; DOCARGS_4
  80. # define DOCARGS_6 swi r10, r1, AC_STACK_SIZE + 24; DOCARGS_5
  81. # define UNDOCARGS_0
  82. # define UNDOCARGS_1 lwi r5, r1, AC_STACK_SIZE + 4;
  83. # define UNDOCARGS_2 UNDOCARGS_1 lwi r6, r1, AC_STACK_SIZE + 8;
  84. # define UNDOCARGS_3 UNDOCARGS_2 lwi r7, r1, AC_STACK_SIZE + 12;
  85. # define UNDOCARGS_4 UNDOCARGS_3 lwi r8, r1, AC_STACK_SIZE + 16;
  86. # define UNDOCARGS_5 UNDOCARGS_4 lwi r9, r1, AC_STACK_SIZE + 20;
  87. # define UNDOCARGS_6 UNDOCARGS_5 lwi r10, r1, AC_STACK_SIZE + 24;
  88. # ifdef PIC
  89. # define PSEUDO_JMP(sym) brlid r15, sym##@PLTPC; addk r0, r0, r0
  90. # else
  91. # define PSEUDO_JMP(sym) brlid r15, sym; addk r0, r0, r0
  92. # endif
  93. # if defined IS_IN_libpthread
  94. # define CENABLE PSEUDO_JMP (__pthread_enable_asynccancel)
  95. # define CDISABLE PSEUDO_JMP (__pthread_disable_asynccancel)
  96. # define __local_multiple_threads __pthread_multiple_threads
  97. # elif !defined NOT_IN_libc
  98. # define CENABLE PSEUDO_JMP (__libc_enable_asynccancel)
  99. # define CDISABLE PSEUDO_JMP (__libc_disable_asynccancel)
  100. # define __local_multiple_threads __libc_multiple_threads
  101. # elif defined IS_IN_librt
  102. # define CENABLE PSEUDO_JMP (__librt_enable_asynccancel)
  103. # define CDISABLE PSEUDO_JMP (__librt_disable_asynccancel)
  104. # else
  105. # error Unsupported library
  106. # endif
  107. #if !defined NOT_IN_libc || defined IS_IN_libpthread
  108. # ifndef __ASSEMBLER__
  109. extern int __local_multiple_threads attribute_hidden;
  110. # define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
  111. # else
  112. # if !defined PIC
  113. # define SINGLE_THREAD_P(reg) lwi reg, r0, __local_multiple_threads;
  114. # else
  115. # define SINGLE_THREAD_P(reg) \
  116. mfs reg, rpc; \
  117. addik reg, reg, _GLOBAL_OFFSET_TABLE_+8; \
  118. lwi reg, reg, __local_multiple_threads@GOT; \
  119. lwi reg, reg, 0;
  120. # endif
  121. # endif
  122. # else
  123. # ifndef __ASSEMBLER__
  124. # define SINGLE_THREAD_P \
  125. __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
  126. header.multiple_threads) == 0, 1)
  127. # else
  128. # define SINGLE_THREAD_P(reg) \
  129. lwi reg, r0, MULTIPLE_THREADS_OFFSET(reg)
  130. # endif
  131. # endif
  132. #elif !defined __ASSEMBLER__
  133. # define SINGLE_THREAD_P (1)
  134. # define NO_CANCELLATION (1)
  135. #endif