sysdep-cancel.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /* Copyright (C) 2014 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. # undef PSEUDO
  21. # define PSEUDO(name, syscall_name, args) \
  22. ENTRY(__##syscall_name##_nocancel); \
  23. L(pseudo_nocancel): \
  24. DO_CALL(syscall_name); \
  25. l.j L(pseudo_finish); \
  26. l.nop; \
  27. END(__##syscall_name##_nocancel); \
  28. ENTRY(name); \
  29. SINGLE_THREAD_P(r13); \
  30. l.sfeq r13,r0; \
  31. l.bnf L(pseudo_nocancel); \
  32. l.nop; \
  33. /* Reserve the same amount of stack space, effectivly disregarding \
  34. * how many args we're supposed to push. This makes the code easier. */ \
  35. l.addi r1,r1,-28; \
  36. cfi_adjust_cfa_offset(28); \
  37. PUSHARGS_##args; /* CENABLE is a function call, save args for syscall. */ \
  38. CENABLE; \
  39. l.sw 24(r1),r11; \
  40. POPARGS_##args; \
  41. DO_CALL(syscall_name); \
  42. l.lwz r3,24(r1); /* pass return value from CENABLE to CDISABLE. */ \
  43. l.sw 24(r1),r11; /* save syscall return value for after CDISABLE. */ \
  44. CDISABLE; \
  45. l.lwz r11,24(r1); /* restore syscall return value. */ \
  46. cfi_adjust_cfa_offset(-28); \
  47. l.addi r1,r1,28; \
  48. L(pseudo_finish): \
  49. /* if -4096 < ret < 0 holds, it's an error */ \
  50. l.sfgeui r11,0xf001; \
  51. l.bf L(pseudo_end); \
  52. l.nop
  53. # undef PSEUDO_END
  54. # define PSEUDO_END(name) \
  55. L(pseudo_end): \
  56. l.j SYSCALL_ERROR_NAME; \
  57. l.ori r3,r11,0; \
  58. END(name)
  59. # define PUSHARGS_0 /* nothing to do */
  60. # define PUSHARGS_1 PUSHARGS_0 l.sw 0(r1),r3;
  61. # define PUSHARGS_2 PUSHARGS_1 l.sw 4(r1),r4;
  62. # define PUSHARGS_3 PUSHARGS_2 l.sw 8(r1),r5;
  63. # define PUSHARGS_4 PUSHARGS_3 l.sw 12(r1),r6;
  64. # define PUSHARGS_5 PUSHARGS_4 l.sw 16(r1),r7;
  65. # define PUSHARGS_6 PUSHARGS_5 l.sw 20(r1),r8;
  66. # define POPARGS_0 /* nothing to do */
  67. # define POPARGS_1 POPARGS_0 l.lwz r3,0(r1);
  68. # define POPARGS_2 POPARGS_1 l.lwz r4,4(r1);
  69. # define POPARGS_3 POPARGS_2 l.lwz r5,8(r1);
  70. # define POPARGS_4 POPARGS_3 l.lwz r6,12(r1);
  71. # define POPARGS_5 POPARGS_4 l.lwz r7,16(r1);
  72. # define POPARGS_6 POPARGS_5 l.lwz r8,20(r1);
  73. # define PSEUDO_JMP(sym) l.jal sym; l.nop;
  74. # ifdef IS_IN_libpthread
  75. # define CENABLE PSEUDO_JMP (__pthread_enable_asynccancel)
  76. # define CDISABLE PSEUDO_JMP (__pthread_disable_asynccancel)
  77. # elif defined IS_IN_librt
  78. # define CENABLE PSEUDO_JMP (__librt_enable_asynccancel)
  79. # define CDISABLE PSEUDO_JMP (__librt_disable_asynccancel)
  80. # else
  81. # define CENABLE PSEUDO_JMP (__libc_enable_asynccancel)
  82. # define CDISABLE PSEUDO_JMP (__libc_disable_asynccancel)
  83. # endif
  84. # ifndef __ASSEMBLER__
  85. # define SINGLE_THREAD_P \
  86. __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
  87. header.multiple_threads) == 0, 1)
  88. # else
  89. /* It's not super nice to have "r10" hardcoded here */
  90. # define SINGLE_THREAD_P(reg) l.lwz reg, MULTIPLE_THREADS_OFFSET(r10)
  91. #endif
  92. #elif !defined __ASSEMBLER__
  93. # define SINGLE_THREAD_P 1
  94. # define NO_CANCELLATION 1
  95. #endif
  96. #ifndef __ASSEMBLER__
  97. # define RTLD_SINGLE_THREAD_P \
  98. __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
  99. header.multiple_threads) == 0, 1)
  100. #endif