Skip to content
Snippets Groups Projects
Commit 2f4a77ce authored by Florian Fischer's avatar Florian Fischer
Browse files

[test] add test using liburcu

The SimpleURCUTest creates a lock-less hash table and inserts values from
separate fibers and verifies the correct insertion.
parent 329c41c3
No related branches found
No related tags found
No related merge requests found
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright © 2020 Florian Fischer
#include <urcu.h> // for rcu_read_lock, rcu_read_unlock
#include <urcu/rculfhash.h> // for RCU lock-free hash table
#include <algorithm> // for find
#include <cstdlib> // for exit, EXIT_FAILURE, EXIT_SUC...
#include <functional> // for hash
#include <iostream> // for hash
#include <vector> // for vector
#include "Common.hpp" // for die
#include "CountingPrivateSemaphore.hpp" // for CPS
#include "Fiber.hpp" // for Fiber
#include "Runtime.hpp" // for Runtime
#include "emper.hpp" // for spawn
struct node {
int value;
struct cds_lfht_node node; /* Chaining in hash table */
};
using node_t = struct node;
auto main() -> int {
Runtime runtime;
struct cds_lfht* ht;
std::vector<int> values = {
-5, 42, 42, 36, 24,
}; /* 42 is duplicated */
// Allocate new hash table.
ht = cds_lfht_new(1, 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, nullptr);
if (!ht) {
die("Error allocating hash table", false);
}
Fiber* verifier = Fiber::from([&]() {
CPS cps;
for (auto& value : values) {
// add each value to the hash table
spawn(
[&ht, value] {
auto* node = reinterpret_cast<node_t*>(malloc(sizeof(node_t)));
if (!node) {
die("allocating node failed", true);
}
cds_lfht_node_init(&node->node);
node->value = value;
size_t hash = std::hash<int>{}(value);
rcu_read_lock();
cds_lfht_add(ht, hash, &node->node);
rcu_read_unlock();
},
cps);
}
// Wait for the adders to finish
cps.wait();
// Verify the content of the hash table.
// Iterate over each hash table node.
// Iteration needs to be performed within RCU read-side critical section.
struct cds_lfht_iter iter;
node_t* node;
rcu_read_lock();
size_t i = 0;
cds_lfht_for_each_entry(ht, &iter, node, node) {
++i;
auto it = std::find(values.begin(), values.end(), node->value);
if (it == values.end()) {
std::cerr << "value: " << node->value << " not found in cds_lfht" << std::endl;
exit(EXIT_FAILURE);
}
}
rcu_read_unlock();
if (i != values.size()) {
std::cerr << "number of values in cds_lfht: " << i
<< " differ number of added ones: " << values.size() << std::endl;
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
});
runtime.schedule(*verifier);
runtime.waitUntilFinished();
return EXIT_FAILURE;
}
cc = meson.get_compiler('c')
liburcu_memb = cc.find_library('urcu-memb')
liburcu_cds = cc.find_library('urcu-cds')
tests = { tests = {
'SimpleFibTest.cpp': 'SimpleFibTest.cpp':
{ {
...@@ -29,10 +33,14 @@ tests = { ...@@ -29,10 +33,14 @@ tests = {
{ {
'description': 'Simple LAWS scheduling strategy test', 'description': 'Simple LAWS scheduling strategy test',
}, },
'SimpleURCUTest.cpp':
{
'description': 'Simple userspace-rcu hash table test',
'dependencies': [liburcu_memb, liburcu_cds]
},
} }
undef_ndebug = '-UNDEBUG' undef_ndebug = '-UNDEBUG'
test_dep = [thread_dep]
test_env = environment( test_env = environment(
{ {
# Set glibc's MALLOC_PERTURB to 1. This means that newly allocated # Set glibc's MALLOC_PERTURB to 1. This means that newly allocated
...@@ -50,12 +58,17 @@ foreach source, test_dict : tests ...@@ -50,12 +58,17 @@ foreach source, test_dict : tests
# The test_name is the name of the source file without the file suffix. # The test_name is the name of the source file without the file suffix.
test_name = source.split('.')[0] test_name = source.split('.')[0]
test_dep = [thread_dep]
if test_dict.has_key('dependencies')
test_dep += test_dict['dependencies']
endif
test_exe = executable(test_name, test_exe = executable(test_name,
source, source,
include_directories: emper_all_include, include_directories: emper_all_include,
c_args: undef_ndebug, c_args: undef_ndebug,
cpp_args: undef_ndebug, cpp_args: undef_ndebug,
dependencies: test_dep, dependencies: emper_dependencies + test_dep,
link_with: [emper, emper_c], link_with: [emper, emper_c],
) )
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment