34#ifdef KICAD_USE_VALGRIND 
   35#include <valgrind/valgrind.h> 
   37#ifdef KICAD_SANITIZE_THREADS 
   38#include <sanitizer/tsan_interface.h> 
   40#ifdef KICAD_SANITIZE_ADDRESS 
   41#include <sanitizer/asan_interface.h> 
   44#include <libcontext.h> 
   82template <
typename ReturnType, 
typename ArgType>
 
  107        libcontext::fcontext_t 
ctx;    
 
  109#ifdef KICAD_SANITIZE_THREADS 
  116#ifdef KICAD_SANITIZE_THREADS
 
  117            ,tsan_fiber( nullptr )
 
  118            ,own_tsan_fiber( true )
 
 
  124#ifdef KICAD_SANITIZE_THREADS 
  127                __tsan_destroy_fiber( tsan_fiber );
 
 
 
  157#ifdef KICAD_SANITIZE_THREADS 
  163                reinterpret_cast<intptr_t
>( &args ) );
 
 
 
  199    COROUTINE( std::function<ReturnType( ArgType )> aEntry ) :
 
  207#ifdef KICAD_USE_VALGRIND
 
  208        ,m_valgrind_stack( 0 )
 
  210#ifdef KICAD_SANITIZE_ADDRESS
 
  211        ,asan_stack( nullptr )
 
 
  219#ifdef KICAD_USE_VALGRIND 
  220        VALGRIND_STACK_DEREGISTER( m_valgrind_stack );
 
  224            libcontext::release_fcontext( 
m_caller.ctx );
 
  227            libcontext::release_fcontext( 
m_callee.ctx );
 
 
  279#ifdef KICAD_SANITIZE_THREADS 
  281        m_caller.tsan_fiber     = __tsan_get_current_fiber();
 
  287        ctx.Continue( 
doCall( &args, aArg ) );
 
 
  325#ifdef KICAD_SANITIZE_THREADS 
  327        m_caller.tsan_fiber     = __tsan_get_current_fiber();
 
 
  375    INVOCATION_ARGS* 
doCall( INVOCATION_ARGS* aInvArgs, ArgType aArgs )
 
  387#ifndef LIBCONTEXT_HAS_OWN_STACK 
  393        std::size_t pages = ( 
m_stacksize + systemPageSize - 1 ) / systemPageSize;
 
  396        stackSize = ( pages + 1 ) * systemPageSize;
 
  399        m_stack.get_deleter().SetSize( stackSize );
 
  406        sp = 
static_cast<char*
>( 
m_stack.get() ) + stackSize;
 
  408#ifdef KICAD_USE_VALGRIND 
  409        m_valgrind_stack = VALGRIND_STACK_REGISTER( sp, 
m_stack.get() );
 
  413#ifdef KICAD_SANITIZE_THREADS 
  415        m_callee.tsan_fiber     = __tsan_create_fiber( 0 );
 
  418        __tsan_set_fiber_name( 
m_callee.tsan_fiber, 
"Coroutine fiber" );
 
  425        return jumpIn( aInvArgs );
 
 
  428#ifndef LIBCONTEXT_HAS_OWN_STACK 
  434        void operator()( 
void* aMem ) 
noexcept { ::VirtualFree( aMem, 0, MEM_RELEASE ); }
 
 
  446        static std::optional<size_t> systemPageSize;
 
  448        if( !systemPageSize.has_value() )
 
  452            ::GetSystemInfo( &si );
 
  453            systemPageSize = 
static_cast<size_t>( si.dwPageSize );
 
  455            int size = getpagesize();
 
  456            systemPageSize = 
static_cast<size_t>( size );
 
  460        return systemPageSize.value();
 
 
  467        void* mem = ::VirtualAlloc( 0, aAllocSize, MEM_COMMIT, PAGE_READWRITE );
 
  470            throw std::bad_alloc();
 
  472        void* mem = ::mmap( 0, aAllocSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 );
 
  474        if( mem == (
void*) -1 )
 
  475            throw std::bad_alloc();
 
 
  481    static inline void GuardMemory( 
void* aAddress, 
size_t aGuardSize )
 
  485        BOOL 
