context.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #pragma once
  2. #include "align.h"
  3. #include "defaults.h"
  4. #include "compiler.h"
  5. #include <util/generic/array_ref.h>
  6. #include <util/generic/utility.h>
  7. #include <util/generic/yexception.h>
  8. #define STACK_ALIGN (8 * PLATFORM_DATA_ALIGN)
  9. #if defined(_x86_64_) || defined(_i386_) || defined(_arm_) || defined(_ppc64_)
  10. #define STACK_GROW_DOWN 1
  11. #else
  12. #error todo
  13. #endif
  14. #if defined(__clang_major__) && (__clang_major__ >= 9) && (defined(_asan_enabled_) || defined(_tsan_enabled_))
  15. #include "sanitizers.h"
  16. #define USE_SANITIZER_CONTEXT
  17. #endif
  18. /*
  19. * switch method
  20. */
  21. #if defined(thread_sanitizer_enabled) && defined(_darwin_)
  22. #define _XOPEN_SOURCE 700
  23. #pragma clang diagnostic push
  24. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  25. #endif
  26. #if defined(_bionic_) || defined(__IOS__)
  27. #define USE_GENERIC_CONT
  28. #elif defined(_cygwin_)
  29. #define USE_UCONTEXT_CONT
  30. #elif defined(_win_)
  31. #define USE_FIBER_CONT
  32. #elif (defined(_i386_) || defined(_x86_64_) || defined(_arm64_)) && !defined(_k1om_)
  33. #define USE_JUMP_CONT
  34. #else
  35. #define USE_UCONTEXT_CONT
  36. #endif
  37. #if defined(USE_JUMP_CONT)
  38. #if defined(_arm64_)
  39. #include "context_aarch64.h"
  40. #else
  41. #include "context_x86.h"
  42. #endif
  43. #endif
  44. #if defined(USE_UCONTEXT_CONT)
  45. #include <ucontext.h>
  46. #endif
  47. struct ITrampoLine {
  48. virtual ~ITrampoLine() = default;
  49. virtual void DoRun();
  50. virtual void DoRunNaked();
  51. };
  52. struct TContClosure {
  53. ITrampoLine* TrampoLine;
  54. TArrayRef<char> Stack;
  55. const char* ContName = nullptr;
  56. };
  57. #if defined(USE_UCONTEXT_CONT)
  58. class TContMachineContext {
  59. typedef void (*ucontext_func_t)(void);
  60. public:
  61. inline TContMachineContext() {
  62. getcontext(&Ctx_);
  63. }
  64. inline TContMachineContext(const TContClosure& c) {
  65. getcontext(&Ctx_);
  66. Ctx_.uc_link = 0;
  67. Ctx_.uc_stack.ss_sp = (void*)c.Stack.data();
  68. Ctx_.uc_stack.ss_size = c.Stack.size();
  69. Ctx_.uc_stack.ss_flags = 0;
  70. extern void ContextTrampoLine(void* arg);
  71. makecontext(&Ctx_, (ucontext_func_t)ContextTrampoLine, 1, c.TrampoLine);
  72. }
  73. inline ~TContMachineContext() {
  74. }
  75. inline void SwitchTo(TContMachineContext* next) noexcept {
  76. swapcontext(&Ctx_, &next->Ctx_);
  77. }
  78. private:
  79. ucontext_t Ctx_;
  80. };
  81. #endif
  82. #if defined(USE_GENERIC_CONT)
  83. class TContMachineContext {
  84. struct TImpl;
  85. public:
  86. TContMachineContext();
  87. TContMachineContext(const TContClosure& c);
  88. ~TContMachineContext();
  89. void SwitchTo(TContMachineContext* next) noexcept;
  90. private:
  91. THolder<TImpl> Impl_;
  92. };
  93. #endif
  94. #if defined(USE_FIBER_CONT)
  95. class TContMachineContext {
  96. public:
  97. TContMachineContext();
  98. TContMachineContext(const TContClosure& c);
  99. ~TContMachineContext();
  100. void SwitchTo(TContMachineContext* next) noexcept;
  101. private:
  102. void* Fiber_;
  103. bool MainFiber_;
  104. };
  105. #endif
  106. #if defined(USE_JUMP_CONT)
  107. class TContMachineContext {
  108. public:
  109. inline TContMachineContext() {
  110. Zero(Buf_);
  111. }
  112. TContMachineContext(const TContClosure& c);
  113. inline ~TContMachineContext() = default;
  114. void SwitchTo(TContMachineContext* next) noexcept;
  115. private:
  116. __myjmp_buf Buf_;
  117. #if defined(USE_SANITIZER_CONTEXT)
  118. struct TSan: public ITrampoLine, public ::NSan::TFiberContext {
  119. TSan() noexcept;
  120. TSan(const TContClosure& c) noexcept;
  121. void DoRunNaked() override;
  122. ITrampoLine* TL;
  123. };
  124. TSan San_;
  125. #endif
  126. };
  127. #endif
  128. static inline size_t MachineContextSize() noexcept {
  129. return sizeof(TContMachineContext);
  130. }
  131. /*
  132. * be polite
  133. */
  134. #if !defined(FROM_CONTEXT_IMPL)
  135. #undef USE_SANITIZER_CONTEXT
  136. #undef USE_JUMP_CONT
  137. #undef USE_FIBER_CONT
  138. #undef USE_GENERIC_CONT
  139. #undef USE_UCONTEXT_CONT
  140. #undef PROGR_CNT
  141. #undef STACK_CNT
  142. #undef EXTRA_PUSH_ARGS
  143. #endif
  144. #if defined(_darwin_) && defined(thread_sanitizer_enabled)
  145. #pragma clang diagnostic pop
  146. #undef _XOPEN_SOURCE
  147. #endif
  148. struct TExceptionSafeContext: public TContMachineContext {
  149. using TContMachineContext::TContMachineContext;
  150. void SwitchTo(TExceptionSafeContext* to) noexcept;
  151. #if defined(_unix_)
  152. void* Buf_[2] = {nullptr, nullptr};
  153. #endif
  154. };