|
#ifndef GREENLET_SLP_SWITCH_HPP |
|
#define GREENLET_SLP_SWITCH_HPP |
|
|
|
#include "greenlet_compiler_compat.hpp" |
|
#include "greenlet_refs.hpp" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static greenlet::Greenlet* volatile switching_thread_state = nullptr; |
|
|
|
|
|
extern "C" { |
|
static int GREENLET_NOINLINE(slp_save_state_trampoline)(char* stackref); |
|
static void GREENLET_NOINLINE(slp_restore_state_trampoline)(); |
|
} |
|
|
|
|
|
#define SLP_SAVE_STATE(stackref, stsizediff) \ |
|
do { \ |
|
assert(switching_thread_state); \ |
|
stackref += STACK_MAGIC; \ |
|
if (slp_save_state_trampoline((char*)stackref)) \ |
|
return -1; \ |
|
if (!switching_thread_state->active()) \ |
|
return 1; \ |
|
stsizediff = switching_thread_state->stack_start() - (char*)stackref; \ |
|
} while (0) |
|
|
|
#define SLP_RESTORE_STATE() slp_restore_state_trampoline() |
|
|
|
#define SLP_EVAL |
|
extern "C" { |
|
#define slp_switch GREENLET_NOINLINE(slp_switch) |
|
#include "slp_platformselect.h" |
|
} |
|
#undef slp_switch |
|
|
|
#ifndef STACK_MAGIC |
|
# error \ |
|
"greenlet needs to be ported to this platform, or taught how to detect your compiler properly." |
|
#endif |
|
|
|
|
|
|
|
#ifdef EXTERNAL_ASM |
|
|
|
|
|
|
|
|
|
extern "C" { |
|
intptr_t |
|
slp_save_state_asm(intptr_t* ref) |
|
{ |
|
intptr_t diff; |
|
SLP_SAVE_STATE(ref, diff); |
|
return diff; |
|
} |
|
|
|
void |
|
slp_restore_state_asm(void) |
|
{ |
|
SLP_RESTORE_STATE(); |
|
} |
|
|
|
extern int slp_switch(void); |
|
}; |
|
#endif |
|
|
|
#endif |
|
|