context_switcher.cpp 1.91 KB
Newer Older
1
#include "context_switcher/context_switcher.h"
2

3
#ifdef THREAD_SANITIZER
4
#include "context_switcher/tsan_support.h"
5 6
#endif

7 8
namespace context_switcher {

9
#ifdef CS_USE_CSCONTEXT
10
continuation switch_context(continuation &&cont) {
11 12 13 14
  continuation_t cont_pointer = cont.consume();
  continuation_t result = cscontext::__cs_switch_context(cont_pointer);
  return continuation{result};
}
15 16
#endif
#if defined(CS_USE_FCONTEXT) and not defined(THREAD_SANITIZER)
17 18
continuation switch_context(continuation &&cont) {
  continuation_t cont_pointer = cont.consume();
19 20
  fcontext::transfer_t transfer = fcontext::jump_fcontext(cont_pointer, (void *) 1);

21
  if (transfer.data) {
22
    return continuation{transfer.continuation};
23
  } else {
24
    return continuation{nullptr};
25 26
  }
}
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#endif
#ifdef THREAD_SANITIZER
std::mutex cache_mtx{};
std::unordered_map<char *, cached_fiber> cached_fibers{};

void context_loop(fcontext::transfer_t initial_transfer) {
  continuation successor = continuation{initial_transfer.continuation, initial_transfer.data};
  do {
    continuation_t cont_pointer = successor.consume();
    __tsan_switch_to_fiber(successor.get_tsan_fiber(), 0);
    fcontext::transfer_t transfer = fcontext::jump_fcontext(cont_pointer, nullptr);

    auto *user_code = static_cast<lambda_capture_base *>(transfer.data);
    continuation_t last_cont_pointer = transfer.continuation;
    successor = user_code->run(last_cont_pointer);
    user_code->deconstruct();
  } while (successor.valid());
}

46 47
continuation switch_context(continuation &&cont) {
  continuation_t cont_pointer = cont.consume();
48 49 50 51 52
  void *next_fiber = cont.get_tsan_fiber();
  void *last_fiber = __tsan_get_current_fiber();
  __tsan_switch_to_fiber(next_fiber, 0);
  fcontext::transfer_t transfer = fcontext::jump_fcontext(cont_pointer, last_fiber);

53
  if (transfer.data) {
54
    return continuation{transfer.continuation, transfer.data};
55
  } else {
56
    return continuation{nullptr, nullptr};
57
  }
58
}
59
#endif
60 61

}