diff --git a/asio/include/asio/detail/conditionally_enabled_mutex.hpp b/asio/include/asio/detail/conditionally_enabled_mutex.hpp index 6d2bdaa2a5..e23646229e 100644 --- a/asio/include/asio/detail/conditionally_enabled_mutex.hpp +++ b/asio/include/asio/detail/conditionally_enabled_mutex.hpp @@ -129,6 +129,12 @@ class conditionally_enabled_mutex return enabled_; } + // Get the spin count. + int spin_count() const + { + return spin_count_; + } + // Lock the mutex. void lock() { diff --git a/asio/include/asio/detail/epoll_reactor.hpp b/asio/include/asio/detail/epoll_reactor.hpp index 80c26ccc7e..2356592896 100644 --- a/asio/include/asio/detail/epoll_reactor.hpp +++ b/asio/include/asio/detail/epoll_reactor.hpp @@ -71,7 +71,7 @@ class epoll_reactor bool try_speculative_[max_ops]; bool shutdown_; - ASIO_DECL descriptor_state(bool locking); + ASIO_DECL descriptor_state(bool locking, int spin_count); void set_ready_events(uint32_t events) { task_result_ = events; } void add_ready_events(uint32_t events) { task_result_ |= events; } ASIO_DECL operation* perform_io(uint32_t events); @@ -272,6 +272,9 @@ class epoll_reactor // Whether I/O locking is enabled. const bool io_locking_; + // How any times to spin waiting for the I/O mutex. + const int io_locking_spin_count_; + // Mutex to protect access to the registered descriptors. mutex registered_descriptors_mutex_; diff --git a/asio/include/asio/detail/impl/epoll_reactor.ipp b/asio/include/asio/detail/impl/epoll_reactor.ipp index 02c5c1b8af..f8136031e1 100644 --- a/asio/include/asio/detail/impl/epoll_reactor.ipp +++ b/asio/include/asio/detail/impl/epoll_reactor.ipp @@ -39,15 +39,19 @@ namespace detail { epoll_reactor::epoll_reactor(asio::execution_context& ctx) : execution_context_service_base(ctx), scheduler_(use_service(ctx)), - mutex_(config(ctx).get("reactor", "registration_locking", true)), + mutex_(config(ctx).get("reactor", "registration_locking", true), + config(ctx).get("reactor", "registration_locking_spin_count", 0)), interrupter_(), epoll_fd_(do_epoll_create()), timer_fd_(do_timerfd_create()), shutdown_(false), io_locking_(config(ctx).get("reactor", "io_locking", true)), - registered_descriptors_mutex_(mutex_.enabled()), + io_locking_spin_count_( + config(ctx).get("reactor", "io_locking_spin_count", 0)), + registered_descriptors_mutex_(mutex_.enabled(), mutex_.spin_count()), registered_descriptors_( - config(ctx).get("reactor", "preallocated_io_objects", 0U), io_locking_) + config(ctx).get("reactor", "preallocated_io_objects", 0U), + io_locking_, io_locking_spin_count_) { // Add the interrupter's descriptor to epoll. epoll_event ev = { 0, { 0 } }; @@ -670,7 +674,7 @@ int epoll_reactor::do_timerfd_create() epoll_reactor::descriptor_state* epoll_reactor::allocate_descriptor_state() { mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_); - return registered_descriptors_.alloc(io_locking_); + return registered_descriptors_.alloc(io_locking_, io_locking_spin_count_); } void epoll_reactor::free_descriptor_state(epoll_reactor::descriptor_state* s) @@ -762,9 +766,9 @@ struct epoll_reactor::perform_io_cleanup_on_block_exit operation* first_op_; }; -epoll_reactor::descriptor_state::descriptor_state(bool locking) +epoll_reactor::descriptor_state::descriptor_state(bool locking, int spin_count) : operation(&epoll_reactor::descriptor_state::do_complete), - mutex_(locking) + mutex_(locking, spin_count) { } diff --git a/asio/include/asio/detail/impl/io_uring_service.ipp b/asio/include/asio/detail/impl/io_uring_service.ipp index 46ceca033f..c661a4d756 100644 --- a/asio/include/asio/detail/impl/io_uring_service.ipp +++ b/asio/include/asio/detail/impl/io_uring_service.ipp @@ -35,17 +35,21 @@ namespace detail { io_uring_service::io_uring_service(asio::execution_context& ctx) : execution_context_service_base(ctx), scheduler_(use_service(ctx)), - mutex_(config(ctx).get("reactor", "registration_locking", true)), + mutex_(config(ctx).get("reactor", "registration_locking", true), + config(ctx).get("reactor", "registration_locking_spin_count", 0)), outstanding_work_(0), submit_sqes_op_(this), pending_sqes_(0), pending_submit_sqes_op_(false), shutdown_(false), io_locking_(config(ctx).get("reactor", "io_locking", true)), + io_locking_spin_count_( + config(ctx).get("reactor", "io_locking_spin_count", 0)), timeout_(), registration_mutex_(mutex_.enabled()), registered_io_objects_( - config(ctx).get("reactor", "preallocated_io_objects", 0U), io_locking_), + config(ctx).get("reactor", "preallocated_io_objects", 0U), + io_locking_, io_locking_spin_count_), reactor_(use_service(ctx)), reactor_data_(), event_fd_(-1) @@ -614,7 +618,7 @@ void io_uring_service::register_with_reactor() io_uring_service::io_object* io_uring_service::allocate_io_object() { mutex::scoped_lock registration_lock(registration_mutex_); - return registered_io_objects_.alloc(io_locking_); + return registered_io_objects_.alloc(io_locking_, io_locking_spin_count_); } void io_uring_service::free_io_object(io_uring_service::io_object* io_obj) @@ -899,8 +903,8 @@ void io_uring_service::io_queue::do_complete(void* owner, operation* base, } } -io_uring_service::io_object::io_object(bool locking) - : mutex_(locking) +io_uring_service::io_object::io_object(bool locking, int spin_count) + : mutex_(locking, spin_count) { } diff --git a/asio/include/asio/detail/impl/kqueue_reactor.ipp b/asio/include/asio/detail/impl/kqueue_reactor.ipp index d508efa4c5..7958a3876c 100644 --- a/asio/include/asio/detail/impl/kqueue_reactor.ipp +++ b/asio/include/asio/detail/impl/kqueue_reactor.ipp @@ -47,14 +47,18 @@ namespace detail { kqueue_reactor::kqueue_reactor(asio::execution_context& ctx) : execution_context_service_base(ctx), scheduler_(use_service(ctx)), - mutex_(config(ctx).get("reactor", "registration_locking", true)), + mutex_(config(ctx).get("reactor", "registration_locking", true), + config(ctx).get("reactor", "registration_locking_spin_count", 0)), kqueue_fd_(do_kqueue_create()), interrupter_(), shutdown_(false), io_locking_(config(ctx).get("reactor", "io_locking", true)), + io_locking_spin_count_( + config(ctx).get("reactor", "io_locking_spin_count", 0)), registered_descriptors_mutex_(mutex_.enabled()), registered_descriptors_( - config(ctx).get("reactor", "preallocated_io_objects", 0U), io_locking_) + config(ctx).get("reactor", "preallocated_io_objects", 0U), + io_locking_, io_locking_spin_count_) { struct kevent events[1]; ASIO_KQUEUE_EV_SET(&events[0], interrupter_.read_descriptor(), @@ -565,7 +569,7 @@ int kqueue_reactor::do_kqueue_create() kqueue_reactor::descriptor_state* kqueue_reactor::allocate_descriptor_state() { mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_); - return registered_descriptors_.alloc(io_locking_); + return registered_descriptors_.alloc(io_locking_, io_locking_spin_count_); } void kqueue_reactor::free_descriptor_state(kqueue_reactor::descriptor_state* s) diff --git a/asio/include/asio/detail/io_uring_service.hpp b/asio/include/asio/detail/io_uring_service.hpp index 731e279691..7b3a39661e 100644 --- a/asio/include/asio/detail/io_uring_service.hpp +++ b/asio/include/asio/detail/io_uring_service.hpp @@ -82,7 +82,7 @@ class io_uring_service io_queue queues_[max_ops]; bool shutdown_; - ASIO_DECL io_object(bool locking); + ASIO_DECL io_object(bool locking, int spin_count); }; // Per I/O object data. @@ -280,6 +280,9 @@ class io_uring_service // Whether I/O locking is enabled. const bool io_locking_; + // How any times to spin waiting for the I/O mutex. + const int io_locking_spin_count_; + // The timer queues. timer_queue_set timer_queues_; diff --git a/asio/include/asio/detail/kqueue_reactor.hpp b/asio/include/asio/detail/kqueue_reactor.hpp index c5a05b33d5..c766d6a4c3 100644 --- a/asio/include/asio/detail/kqueue_reactor.hpp +++ b/asio/include/asio/detail/kqueue_reactor.hpp @@ -65,7 +65,8 @@ class kqueue_reactor // Per-descriptor queues. struct descriptor_state { - descriptor_state(bool locking) : mutex_(locking) {} + descriptor_state(bool locking, int spin_count) + : mutex_(locking, spin_count) {} friend class kqueue_reactor; friend class object_pool_access; @@ -252,6 +253,9 @@ class kqueue_reactor // Whether I/O locking is enabled. const bool io_locking_; + // How any times to spin waiting for the I/O mutex. + const int io_locking_spin_count_; + // Mutex to protect access to the registered descriptors. mutex registered_descriptors_mutex_;