Annotate the coroutines with TSAN fiber information

This commit is contained in:
Ian McInerney 2021-04-16 17:39:31 +01:00
parent e237b6a2af
commit 660d1596e2
1 changed files with 83 additions and 16 deletions

View File

@ -34,8 +34,15 @@
#ifdef KICAD_USE_VALGRIND
#include <valgrind/valgrind.h>
#endif
#ifdef KICAD_SANITIZE_THREADS
#include <sanitizer/tsan_interface.h>
#endif
#ifdef KICAD_SANITIZE_ADDRESS
#include <sanitizer/asan_interface.h>
#endif
#include <libcontext.h>
#include <functional>
#include <memory>
#include <advanced_config.h>
@ -83,8 +90,32 @@ private:
// call context holds a reference to the main stack context
};
using CONTEXT_T = libcontext::fcontext_t;
using CALLEE_STORAGE = CONTEXT_T;
struct CONTEXT_T
{
libcontext::fcontext_t ctx; // The context itself
#ifdef KICAD_SANITIZE_THREADS
void* tsan_fiber; // The TSAN fiber for this context
bool own_tsan_fiber; // Do we own this TSAN fiber? (we only delete fibers we own)
#endif
CONTEXT_T() :
ctx( nullptr )
#ifdef KICAD_SANITIZE_THREADS
,tsan_fiber( nullptr )
,own_tsan_fiber( true )
#endif
{}
~CONTEXT_T()
{
#ifdef KICAD_SANITIZE_THREADS
// Only destroy the fiber when we own it
if( own_tsan_fiber )
__tsan_destroy_fiber( tsan_fiber );
#endif
}
};
class CALL_CONTEXT
{
@ -97,7 +128,7 @@ private:
~CALL_CONTEXT()
{
if( m_mainStackContext )
libcontext::release_fcontext( *m_mainStackContext );
libcontext::release_fcontext( m_mainStackContext->ctx );
}
@ -111,7 +142,12 @@ private:
m_mainStackFunction = std::move( aFunc );
INVOCATION_ARGS args{ INVOCATION_ARGS::CONTINUE_AFTER_ROOT, aCor, this };
libcontext::jump_fcontext( &aCor->m_callee, *m_mainStackContext,
#ifdef KICAD_SANITIZE_THREADS
// Tell TSAN we are changing fibers
__tsan_switch_to_fiber( m_mainStackContext->tsan_fiber, 0 );
#endif
libcontext::jump_fcontext( &( aCor->m_callee.ctx ), m_mainStackContext->ctx,
reinterpret_cast<intptr_t>( &args ) );
}
@ -152,12 +188,15 @@ public:
m_func( std::move( aEntry ) ),
m_running( false ),
m_args( 0 ),
m_caller( nullptr ),
m_caller(),
m_callContext( nullptr ),
m_callee( nullptr ),
m_callee(),
m_retVal( 0 )
#ifdef KICAD_USE_VALGRIND
,valgrind_stack( 0 )
#endif
#ifdef KICAD_SANITIZE_ADDRESS
,asan_stack( nullptr )
#endif
{
m_stacksize = ADVANCED_CFG::GetCfg().m_CoroutineStackSize;
@ -168,10 +207,10 @@ public:
#ifdef KICAD_USE_VALGRIND
VALGRIND_STACK_DEREGISTER( valgrind_stack );
#endif
if(m_caller)
libcontext::release_fcontext( m_caller );
if(m_callee)
libcontext::release_fcontext( m_callee );
if( m_caller.ctx )
libcontext::release_fcontext( m_caller.ctx );
if( m_callee.ctx )
libcontext::release_fcontext( m_callee.ctx );
}
public:
@ -222,6 +261,12 @@ public:
{
CALL_CONTEXT ctx;
INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROOT, this, &ctx };
#ifdef KICAD_SANITIZE_THREADS
// Get the TSAN fiber for the current stack here
m_caller.tsan_fiber = __tsan_get_current_fiber();
m_caller.own_tsan_fiber = false;
#endif
ctx.Continue( doCall( &args, aArg ) );
return Running();
@ -256,6 +301,12 @@ public:
{
CALL_CONTEXT ctx;
INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROOT, this, &ctx };
#ifdef KICAD_SANITIZE_THREADS
// Get the TSAN fiber for the current stack here
m_caller.tsan_fiber = __tsan_get_current_fiber();
m_caller.own_tsan_fiber = false;
#endif
ctx.Continue( doResume( &args ) );
return Running();
@ -298,7 +349,7 @@ private:
INVOCATION_ARGS* doCall( INVOCATION_ARGS* aInvArgs, ArgType aArgs )
{
assert( m_func );
assert( !m_callee );
assert( !( m_callee.ctx ) );
m_args = &aArgs;
@ -323,7 +374,12 @@ private:
#endif
#endif
m_callee = libcontext::make_fcontext( sp, stackSize, callerStub );
#ifdef KICAD_SANITIZE_THREADS
// Create a new fiber to go with the new context
m_callee.tsan_fiber = __tsan_create_fiber( 0 );
m_callee.own_tsan_fiber = true;
#endif
m_callee.ctx = libcontext::make_fcontext( sp, stackSize, callerStub );
m_running = true;
// off we go!
@ -357,8 +413,12 @@ private:
INVOCATION_ARGS* jumpIn( INVOCATION_ARGS* args )
{
#ifdef KICAD_SANITIZE_THREADS
// Tell TSAN we are changing fibers to the callee
__tsan_switch_to_fiber( m_callee.tsan_fiber, 0 );
#endif
args = reinterpret_cast<INVOCATION_ARGS*>(
libcontext::jump_fcontext( &m_caller, m_callee,
libcontext::jump_fcontext( &( m_caller.ctx ), m_callee.ctx,
reinterpret_cast<intptr_t>( args ) )
);
@ -370,8 +430,12 @@ private:
INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROUTINE, nullptr, nullptr };
INVOCATION_ARGS* ret;
#ifdef KICAD_SANITIZE_THREADS
// Tell TSAN we are changing fibers back to the caller
__tsan_switch_to_fiber( m_caller.tsan_fiber, 0 );
#endif
ret = reinterpret_cast<INVOCATION_ARGS*>(
libcontext::jump_fcontext( &m_callee, m_caller,
libcontext::jump_fcontext( &( m_callee.ctx ), m_caller.ctx,
reinterpret_cast<intptr_t>( &args ) )
);
@ -403,13 +467,16 @@ private:
CALL_CONTEXT* m_callContext;
///< saved coroutine context
CALLEE_STORAGE m_callee;
CONTEXT_T m_callee;
ReturnType m_retVal;
#ifdef KICAD_USE_VALGRIND
uint32_t valgrind_stack;
#endif
#ifdef KICAD_SANITIZE_ADDRESS
void* asan_stack;
#endif
};
#endif