context.h 4.0 KB

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