sysdep-cancel.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
  3. *
  4. * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
  5. */
  6. #include <tls.h>
  7. #include <sysdep.h>
  8. #ifndef __ASSEMBLER__
  9. # include <pthreadP.h>
  10. #endif
  11. #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
  12. #ifdef __ASSEMBLER__
  13. #undef ret
  14. #define ret
  15. # undef PSEUDO
  16. # define PSEUDO(name, syscall_name, nargs) \
  17. /* vanilla version */ ` \
  18. ENTRY(name##_nocancel) ` \
  19. DO_CALL (__NR_##syscall_name) ` \
  20. jls [blink] ` \
  21. b __syscall_error@plt ` \
  22. END(name##_nocancel) ` \
  23. /* thread cancellation variant */ ` \
  24. ENTRY(name) ` \
  25. SINGLE_THREAD_P ` \
  26. bz name##_nocancel ` \
  27. DOCARGS_##nargs /* stash syscall args */ ` \
  28. CENABLE /* call enable_asynccancel */ ` \
  29. mov r9, r0 /* Safe-keep mask */ ` \
  30. UNDOCARGS_##nargs /* restore syscall args */ ` \
  31. DO_CALL (__NR_##syscall_name) ` \
  32. push r0 /* save syscall return value */ ` \
  33. mov r0, r9 /* prep mask for disable_asynccancel */ ` \
  34. CDISABLE ` \
  35. pop r0 /* get syscall ret value back */ ` \
  36. pop blink /* UNDOCARGS above left blink on stack */ ` \
  37. cmp r0, -1024 ` \
  38. jls [blink] ` \
  39. b __syscall_error@plt ` \
  40. END(name)
  41. #undef PSEUDO_END
  42. #define PSEUDO_END(name) \
  43. # ifdef IS_IN_libpthread
  44. # define CENABLE bl __pthread_enable_asynccancel
  45. # define CDISABLE bl __pthread_disable_asynccancel
  46. # define __local_multiple_threads __pthread_multiple_threads
  47. # elif !defined NOT_IN_libc
  48. # define CENABLE bl __libc_enable_asynccancel
  49. # define CDISABLE bl __libc_disable_asynccancel
  50. # define __local_multiple_threads __libc_multiple_threads
  51. # elif defined IS_IN_librt
  52. # define CENABLE bl __librt_enable_asynccancel
  53. # define CDISABLE bl __librt_disable_asynccancel
  54. # else
  55. # error Unsupported library
  56. # endif
  57. #define DO_CALL(num) \
  58. mov r8, num ` \
  59. ARC_TRAP_INSN ` \
  60. cmp r0, -1024
  61. .macro push reg
  62. st.a \reg, [sp, -4]
  63. .endm
  64. .macro pop reg
  65. ld.ab \reg, [sp, 4]
  66. .endm
  67. #define DOCARGS_0 push blink
  68. /* don't pop blink at this point */
  69. #define UNDOCARGS_0 ld blink, [sp]
  70. #define DOCARGS_1 DOCARGS_0` push r0
  71. #define UNDOCARGS_1 pop r0` UNDOCARGS_0
  72. #define DOCARGS_2 DOCARGS_1` push r1
  73. #define UNDOCARGS_2 pop r1` UNDOCARGS_1
  74. #define DOCARGS_3 DOCARGS_2` push r2
  75. #define UNDOCARGS_3 pop r2` UNDOCARGS_2
  76. #define DOCARGS_4 DOCARGS_3` push r3
  77. #define UNDOCARGS_4 pop r3` UNDOCARGS_3
  78. #define DOCARGS_5 DOCARGS_4` push r4
  79. #define UNDOCARGS_5 pop r4` UNDOCARGS_4
  80. #define DOCARGS_6 DOCARGS_5` push r5
  81. #define UNDOCARGS_6 pop r5` UNDOCARGS_5
  82. #define DOCARGS_7 DOCARGS_6` push r6
  83. #define UNDOCARGS_7 pop r6` UNDOCARGS_6
  84. # define SINGLE_THREAD_P \
  85. THREAD_SELF r9 ` \
  86. ld r10, [r9, MULTIPLE_THREADS_OFFSET]` \
  87. cmp r10, 0
  88. /* ld r2, [r1, -TLS_PRE_TCB_SIZE + MULTIPLE_THREADS_OFFSET] */
  89. #else /* !__ASSEMBLER__ */
  90. /* TBD: Can use @__local_multiple_threads for libc/libpthread like ARM */
  91. # define SINGLE_THREAD_P \
  92. likely(THREAD_GETMEM (THREAD_SELF, header.multiple_threads) == 0)
  93. #endif /* __ASSEMBLER__ */
  94. #endif