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

3
#ifdef THREAD_SANITIZER
4
#include <sanitizer/tsan_interface.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
continuation switch_context(continuation &&cont) {
  continuation_t cont_pointer = cont.consume();
31 32
  void *next_fiber = cont.get_tsan_fiber();
  void *last_fiber = __tsan_get_current_fiber();
33 34
  fcontext::fiber_data send_fiber_data{last_fiber, nullptr, false};

35
  __tsan_switch_to_fiber(next_fiber, 0);
36 37
  fcontext::transfer_t transfer = fcontext::jump_fcontext(cont_pointer, &send_fiber_data);
  fcontext::fiber_data received_fiber_data = *(fcontext::fiber_data *) transfer.data;
38

39 40
  if (received_fiber_data.finished) {
    __tsan_destroy_fiber(received_fiber_data.old_fiber);
41
    return continuation{nullptr, nullptr};
42 43
  } else {
    return continuation{transfer.continuation, received_fiber_data.old_fiber};
44
  }
45
}
46
#endif
47 48

}