sysdep-cancel.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /* Copyright (C) 2003-2017 Free Software Foundation, Inc.
  2. The GNU C Library is free software; you can redistribute it and/or
  3. modify it under the terms of the GNU Lesser General Public
  4. License as published by the Free Software Foundation; either
  5. version 2.1 of the License, or (at your option) any later version.
  6. The GNU C Library is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  9. Lesser General Public License for more details.
  10. You should have received a copy of the GNU Lesser General Public
  11. License along with the GNU C Library; if not, see
  12. <http://www.gnu.org/licenses/>. */
  13. #include <sysdep.h>
  14. #include <tls.h>
  15. #ifndef __ASSEMBLER__
  16. # include <pthreadP.h>
  17. #endif
  18. #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
  19. # undef PSEUDO
  20. # define PSEUDO(name, syscall_name, args) \
  21. .section ".text"; \
  22. ENTRY (__##syscall_name##_nocancel); \
  23. .Lpseudo_nocancel: \
  24. DO_CALL (syscall_name, args); \
  25. .Lpseudo_finish: \
  26. cmn x0, 4095; \
  27. b.cs .Lsyscall_error; \
  28. .subsection 2; \
  29. .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
  30. ENTRY (name); \
  31. SINGLE_THREAD_P(16); \
  32. cbz w16, .Lpseudo_nocancel; \
  33. /* Setup common stack frame no matter the number of args. \
  34. Also save the first arg, since it's basically free. */ \
  35. stp x30, x0, [sp, -64]!; \
  36. cfi_adjust_cfa_offset (64); \
  37. cfi_rel_offset (x30, 0); \
  38. DOCARGS_##args; /* save syscall args around CENABLE. */ \
  39. CENABLE; \
  40. mov x16, x0; /* save mask around syscall. */ \
  41. UNDOCARGS_##args; /* restore syscall args. */ \
  42. DO_CALL (syscall_name, args); \
  43. str x0, [sp, 8]; /* save result around CDISABLE. */ \
  44. mov x0, x16; /* restore mask for CDISABLE. */ \
  45. CDISABLE; \
  46. /* Break down the stack frame, restoring result at once. */ \
  47. ldp x30, x0, [sp], 64; \
  48. cfi_adjust_cfa_offset (-64); \
  49. cfi_restore (x30); \
  50. b .Lpseudo_finish; \
  51. cfi_endproc; \
  52. .size name, .-name; \
  53. .previous
  54. # undef PSEUDO_END
  55. # define PSEUDO_END(name) \
  56. SYSCALL_ERROR_HANDLER; \
  57. cfi_endproc
  58. # define DOCARGS_0
  59. # define DOCARGS_1
  60. # define DOCARGS_2 str x1, [sp, 16]
  61. # define DOCARGS_3 stp x1, x2, [sp, 16]
  62. # define DOCARGS_4 DOCARGS_3; str x3, [sp, 32]
  63. # define DOCARGS_5 DOCARGS_3; stp x3, x4, [sp, 32]
  64. # define DOCARGS_6 DOCARGS_5; str x5, [sp, 48]
  65. # define UNDOCARGS_0
  66. # define UNDOCARGS_1 ldr x0, [sp, 8]
  67. # define UNDOCARGS_2 ldp x0, x1, [sp, 8]
  68. # define UNDOCARGS_3 UNDOCARGS_1; ldp x1, x2, [sp, 16]
  69. # define UNDOCARGS_4 UNDOCARGS_2; ldp x2, x3, [sp, 24]
  70. # define UNDOCARGS_5 UNDOCARGS_3; ldp x3, x4, [sp, 32]
  71. # define UNDOCARGS_6 UNDOCARGS_4; ldp x4, x5, [sp, 40]
  72. # if defined IS_IN_libpthread
  73. # define CENABLE bl __pthread_enable_asynccancel
  74. # define CDISABLE bl __pthread_disable_asynccancel
  75. # define __local_multiple_threads __pthread_multiple_threads
  76. # elif !defined NOT_IN_libc
  77. # define CENABLE bl __libc_enable_asynccancel
  78. # define CDISABLE bl __libc_disable_asynccancel
  79. # define __local_multiple_threads __libc_multiple_threads
  80. # elif defined IS_IN_librt
  81. # define CENABLE bl __librt_enable_asynccancel
  82. # define CDISABLE bl __librt_disable_asynccancel
  83. # else
  84. # error Unsupported library
  85. # endif
  86. # if defined IS_IN_libpthread || !defined NOT_IN_libc
  87. # ifndef __ASSEMBLER__
  88. extern int __local_multiple_threads attribute_hidden;
  89. # define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
  90. # else
  91. # define SINGLE_THREAD_P(R) \
  92. adrp x##R, __local_multiple_threads; \
  93. ldr w##R, [x##R, :lo12:__local_multiple_threads]
  94. # endif
  95. # else
  96. /* There is no __local_multiple_threads for librt, so use the TCB. */
  97. # ifndef __ASSEMBLER__
  98. # define SINGLE_THREAD_P \
  99. __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
  100. header.multiple_threads) == 0, 1)
  101. # else
  102. # define SINGLE_THREAD_P(R) \
  103. mrs x##R, tpidr_el0; \
  104. sub x##R, x##R, PTHREAD_SIZEOF; \
  105. ldr w##R, [x##R, PTHREAD_MULTIPLE_THREADS_OFFSET]
  106. # endif
  107. # endif
  108. #elif !defined __ASSEMBLER__
  109. /* For rtld, et cetera. */
  110. # define SINGLE_THREAD_P 1
  111. # define NO_CANCELLATION 1
  112. #endif
  113. #ifndef __ASSEMBLER__
  114. # define RTLD_SINGLE_THREAD_P \
  115. __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
  116. header.multiple_threads) == 0, 1)
  117. #endif