From 4c8ccf384a2aaffca42b7ad7d921dc13c2c545ef Mon Sep 17 00:00:00 2001 From: oliver Kowalke Date: Mon, 23 May 2016 09:02:01 +0200 Subject: [PATCH] replace atomic< scheduler > by raw pointer - to synchronize, use a fence in scheduler::detach_worker_context() and scheduler::attach_worker_context() --- include/boost/fiber/context.hpp | 4 ++-- performance/fiber/Jamfile.v2 | 3 --- performance/fiber/skynet_shared.cpp | 2 +- src/context.cpp | 36 ++++++++++++++--------------- src/scheduler.cpp | 4 +++- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/include/boost/fiber/context.hpp b/include/boost/fiber/context.hpp index 498f8d7e..2c619db6 100644 --- a/include/boost/fiber/context.hpp +++ b/include/boost/fiber/context.hpp @@ -161,8 +161,8 @@ private: unsigned int flags_; type type_; #endif - launch policy_{ launch::post }; - std::atomic< scheduler * > scheduler_{ nullptr }; + launch policy_{ launch::post }; + scheduler * scheduler_{ nullptr }; #if (BOOST_EXECUTION_CONTEXT==1) boost::context::execution_context ctx_; #else diff --git a/performance/fiber/Jamfile.v2 b/performance/fiber/Jamfile.v2 index d0a56343..5f022edd 100644 --- a/performance/fiber/Jamfile.v2 +++ b/performance/fiber/Jamfile.v2 @@ -22,9 +22,6 @@ project boost/fiber/performance/fiber clang,on:-DBOOST_USE_SEGMENTED_STACKS static multi - -DBOOST_DISABLE_ASSERTS - speed - release ; alias pbind diff --git a/performance/fiber/skynet_shared.cpp b/performance/fiber/skynet_shared.cpp index 87d45da7..4f5299f0 100644 --- a/performance/fiber/skynet_shared.cpp +++ b/performance/fiber/skynet_shared.cpp @@ -70,7 +70,7 @@ int main() { unsigned int n = std::thread::hardware_concurrency(); barrier b( n); bind_to_processor( n - 1); - std::size_t stack_size{ 4048 }; + std::size_t stack_size{ 8*1024 }; std::size_t size{ 100000 }; std::size_t div{ 10 }; std::vector< std::thread > threads; diff --git a/src/context.cpp b/src/context.cpp index edd43714..cbf88566 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -176,7 +176,7 @@ context::resume_( detail::data_t & d) noexcept { void context::set_ready_( context * ctx) noexcept { - scheduler_.load()->set_ready( ctx); + scheduler_->set_ready( ctx); } // main fiber context @@ -288,12 +288,12 @@ context::resume( context * ready_ctx) noexcept { void context::suspend() noexcept { - scheduler_.load()->suspend(); + scheduler_->suspend(); } void context::suspend( detail::spinlock_lock & lk) noexcept { - scheduler_.load()->suspend( lk); + scheduler_->suspend( lk); } void @@ -310,7 +310,7 @@ context::join() { active_ctx->wait_link( wait_queue_); lk.unlock(); // suspend active context - scheduler_.load()->suspend(); + scheduler_->suspend(); // remove from wait-queue active_ctx->wait_unlink(); // active context resumed @@ -321,7 +321,7 @@ context::join() { void context::yield() noexcept { // yield active context - scheduler_.load()->yield( context::active() ); + scheduler_->yield( context::active() ); } #if (BOOST_EXECUTION_CONTEXT>1) @@ -363,42 +363,42 @@ context::set_terminated() noexcept { fss_data_.clear(); // switch to another context #if (BOOST_EXECUTION_CONTEXT==1) - scheduler_.load()->set_terminated( this); + scheduler_->set_terminated( this); #else - return scheduler_.load()->set_terminated( this); + return scheduler_->set_terminated( this); #endif } bool context::wait_until( std::chrono::steady_clock::time_point const& tp) noexcept { - BOOST_ASSERT( nullptr != scheduler_.load() ); + BOOST_ASSERT( nullptr != scheduler_); BOOST_ASSERT( this == active_); - return scheduler_.load()->wait_until( this, tp); + return scheduler_->wait_until( this, tp); } bool context::wait_until( std::chrono::steady_clock::time_point const& tp, detail::spinlock_lock & lk) noexcept { - BOOST_ASSERT( nullptr != scheduler_.load() ); + BOOST_ASSERT( nullptr != scheduler_); BOOST_ASSERT( this == active_); - return scheduler_.load()->wait_until( this, tp, lk); + return scheduler_->wait_until( this, tp, lk); } void context::set_ready( context * ctx) noexcept { //BOOST_ASSERT( nullptr != ctx); BOOST_ASSERT( this != ctx); - BOOST_ASSERT( nullptr != scheduler_.load() ); - BOOST_ASSERT( nullptr != ctx->scheduler_.load() ); + BOOST_ASSERT( nullptr != scheduler_); + BOOST_ASSERT( nullptr != ctx->scheduler_); // FIXME: comparing scheduler address' must be synchronized? // what if ctx is migrated between threads // (other scheduler assigned) - if ( scheduler_.load() == ctx->scheduler_.load() ) { + if ( scheduler_ == ctx->scheduler_) { // local - scheduler_.load()->set_ready( ctx); + scheduler_->set_ready( ctx); } else { // remote - ctx->scheduler_.load()->set_remote_ready( ctx); + ctx->scheduler_->set_remote_ready( ctx); } } @@ -492,13 +492,13 @@ context::wait_unlink() noexcept { void context::detach() noexcept { BOOST_ASSERT( context::active() != this); - scheduler_.load()->detach_worker_context( this); + scheduler_->detach_worker_context( this); } void context::attach( context * ctx) noexcept { BOOST_ASSERT( nullptr != ctx); - scheduler_.load()->attach_worker_context( ctx); + scheduler_->attach_worker_context( ctx); } }} diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 82440428..1caee04d 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -386,13 +386,15 @@ scheduler::attach_worker_context( context * ctx) noexcept { BOOST_ASSERT( ! ctx->terminated_is_linked() ); BOOST_ASSERT( ! ctx->wait_is_linked() ); BOOST_ASSERT( ! ctx->worker_is_linked() ); - BOOST_ASSERT( nullptr == ctx->scheduler_.load() ); + BOOST_ASSERT( nullptr == ctx->scheduler_); ctx->worker_link( worker_queue_); ctx->scheduler_ = this; + std::atomic_thread_fence(std::memory_order_release); } void scheduler::detach_worker_context( context * ctx) noexcept { + std::atomic_thread_fence(std::memory_order_acquire); BOOST_ASSERT( nullptr != ctx); BOOST_ASSERT( ! ctx->ready_is_linked() ); BOOST_ASSERT( ! ctx->sleep_is_linked() );