Skip to content

Commit

Permalink
Using shared_mutex for one_size_heap
Browse files Browse the repository at this point in the history
  • Loading branch information
hkaiser committed Oct 19, 2023
1 parent 5ce01b4 commit a41c2d6
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 98 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 1998-2017 Hartmut Kaiser
// Copyright (c) 1998-2023 Hartmut Kaiser
// Copyright (c) 2011 Bryce Lelbach
//
// SPDX-License-Identifier: BSL-1.0
Expand All @@ -10,6 +10,7 @@
#include <hpx/config.hpp>
#include <hpx/assert.hpp>
#include <hpx/components_base/server/wrapper_heap_base.hpp>
#include <hpx/synchronization/shared_mutex.hpp>
#include <hpx/synchronization/spinlock.hpp>

#include <cstddef>
Expand All @@ -30,7 +31,7 @@ namespace hpx { namespace util {
using iterator = typename list_type::iterator;
using const_iterator = typename list_type::const_iterator;

using mutex_type = hpx::spinlock;
using mutex_type = hpx::shared_mutex;

using heap_parameters = wrapper_heap_base::heap_parameters;

Expand Down Expand Up @@ -107,8 +108,7 @@ namespace hpx { namespace util {
std::string name() const;

protected:
// mutable mutex_type mtx_;
mutable pthread_rwlock_t rwlock;
mutable mutex_type rwlock_;
list_type heap_list_;

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <hpx/allocator_support/internal_allocator.hpp>
#include <hpx/assert.hpp>
#include <hpx/components_base/server/wrapper_heap_base.hpp>
#include <hpx/concurrency/cache_line_data.hpp>
#include <hpx/modules/itt_notify.hpp>
#include <hpx/naming_base/id_type.hpp>
#include <hpx/synchronization/spinlock.hpp>
Expand Down Expand Up @@ -78,7 +79,7 @@ namespace hpx::components::detail {

public:
explicit wrapper_heap(char const* class_name, std::size_t count,
heap_parameters parameters);
heap_parameters const& parameters);

wrapper_heap();
~wrapper_heap() override;
Expand Down Expand Up @@ -112,11 +113,11 @@ namespace hpx::components::detail {
protected:
char* pool_;
heap_parameters const parameters_;
alignas(64) std::atomic<char*> first_free_;
alignas(64) std::atomic<std::size_t> free_size_;
util::cache_aligned_data_derived<std::atomic<char*>> first_free_;
util::cache_aligned_data_derived<std::atomic<std::size_t>> free_size_;
// these values are used for AGAS registration of all elements of this
// managed_component heap
alignas(64) mutable mutex_type mtx_;
mutable util::cache_aligned_data_derived<mutex_type> mtx_;
naming::gid_type base_gid_;

public:
Expand Down Expand Up @@ -158,7 +159,7 @@ namespace hpx::components::detail {
using value_type = T;

explicit fixed_wrapper_heap(char const* class_name, std::size_t count,
heap_parameters parameters)
heap_parameters const& parameters)
: base_type(class_name, count, parameters)
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
#include <hpx/components_base/component_type.hpp>
#include <hpx/components_base/server/one_size_heap_list.hpp>
#include <hpx/naming_base/id_type.hpp>
#include <hpx/synchronization/shared_mutex.hpp>
#include <hpx/thread_support/unlock_guard.hpp>

#include <mutex>
#include <shared_mutex>
#include <type_traits>

///////////////////////////////////////////////////////////////////////////////
Expand All @@ -25,7 +28,7 @@ namespace hpx::components::detail {
using value_type = typename Heap::value_type;

using storage_type = std::aligned_storage_t<sizeof(value_type),
std::alignment_of<value_type>::value>;
std::alignment_of_v<value_type>>;

enum
{
Expand All @@ -44,27 +47,23 @@ namespace hpx::components::detail {
get_component_type<typename value_type::wrapped_type>()),
base_type::heap_parameters{
heap_capacity, heap_element_alignment, heap_element_size},
(Heap*) nullptr)
static_cast<Heap*>(nullptr))
, type_(get_component_type<typename value_type::wrapped_type>())
{
}

naming::gid_type get_gid(void* p)
{
pthread_rwlock_rdlock(&rwlock);
std::shared_lock<hpx::shared_mutex> sl(rwlock_);

using iterator = typename base_type::const_iterator;

iterator end = heap_list_.end();
for (iterator it = heap_list_.begin(); it != end; ++it)
auto const end = heap_list_.end();
for (auto it = heap_list_.begin(); it != end; ++it)
{
if ((*it)->did_alloc(p))
{
pthread_rwlock_unlock(&rwlock);
return (*it)->get_gid(p, type_);
}
}
pthread_rwlock_unlock(&rwlock);
return naming::invalid_gid;
}

Expand Down
83 changes: 39 additions & 44 deletions libs/full/components_base/src/server/one_size_heap_list.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 1998-2021 Hartmut Kaiser
// Copyright (c) 1998-2023 Hartmut Kaiser
// Copyright (c) 2011 Bryce Lelbach
//
// SPDX-License-Identifier: BSL-1.0
Expand All @@ -12,6 +12,7 @@
#include <hpx/functional/bind_front.hpp>
#include <hpx/modules/errors.hpp>
#include <hpx/modules/format.hpp>
#include <hpx/modules/synchronization.hpp>
#include <hpx/runtime_local/state.hpp>
#include <hpx/thread_support/unlock_guard.hpp>
#include <hpx/threading_base/register_thread.hpp>
Expand All @@ -24,6 +25,7 @@
#include <list>
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <string>

namespace hpx { namespace util {
Expand Down Expand Up @@ -55,37 +57,35 @@ namespace hpx { namespace util {

void* p = nullptr;

pthread_rwlock_rdlock(&rwlock);

if (!heap_list_.empty())
{
for (auto& heap : heap_list_)
{
bool allocated = heap->alloc(&p, count);
std::shared_lock<hpx::shared_mutex> sl(rwlock_);

if (allocated)
if (!heap_list_.empty())
{
for (auto& heap : heap_list_)
{
if (heap->alloc(&p, count))
{
#if defined(HPX_DEBUG)
// Allocation succeeded, update statistics.
alloc_count_ += count;
if (alloc_count_ - free_count_ > max_alloc_count_)
max_alloc_count_ = alloc_count_ - free_count_;
// Allocation succeeded, update statistics.
alloc_count_ += count;
if (alloc_count_ - free_count_ > max_alloc_count_)
max_alloc_count_ = alloc_count_ - free_count_;
#endif
pthread_rwlock_unlock(&rwlock);
return p;
}
return p;
}

#if defined(HPX_DEBUG)
LOSH_(info).format(
"{1}::alloc: failed to allocate from heap[{2}] "
"(heap[{2}] has allocated {3} objects and has "
"space for {4} more objects)",
name(), heap->heap_count(), heap->size(),
heap->free_size());
LOSH_(info).format(
"{1}::alloc: failed to allocate from heap[{2}] "
"(heap[{2}] has allocated {3} objects and has "
"space for {4} more objects)",
name(), heap->heap_count(), heap->size(),
heap->free_size());
#endif
}
}
}
pthread_rwlock_unlock(&rwlock);

// Create new heap.
bool result = false;
Expand All @@ -98,11 +98,10 @@ namespace hpx { namespace util {
result = heap->alloc((void**) &p, count);

// Add the heap into the list
// mtx_.lock();
pthread_rwlock_wrlock(&rwlock);
heap_list_.push_front(heap);
pthread_rwlock_unlock(&rwlock);
// mtx_.unlock();
{
std::unique_lock<hpx::shared_mutex> ul(rwlock_);
heap_list_.push_front(heap);
}

if (HPX_UNLIKELY(!result || nullptr == p))
{
Expand Down Expand Up @@ -149,49 +148,45 @@ namespace hpx { namespace util {
if (reschedule(p, count))
return;

// mtx_.lock();
pthread_rwlock_rdlock(&rwlock);
// mtx_.unlock();
// Find the heap which allocated this pointer.
for (auto& heap : heap_list_)
{
bool did_allocate = heap->did_alloc(p);
if (did_allocate)
std::shared_lock<hpx::shared_mutex> sl(rwlock_);

// Find the heap which allocated this pointer.
for (auto const& heap : heap_list_)
{
heap->free(p, count);
if (heap->did_alloc(p))
{
heap->free(p, count);
#if defined(HPX_DEBUG)
free_count_ += count;
free_count_ += count;
#endif
pthread_rwlock_unlock(&rwlock);
return;
return;
}
}
}
pthread_rwlock_unlock(&rwlock);

HPX_THROW_EXCEPTION(hpx::error::bad_parameter, name() + "::free",
"pointer {1} was not allocated by this {2}", p, name());
}

bool one_size_heap_list::did_alloc(void* p) const
{
pthread_rwlock_rdlock(&rwlock);
for (typename list_type::value_type const& heap : heap_list_)
std::shared_lock<hpx::shared_mutex> sl(rwlock_);
for (auto const& heap : heap_list_)
{
if (heap->did_alloc(p))
{
pthread_rwlock_unlock(&rwlock);
return true;
}
}
pthread_rwlock_unlock(&rwlock);
return false;
}

std::string one_size_heap_list::name() const
{
if (class_name_.empty())
{
return std::string("one_size_heap_list(unknown)");
return {"one_size_heap_list(unknown)"};
}
return std::string("one_size_heap_list(") + class_name_ + ")";
}
Expand Down
Loading

0 comments on commit a41c2d6

Please sign in to comment.