res = ::VirtualProtect( aAddress, aGuardSize,
 
  486                                    PAGE_READWRITE | PAGE_GUARD, &old_prot );
 
  488        bool res = ( 0 == ::mprotect( aAddress, aGuardSize, PROT_NONE ) );
 
 
  503        INVOCATION_ARGS& args = *
reinterpret_cast<INVOCATION_ARGS*
>( aData );
 
 
  520    INVOCATION_ARGS* 
jumpIn( INVOCATION_ARGS* args )
 
  522#ifdef KICAD_SANITIZE_THREADS 
  524        __tsan_switch_to_fiber( 
m_callee.tsan_fiber, 0 );
 
  529        args = 
reinterpret_cast<INVOCATION_ARGS*
>(
 
  531                                       reinterpret_cast<intptr_t
>( args ) )
 
 
  540        INVOCATION_ARGS* ret;
 
  542#ifdef KICAD_SANITIZE_THREADS 
  544        __tsan_switch_to_fiber( 
m_caller.tsan_fiber, 0 );
 
  549        ret = 
reinterpret_cast<INVOCATION_ARGS*
>(
 
  551                                       reinterpret_cast<intptr_t
>( &args ) )
 
 
  562#ifndef LIBCONTEXT_HAS_OWN_STACK 
  564    std::unique_ptr<char[], struct STACK_DELETER> 
m_stack;
 
  569    std::function<ReturnType( ArgType )> 
m_func;
 
  574    typename std::remove_reference<ArgType>::type* 
m_args;
 
  587#ifdef KICAD_USE_VALGRIND 
  588    uint32_t m_valgrind_stack;
 
  591#ifdef KICAD_SANITIZE_ADDRESS 
 
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
 
CONTEXT_T * m_mainStackContext
 
void SetMainStack(CONTEXT_T *aStack)
 
void RunMainStack(COROUTINE *aCor, std::function< void()> aFunc)
 
void Continue(INVOCATION_ARGS *args)
 
std::function< void()> m_mainStackFunction
 
bool Call(ArgType aArg)
Start execution of a coroutine, passing args as its arguments.
 
CALL_CONTEXT * m_callContext
 
void KiYield(ReturnType &aRetVal)
KiYield with a value.
 
void KiYield()
Stop execution of the coroutine and returns control to the caller.
 
bool Resume()
Resume execution of a previously yielded coroutine.
 
COROUTINE(std::function< ReturnType(ArgType)> aEntry)
Create a coroutine from a delegate object.
 
static void callerStub(intptr_t aData)
 
CONTEXT_T m_callee
Saved coroutine context.
 
INVOCATION_ARGS * jumpIn(INVOCATION_ARGS *args)
 
std::unique_ptr< char[], struct STACK_DELETER > m_stack
 
const ReturnType & ReturnValue() const
Return the yielded value (the argument KiYield() was called with).
 
INVOCATION_ARGS * doResume(INVOCATION_ARGS *args)
 
static void * MapMemory(size_t aAllocSize)
Map a page-aligned memory region into our address space.
 
static size_t SystemPageSize()
The size of the mappable memory page size.
 
INVOCATION_ARGS * doCall(INVOCATION_ARGS *aInvArgs, ArgType aArgs)
 
bool Call(const COROUTINE &aCor, ArgType aArg)
Start execution of a coroutine, passing args as its arguments.
 
std::function< int(int)> m_func
 
static void GuardMemory(void *aAddress, size_t aGuardSize)
Change protection of memory page(s) to act as stack guards.
 
bool Resume(const COROUTINE &aCor)
Resume execution of a previously yielded coroutine.
 
COROUTINE(T *object, ReturnType(T::*ptr)(ArgType))
Create a coroutine from a member method of an object.
 
void RunMainStack(std::function< void()> func)
Run a functor inside the application main stack context.
 
std::remove_reference< int >::type * m_args
 
int m_CoroutineStackSize
Configure the coroutine stack size in bytes.
 
const wxChar *const kicadTraceCoroutineStack
Flag to enable tracing of the coroutine call stack.
 
libcontext::fcontext_t ctx
 
enum COROUTINE::INVOCATION_ARGS::@361002175157160365344154346100200253026233123042 type
 
A functor that frees the stack.
 
void SetSize(std::size_t aSize)
 
void operator()(void *aMem) noexcept
 
wxLogTrace helper definitions.