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 #ifdef KICAD_USE_VALGRIND
#include <valgrind/valgrind.h> #include <valgrind/valgrind.h>
#endif #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 <libcontext.h>
#include <functional>
#include <memory> #include <memory>
#include <advanced_config.h> #include <advanced_config.h>
@ -83,8 +90,32 @@ private:
// call context holds a reference to the main stack context // call context holds a reference to the main stack context
}; };
using CONTEXT_T = libcontext::fcontext_t; struct CONTEXT_T
using CALLEE_STORAGE = 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 class CALL_CONTEXT
{ {
@ -96,8 +127,8 @@ private:
~CALL_CONTEXT() ~CALL_CONTEXT()
{ {
if ( m_mainStackContext ) if( m_mainStackContext )
libcontext::release_fcontext( *m_mainStackContext ); libcontext::release_fcontext( m_mainStackContext->ctx );
} }
@ -111,7 +142,12 @@ private:
m_mainStackFunction = std::move( aFunc ); m_mainStackFunction = std::move( aFunc );
INVOCATION_ARGS args{ INVOCATION_ARGS::CONTINUE_AFTER_ROOT, aCor, this }; 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 ) ); reinterpret_cast<intptr_t>( &args ) );
} }
@ -152,12 +188,15 @@ public:
m_func( std::move( aEntry ) ), m_func( std::move( aEntry ) ),
m_running( false ), m_running( false ),
m_args( 0 ), m_args( 0 ),
m_caller( nullptr ), m_caller(),
m_callContext( nullptr ), m_callContext( nullptr ),
m_callee( nullptr ), m_callee(),
m_retVal( 0 ) m_retVal( 0 )
#ifdef KICAD_USE_VALGRIND #ifdef KICAD_USE_VALGRIND
,valgrind_stack( 0 ) ,valgrind_stack( 0 )
#endif
#ifdef KICAD_SANITIZE_ADDRESS
,asan_stack( nullptr )
#endif #endif
{ {
m_stacksize = ADVANCED_CFG::GetCfg().m_CoroutineStackSize; m_stacksize = ADVANCED_CFG::GetCfg().m_CoroutineStackSize;
@ -168,10 +207,10 @@ public:
#ifdef KICAD_USE_VALGRIND #ifdef KICAD_USE_VALGRIND
VALGRIND_STACK_DEREGISTER( valgrind_stack ); VALGRIND_STACK_DEREGISTER( valgrind_stack );
#endif #endif
if(m_caller) if( m_caller.ctx )
libcontext::release_fcontext( m_caller ); libcontext::release_fcontext( m_caller.ctx );
if(m_callee) if( m_callee.ctx )
libcontext::release_fcontext( m_callee ); libcontext::release_fcontext( m_callee.ctx );
} }
public: public:
@ -222,6 +261,12 @@ public:
{ {
CALL_CONTEXT ctx; CALL_CONTEXT ctx;
INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROOT, this, &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 ) ); ctx.Continue( doCall( &args, aArg ) );
return Running(); return Running();
@ -256,6 +301,12 @@ public:
{ {
CALL_CONTEXT ctx; CALL_CONTEXT ctx;
INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROOT, this, &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 ) ); ctx.Continue( doResume( &args ) );
return Running(); return Running();
@ -298,7 +349,7 @@ private:
INVOCATION_ARGS* doCall( INVOCATION_ARGS* aInvArgs, ArgType aArgs ) INVOCATION_ARGS* doCall( INVOCATION_ARGS* aInvArgs, ArgType aArgs )
{ {
assert( m_func ); assert( m_func );
assert( !m_callee ); assert( !( m_callee.ctx ) );
m_args = &aArgs; m_args = &aArgs;
@ -323,7 +374,12 @@ private:
#endif #endif
#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; m_running = true;
// off we go! // off we go!
@ -357,8 +413,12 @@ private:
INVOCATION_ARGS* jumpIn( INVOCATION_ARGS* args ) 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*>( 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 ) ) reinterpret_cast<intptr_t>( args ) )
); );
@ -370,8 +430,12 @@ private:
INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROUTINE, nullptr, nullptr }; INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROUTINE, nullptr, nullptr };
INVOCATION_ARGS* ret; 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*>( 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 ) ) reinterpret_cast<intptr_t>( &args ) )
); );
@ -403,13 +467,16 @@ private:
CALL_CONTEXT* m_callContext; CALL_CONTEXT* m_callContext;
///< saved coroutine context ///< saved coroutine context
CALLEE_STORAGE m_callee; CONTEXT_T m_callee;
ReturnType m_retVal; ReturnType m_retVal;
#ifdef KICAD_USE_VALGRIND #ifdef KICAD_USE_VALGRIND
uint32_t valgrind_stack; uint32_t valgrind_stack;
#endif #endif
#ifdef KICAD_SANITIZE_ADDRESS
void* asan_stack;
#endif
}; };
#endif #endif