#include "guard.h" #include "../arch/core.h" #include "../debug/output.h" #include "../object/bbuffer.h" #include "../sync/ticketlock.h" #include "../arch/core_interrupt.h" #include "epilogues.h" #define FOR_CURRENT_CORE [Core::getID()] //! \brief The protected data for the epilogue level static Vault global_vault; // lists of pending epilogues static BBuffer epilogue_queue[Core::MAX] = {}; // Big Kernel Lock (BKL) for the epilogue level constinit Ticketlock global_lock; constinit bool epi_flag[Core::MAX] = {false}; Vault::Vault() {} Guarded::~Guarded() { Guard::leave(); } Guarded Guard::enter() { epi_flag FOR_CURRENT_CORE = true; Core::Interrupt::enable(); global_lock.lock(); } void Guard::leave() { bool istate = Core::Interrupt::disable(); Epilogue next; while(epilogue_queue FOR_CURRENT_CORE.consume(next)){ Core::Interrupt::enable(); next(global_vault); Core::Interrupt::disable(); } epi_flag FOR_CURRENT_CORE = false; global_lock.unlock(); Core::Interrupt::restore(istate); } void Guard::relay(Epilogue handler) { if(!epilogue_queue FOR_CURRENT_CORE.consume(handler)) return; // enqueue, but dont execute if(epi_flag FOR_CURRENT_CORE){ enter(); Core::Interrupt::disable(); leave(); } //Core::Interrupt::enable(); // goto level 0.5 //if(epi_flag FOR_CURRENT_CORE){ // epilogue_queue->produce(handler); //} //else{ // epi_flag FOR_CURRENT_CORE = true; // handler(global_vault); // leave(); // maybe not needed since destructor also calls leave //} } const Vault &Guard::unsafeConstAccess() { return global_vault; }