sysdep-cancel.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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. cmp r0, -1024 ` \
  37. jls [blink] ` \
  38. b __syscall_error@plt ` \
  39. END(name)
  40. #undef PSEUDO_END
  41. #define PSEUDO_END(name) \
  42. # ifdef IS_IN_libpthread
  43. # define CENABLE bl __pthread_enable_asynccancel
  44. # define CDISABLE bl __pthread_disable_asynccancel
  45. # define __local_multiple_threads __pthread_multiple_threads
  46. # elif !defined NOT_IN_libc
  47. # define CENABLE bl __libc_enable_asynccancel
  48. # define CDISABLE bl __libc_disable_asynccancel
  49. # define __local_multiple_threads __libc_multiple_threads
  50. # elif defined IS_IN_librt
  51. # define CENABLE bl __librt_enable_asynccancel
  52. # define CDISABLE bl __librt_disable_asynccancel
  53. # else
  54. # error Unsupported library
  55. # endif
  56. #define DO_CALL(num) \
  57. mov r8, num ` \
  58. ARC_TRAP_INSN ` \
  59. cmp r0, -1024
  60. .macro push reg
  61. st.a \reg, [sp, -4]
  62. .endm
  63. .macro pop reg
  64. ld.ab \reg, [sp, 4]
  65. .endm
  66. #define DOCARGS_0 push blink
  67. #define UNDOCARGS_0 pop blink
  68. #define DOCARGS_1 DOCARGS_0` push r0
  69. #define UNDOCARGS_1 pop r0` UNDOCARGS_0
  70. #define DOCARGS_2 DOCARGS_1` push r1
  71. #define UNDOCARGS_2 pop r1` UNDOCARGS_1
  72. #define DOCARGS_3 DOCARGS_2` push r2
  73. #define UNDOCARGS_3 pop r2` UNDOCARGS_2
  74. #define DOCARGS_4 DOCARGS_3` push r3
  75. #define UNDOCARGS_4 pop r3` UNDOCARGS_3
  76. #define DOCARGS_5 DOCARGS_4` push r4
  77. #define UNDOCARGS_5 pop r4` UNDOCARGS_4
  78. #define DOCARGS_6 DOCARGS_5` push r5
  79. #define UNDOCARGS_6 pop r5` UNDOCARGS_5
  80. #define DOCARGS_7 DOCARGS_6` push r6
  81. #define UNDOCARGS_7 pop r6` UNDOCARGS_6
  82. # define SINGLE_THREAD_P \
  83. THREAD_SELF r1 ` \
  84. ld r2, [r1, MULTIPLE_THREADS_OFFSET]` \
  85. cmp r2, 0
  86. /* ld r2, [r1, -TLS_PRE_TCB_SIZE + MULTIPLE_THREADS_OFFSET] */
  87. #else /* !__ASSEMBLER__ */
  88. /* TBD: Can use @__local_multiple_threads for libc/libpthread like ARM */
  89. # define SINGLE_THREAD_P \
  90. likely(THREAD_GETMEM (THREAD_SELF, header.multiple_threads) == 0)
  91. #endif /* __ASSEMBLER__ */
  92. #endif