context_switcher.cpp 2.01 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
#endif
#ifdef THREAD_SANITIZER
29 30 31
std::mutex shared_cache_mtx{};
std::unordered_map<char *, cached_fiber> shared_cached_fibers{};
thread_local std::unordered_map<char *, cached_fiber> local_cached_fibers{};
32 33 34 35 36 37 38 39 40 41 42

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);
43
    user_code->~lambda_capture_base();
44 45 46
  } while (successor.valid());
}

47 48
continuation switch_context(continuation &&cont) {
  continuation_t cont_pointer = cont.consume();
49 50 51 52 53
  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);

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

}