#include "context_switcher/context_switcher.h" #ifdef THREAD_SANITIZER #include #endif namespace context_switcher { #ifdef CS_USE_CSCONTEXT continuation switch_context(continuation &&cont) { continuation_t cont_pointer = cont.consume(); continuation_t result = cscontext::__cs_switch_context(cont_pointer); return continuation{result}; } #endif #if defined(CS_USE_FCONTEXT) and not defined(THREAD_SANITIZER) continuation switch_context(continuation &&cont) { continuation_t cont_pointer = cont.consume(); fcontext::transfer_t transfer = fcontext::jump_fcontext(cont_pointer, (void *) 1); if (transfer.data) { return continuation{transfer.continuation}; } else { return continuation{nullptr}; } } #endif #ifdef THREAD_SANITIZER continuation switch_context(continuation &&cont) { continuation_t cont_pointer = cont.consume(); void *next_fiber = cont.get_tsan_fiber(); void *last_fiber = __tsan_get_current_fiber(); fcontext::fiber_data send_fiber_data{last_fiber, nullptr, false}; __tsan_switch_to_fiber(next_fiber, 0); fcontext::transfer_t transfer = fcontext::jump_fcontext(cont_pointer, &send_fiber_data); fcontext::fiber_data received_fiber_data = *(fcontext::fiber_data *) transfer.data; if (received_fiber_data.finished) { __tsan_destroy_fiber(received_fiber_data.old_fiber); return continuation{nullptr, nullptr}; } else { return continuation{transfer.continuation, received_fiber_data.old_fiber}; } } #endif }