Commit 520148aa authored by Maged Michael's avatar Maged Michael Committed by Facebook Github Bot

Fix destruction order

Summary:
- Added `hazptr.cpp` and `memory_resource.cpp`. Moved singleton code to source.
  - Changed the singleton for the default `hazptr_domain` to a global.
  - Changed hazptr_stats singleton to a global.
  - Moved the thread caching calls from the hazptr_domain functions to the constructor/destructor of hazptr_holder.
  - Changed the TLS singletons to TLS globals.
  - Changed some inlining directives.
  - Leak the hazptr_rec-s in the default domain

Reviewed By: davidtgoldblatt, djwatson

Differential Revision: D5553753

fbshipit-source-id: da69eecec55c0f78fb8ef5591f9aeffee99ff3fa
parent cccde53e
...@@ -98,7 +98,6 @@ inline uint64_t bench(std::string name, int ops, const RepFunc& repFn) { ...@@ -98,7 +98,6 @@ inline uint64_t bench(std::string name, int ops, const RepFunc& repFn) {
inline uint64_t listBench(std::string name, int nthreads, int size) { inline uint64_t listBench(std::string name, int nthreads, int size) {
int ops = 100000; int ops = 100000;
auto repFn = [&] { auto repFn = [&] {
hazptr_holder dummy[100];
SWMRListSet<uint64_t> s; SWMRListSet<uint64_t> s;
auto init = [&] { auto init = [&] {
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
...@@ -119,7 +118,6 @@ inline uint64_t listBench(std::string name, int nthreads, int size) { ...@@ -119,7 +118,6 @@ inline uint64_t listBench(std::string name, int nthreads, int size) {
inline uint64_t holderBench(std::string name, int nthreads) { inline uint64_t holderBench(std::string name, int nthreads) {
int ops = 100000; int ops = 100000;
auto repFn = [&] { auto repFn = [&] {
hazptr_holder dummy[100];
auto init = [] {}; auto init = [] {};
auto fn = [&](int tid) { auto fn = [&](int tid) {
for (int j = tid; j < ops; j += nthreads) { for (int j = tid; j < ops; j += nthreads) {
...@@ -138,7 +136,6 @@ inline uint64_t retireBench(std::string name, int nthreads) { ...@@ -138,7 +136,6 @@ inline uint64_t retireBench(std::string name, int nthreads) {
}; };
int ops = 100000; int ops = 100000;
auto repFn = [&] { auto repFn = [&] {
hazptr_holder dummy[100];
auto init = [] {}; auto init = [] {};
auto fn = [&](int tid) { auto fn = [&](int tid) {
for (int j = tid; j < ops; j += nthreads) { for (int j = tid; j < ops; j += nthreads) {
......
...@@ -53,7 +53,6 @@ class SWMRListSet { ...@@ -53,7 +53,6 @@ class SWMRListSet {
}; };
std::atomic<Node*> head_ = {nullptr}; std::atomic<Node*> head_ = {nullptr};
hazptr_domain& domain_;
/* Used by the single writer */ /* Used by the single writer */
void locate_lower_bound(const T& v, std::atomic<Node*>*& prev) const { void locate_lower_bound(const T& v, std::atomic<Node*>*& prev) const {
...@@ -67,9 +66,6 @@ class SWMRListSet { ...@@ -67,9 +66,6 @@ class SWMRListSet {
} }
public: public:
explicit SWMRListSet(hazptr_domain& domain = default_hazptr_domain())
: domain_(domain) {}
~SWMRListSet() { ~SWMRListSet() {
Node* next; Node* next;
for (auto p = head_.load(); p; p = next) { for (auto p = head_.load(); p; p = next) {
...@@ -97,14 +93,15 @@ class SWMRListSet { ...@@ -97,14 +93,15 @@ class SWMRListSet {
prev->store(curr_next, std::memory_order_release); prev->store(curr_next, std::memory_order_release);
// ...and only then null out the removed node. // ...and only then null out the removed node.
curr->next_.store(nullptr, std::memory_order_release); curr->next_.store(nullptr, std::memory_order_release);
curr->retire(domain_); curr->retire();
return true; return true;
} }
/* Used by readers */ /* Used by readers */
bool contains(const T& val) const { bool contains(const T& val) const {
/* Acquire two hazard pointers for hand-over-hand traversal. */ /* Acquire two hazard pointers for hand-over-hand traversal. */
hazptr_holder hptr_prev(domain_); hazptr_holder hptr_prev;
hazptr_holder hptr_curr(domain_); hazptr_holder hptr_curr;
while (true) { while (true) {
auto prev = &head_; auto prev = &head_;
auto curr = prev->load(std::memory_order_acquire); auto curr = prev->load(std::memory_order_acquire);
......
This diff is collapsed.
/*
* Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hazptr.h"
namespace folly {
namespace hazptr {
FOLLY_STATIC_CTOR_PRIORITY_MAX hazptr_domain default_domain_;
hazptr_stats hazptr_stats_;
thread_local hazptr_tls_state tls_state_ = TLS_UNINITIALIZED;
thread_local hazptr_tc tls_tc_data_;
thread_local hazptr_priv tls_priv_data_;
thread_local hazptr_tls_life tls_life_; // last
} // namespace hazptr
} // namespace folly
...@@ -51,7 +51,7 @@ class hazptr_domain { ...@@ -51,7 +51,7 @@ class hazptr_domain {
friend class hazptr_holder; friend class hazptr_holder;
template <typename, typename> template <typename, typename>
friend class hazptr_obj_base; friend class hazptr_obj_base;
friend class hazptr_priv; friend struct hazptr_priv;
memory_resource* mr_; memory_resource* mr_;
std::atomic<hazptr_rec*> hazptrs_ = {nullptr}; std::atomic<hazptr_rec*> hazptrs_ = {nullptr};
...@@ -71,12 +71,14 @@ class hazptr_domain { ...@@ -71,12 +71,14 @@ class hazptr_domain {
/** Get the default hazptr_domain */ /** Get the default hazptr_domain */
hazptr_domain& default_hazptr_domain(); hazptr_domain& default_hazptr_domain();
extern hazptr_domain default_domain_;
/** Definition of hazptr_obj */ /** Definition of hazptr_obj */
class hazptr_obj { class hazptr_obj {
friend class hazptr_domain; friend class hazptr_domain;
template <typename, typename> template <typename, typename>
friend class hazptr_obj_base; friend class hazptr_obj_base;
friend class hazptr_priv; friend struct hazptr_priv;
void (*reclaim_)(hazptr_obj*); void (*reclaim_)(hazptr_obj*);
hazptr_obj* next_; hazptr_obj* next_;
......
/*
* Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "memory_resource.h"
namespace folly {
namespace hazptr {
memory_resource** default_mr_ptr() {
/* library-local */ static memory_resource* default_mr =
new_delete_resource();
DEBUG_PRINT(&default_mr << " " << default_mr);
return &default_mr;
}
memory_resource* get_default_resource() {
DEBUG_PRINT("");
return *default_mr_ptr();
}
void set_default_resource(memory_resource* mr) {
DEBUG_PRINT("");
*default_mr_ptr() = mr;
}
memory_resource* new_delete_resource() {
class new_delete : public memory_resource {
public:
void* allocate(
const size_t bytes,
const size_t alignment = folly::max_align_v) override {
(void)alignment;
void* p = static_cast<void*>(new char[bytes]);
DEBUG_PRINT(this << " " << p << " " << bytes);
return p;
}
void deallocate(
void* p,
const size_t bytes,
const size_t alignment = folly::max_align_v) override {
(void)alignment;
(void)bytes;
DEBUG_PRINT(p << " " << bytes);
delete[] static_cast<char*>(p);
}
};
static new_delete mr;
return &mr;
}
} // namespace hazptr
} // namespace folly
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
/// std::pmr::memory_resource (C++17) as needed for developing a /// std::pmr::memory_resource (C++17) as needed for developing a
/// hazptr prototype. /// hazptr prototype.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include <folly/Portability.h> #include <folly/Portability.h>
#include <memory> #include <memory>
...@@ -44,51 +45,5 @@ memory_resource* get_default_resource(); ...@@ -44,51 +45,5 @@ memory_resource* get_default_resource();
void set_default_resource(memory_resource*); void set_default_resource(memory_resource*);
memory_resource* new_delete_resource(); memory_resource* new_delete_resource();
////////////////////////////////////////////////////////////////////////////////
/// Implementation
////////////////////////////////////////////////////////////////////////////////
inline memory_resource** default_mr_ptr() {
/* library-local */ static memory_resource* default_mr =
new_delete_resource();
DEBUG_PRINT(&default_mr << " " << default_mr);
return &default_mr;
}
inline memory_resource* get_default_resource() {
DEBUG_PRINT("");
return *default_mr_ptr();
}
inline void set_default_resource(memory_resource* mr) {
DEBUG_PRINT("");
*default_mr_ptr() = mr;
}
inline memory_resource* new_delete_resource() {
class new_delete : public memory_resource {
public:
void* allocate(
const size_t bytes,
const size_t alignment = folly::max_align_v) override {
(void)alignment;
void* p = static_cast<void*>(new char[bytes]);
DEBUG_PRINT(this << " " << p << " " << bytes);
return p;
}
void deallocate(
void* p,
const size_t bytes,
const size_t alignment = folly::max_align_v) override {
(void)alignment;
(void)bytes;
DEBUG_PRINT(p << " " << bytes);
delete[] static_cast<char*>(p);
}
};
static new_delete mr;
return &mr;
}
} // namespace folly } // namespace folly
} // namespace hazptr } // namespace hazptr
...@@ -198,12 +198,11 @@ TEST_F(HazptrTest, LIFO) { ...@@ -198,12 +198,11 @@ TEST_F(HazptrTest, LIFO) {
TEST_F(HazptrTest, SWMRLIST) { TEST_F(HazptrTest, SWMRLIST) {
using T = uint64_t; using T = uint64_t;
hazptr_domain custom_domain;
CHECK_GT(FLAGS_num_threads, 0); CHECK_GT(FLAGS_num_threads, 0);
for (int i = 0; i < FLAGS_num_reps; ++i) { for (int i = 0; i < FLAGS_num_reps; ++i) {
DEBUG_PRINT("========== start of rep scope"); DEBUG_PRINT("========== start of rep scope");
SWMRListSet<T> s(custom_domain); SWMRListSet<T> s;
std::vector<std::thread> threads(FLAGS_num_threads); std::vector<std::thread> threads(FLAGS_num_threads);
for (int tid = 0; tid < FLAGS_num_threads; ++tid) { for (int tid = 0; tid < FLAGS_num_threads; ++tid) {
threads[tid] = std::thread([&s, tid]() { threads[tid] = std::thread([&s, tid]() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment