Commit a3c62f0c by Tobias Fuchs

containers_cpp: fixes in LlxScx, added unit test for LlxScx

parent a425b12e
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include <embb/base/thread.h> #include <embb/base/thread.h>
#include <embb/base/atomic.h> #include <embb/base/atomic.h>
#include <embb/base/thread_specific_storage.h> #include <embb/base/thread_specific_storage.h>
#include <embb/containers/object_pool.h>
#include <embb/containers/lock_free_tree_value_pool.h>
#include <embb/containers/internal/fixed_size_list.h> #include <embb/containers/internal/fixed_size_list.h>
namespace embb { namespace embb {
...@@ -42,7 +44,7 @@ namespace internal { ...@@ -42,7 +44,7 @@ namespace internal {
* SCX operation description. An SCX record contains all information * SCX operation description. An SCX record contains all information
* required to allow any process to complete a pending SCX operation. * required to allow any process to complete a pending SCX operation.
*/ */
template< class DataRecord > template< typename DataRecord >
class ScxRecord { class ScxRecord {
private: private:
...@@ -66,11 +68,11 @@ class ScxRecord { ...@@ -66,11 +68,11 @@ class ScxRecord {
*/ */
ScxRecord() ScxRecord()
: linked_data_records_(0), : linked_data_records_(0),
finalize_data_records_(0) finalize_data_records_(0),
new_value_(0), new_value_(0),
old_value_(0), old_value_(0),
scx_ops_(0), scx_ops_(0),
state_(OperationState::Undefined), state_(OperationState::Comitted),
all_frozen_(false) { all_frozen_(false) {
field_ = 0; field_ = 0;
} }
...@@ -84,7 +86,7 @@ class ScxRecord { ...@@ -84,7 +86,7 @@ class ScxRecord {
embb::base::Atomic<cas_t> * field, embb::base::Atomic<cas_t> * field,
cas_t new_value, cas_t new_value,
cas_t old_value, cas_t old_value,
embb::containers::internal::FixedSizeList<self_t *> * scx_ops, embb::containers::internal::FixedSizeList<self_t> * scx_ops,
OperationState operation_state) OperationState operation_state)
: linked_data_records_(&linked_data_records), : linked_data_records_(&linked_data_records),
finalize_data_records_(&finalize_data_records), finalize_data_records_(&finalize_data_records),
...@@ -143,7 +145,7 @@ class ScxRecord { ...@@ -143,7 +145,7 @@ class ScxRecord {
* List of SCX operation descriptions associated with data records * List of SCX operation descriptions associated with data records
* linked with this SCX operation. * linked with this SCX operation.
*/ */
embb::containers::internal::FixedSizeList<self_t *> scx_ops_; embb::containers::internal::FixedSizeList<self_t> * scx_ops_;
/** /**
* Current state of this SCX record. * Current state of this SCX record.
...@@ -165,7 +167,7 @@ class ScxRecord { ...@@ -165,7 +167,7 @@ class ScxRecord {
* Wraps user-defined data with fields required for LLX/SCX algorithm. * Wraps user-defined data with fields required for LLX/SCX algorithm.
* Mutable fields must each be contained in a single word. * Mutable fields must each be contained in a single word.
*/ */
template< class UserData > template< typename UserData >
class LlxScxRecord { class LlxScxRecord {
private: private:
...@@ -203,10 +205,13 @@ class LlxScxRecord { ...@@ -203,10 +205,13 @@ class LlxScxRecord {
* Assignment operator. * Assignment operator.
*/ */
LlxScxRecord & operator=(const LlxScxRecord & rhs) { LlxScxRecord & operator=(const LlxScxRecord & rhs) {
if (this != &rhs) {
user_data_ = rhs.user_data_; user_data_ = rhs.user_data_;
scx_op_.Store(rhs.scx_info_.Load()); scx_op_.Store(rhs.scx_op_.Load());
marked_for_finalize_ = rhs.marked_for_finalize_; marked_for_finalize_ = rhs.marked_for_finalize_;
} }
return *this;
}
/** /**
* Destructor. * Destructor.
...@@ -299,10 +304,13 @@ class LlxScxRecord { ...@@ -299,10 +304,13 @@ class LlxScxRecord {
* "Pragmatic Primitives for Non-blocking Data Structures" * "Pragmatic Primitives for Non-blocking Data Structures"
* (Brown et al., 2013). * (Brown et al., 2013).
* *
* \tparam MaxLinks Maximum number of active LL-dependencies per thread
* \tparam UserData Type containing mutable fields * \tparam UserData Type containing mutable fields
* \tparam ValuePool Type containing mutable fields
*/ */
template< class UserData > template<
typename UserData,
typename ValuePool = embb::containers::LockFreeTreeValuePool< bool, false >
>
class LlxScx { class LlxScx {
private: private:
...@@ -335,8 +343,7 @@ class LlxScx { ...@@ -335,8 +343,7 @@ class LlxScx {
DataRecord_t * const data_record, DataRecord_t * const data_record,
/**< [IN] Pointer to data record to load */ /**< [IN] Pointer to data record to load */
DataRecord_t & data, DataRecord_t & data,
/**< [OUT] Atomic snapshot of \c NumMutableFields fields in data /**< [OUT] Atomic snapshot of data record */
record at given index */
bool & finalized bool & finalized
/**< [OUT] Indicating whether requested fields have been finalized */ /**< [OUT] Indicating whether requested fields have been finalized */
); );
...@@ -393,6 +400,11 @@ class LlxScx { ...@@ -393,6 +400,11 @@ class LlxScx {
size_t max_links_; size_t max_links_;
/** /**
* Maximum number of threads engaging in operations on this LLX/SCX instance.
*/
unsigned int max_threads_;
/**
* Shared table containing for each r in V, a copy of r's info * Shared table containing for each r in V, a copy of r's info
* value in this thread's local table of LLX results. * value in this thread's local table of LLX results.
* *
...@@ -402,23 +414,38 @@ class LlxScx { ...@@ -402,23 +414,38 @@ class LlxScx {
* r_i in V -> *ScxRecord(thread_llx_results_[r_i].data_record.ScxInfo()) * r_i in V -> *ScxRecord(thread_llx_results_[r_i].data_record.ScxInfo())
* } * }
*/ */
embb::containers::internal::FixedSizeList<ScxRecord_t> * info_fields_; // embb::containers::internal::FixedSizeList<ScxRecord_t> * info_fields_;
/**
* Shared table containing for each r in V, a copy of r's info
* value in this thread's local table of LLX results.
*
* thread_id -> {
* r_1 in V -> *ScxRecord(thread_llx_results_[r_1].data_record.ScxInfo()),
* ...
* r_i in V -> *ScxRecord(thread_llx_results_[r_i].data_record.ScxInfo())
* }
*/
embb::containers::ObjectPool<
embb::containers::internal::FixedSizeList<ScxRecord_t>, ValuePool >
scx_record_list_pool_;
/** /**
* Thread-specific list of LLX results performed by the thread. * Thread-specific list of LLX results performed by the thread.
*/ */
embb::base::ThreadSpecificStorage< embb::containers::internal::FixedSizeList<LlxResult> *
embb::containers::internal::FixedSizeList<LlxResult> >
thread_llx_results_; thread_llx_results_;
/** /**
* Prevent default construction. * Prevent default construction.
*/ */
LlxScx(); LlxScx();
/** /**
* Prevent copy construction. * Prevent copy construction.
*/ */
LlxScx(const LlxScx &); LlxScx(const LlxScx &);
/** /**
* Prevent assignment. * Prevent assignment.
*/ */
......
...@@ -37,14 +37,13 @@ using embb::containers::primitives::LlxScxRecord; ...@@ -37,14 +37,13 @@ using embb::containers::primitives::LlxScxRecord;
using embb::containers::primitives::LlxScx; using embb::containers::primitives::LlxScx;
LlxScxTest::LlxScxTest() : LlxScxTest::LlxScxTest() :
num_threads_(static_cast<int> num_threads_(
(partest::TestSuite::GetDefaultNumThreads())) { static_cast<int>(partest::TestSuite::GetDefaultNumThreads())) {
CreateUnit("SerialTest").Add(&LlxScxTest::SerialTest, this); CreateUnit("SerialTest").Add(&LlxScxTest::SerialTest, this);
} }
void LlxScxTest::SerialTest() { void LlxScxTest::SerialTest() {
typedef LlxScxTest::Node Node; typedef LlxScxTest::Node Node;
// Global: // Global:
LlxScx<Node> llxscx(3); LlxScx<Node> llxscx(3);
...@@ -92,6 +91,12 @@ void LlxScxTest::SerialTest() { ...@@ -92,6 +91,12 @@ void LlxScxTest::SerialTest() {
linked_deps, // V: dependencies, must be LL'd before linked_deps, // V: dependencies, must be LL'd before
finalize_deps // R: Subsequence of V to be finalized finalize_deps // R: Subsequence of V to be finalized
)); ));
// Following LLX calls on finalized data records are
// expected to fail:
PT_ASSERT(!llxscx.TryLoadLinked(&dr2, l2, finalized));
PT_ASSERT(finalized);
PT_ASSERT(!llxscx.TryLoadLinked(&dr3, l3, finalized));
PT_ASSERT(finalized);
} }
} // namespace test } // namespace test
......
...@@ -66,11 +66,20 @@ class LlxScxTest : public partest::TestCase { ...@@ -66,11 +66,20 @@ class LlxScxTest : public partest::TestCase {
next_.Store(next_node); next_.Store(next_node);
} }
Node(const Node & other)
: value_(other.value_) {
next_.Store(other.next_.Load());
count_.Store(other.count_.Load());
}
Node & operator=(const Node & rhs) { Node & operator=(const Node & rhs) {
if (this != &rhs) {
count_.Store(rhs.count_.Load()); count_.Store(rhs.count_.Load());
next_.Store(rhs.next_.Load()); next_.Store(rhs.next_.Load());
value_ = rhs.value_; value_ = rhs.value_;
} }
return *this;
}
}; };
public: public:
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "./stack_test.h" #include "./stack_test.h"
#include "./hazard_pointer_test.h" #include "./hazard_pointer_test.h"
#include "./object_pool_test.h" #include "./object_pool_test.h"
#include "./llx_scx_test.h"
#define COMMA , #define COMMA ,
...@@ -55,6 +56,7 @@ using embb::containers::test::HazardPointerTest; ...@@ -55,6 +56,7 @@ using embb::containers::test::HazardPointerTest;
using embb::containers::test::QueueTest; using embb::containers::test::QueueTest;
using embb::containers::test::StackTest; using embb::containers::test::StackTest;
using embb::containers::test::ObjectPoolTest; using embb::containers::test::ObjectPoolTest;
using embb::containers::test::LlxScxTest;
PT_MAIN("Data Structures C++") { PT_MAIN("Data Structures C++") {
unsigned int max_threads = static_cast<unsigned int>( unsigned int max_threads = static_cast<unsigned int>(
...@@ -70,6 +72,7 @@ PT_MAIN("Data Structures C++") { ...@@ -70,6 +72,7 @@ PT_MAIN("Data Structures C++") {
PT_RUN(StackTest< LockFreeStack<int> >); PT_RUN(StackTest< LockFreeStack<int> >);
PT_RUN(ObjectPoolTest< LockFreeTreeValuePool<bool COMMA false > >); PT_RUN(ObjectPoolTest< LockFreeTreeValuePool<bool COMMA false > >);
PT_RUN(ObjectPoolTest< WaitFreeArrayValuePool<bool COMMA false> >); PT_RUN(ObjectPoolTest< WaitFreeArrayValuePool<bool COMMA false> >);
PT_RUN(LlxScxTest);
PT_EXPECT(embb_get_bytes_allocated() == 0); PT_EXPECT(embb_get_bytes_allocated() == 0);
} }
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 sign in to comment