From 65a593bcceb3d0de4febf0c65a6ac38d9aff3959 Mon Sep 17 00:00:00 2001
From: Florian Fischer <florian.fischer@muhq.space>
Date: Tue, 23 Nov 2021 15:44:38 +0100
Subject: [PATCH] add concurrent BPS test

The test introduces multiple cycles of Semaphores and
a Fiber for each semaphore blocking and signaling the next.
Through work-stealing the fibers from a cycle should be spread
across different workers and thus test concurrent use of
BinaryPrivateSemaphores.

Cycle of length 3: Sem A -> Sem B -> Sem C -> Sem A -> ...
Algorithm:
	if isFirstInCycle
		signal next

	wait

	if not isFirstInCycle
		signal next
---
 tests/BinaryPrivateSemaphoreTest.cpp | 43 ++++++++++++++++++++++++++++
 tests/meson.build                    |  7 +++++
 2 files changed, 50 insertions(+)
 create mode 100644 tests/BinaryPrivateSemaphoreTest.cpp

diff --git a/tests/BinaryPrivateSemaphoreTest.cpp b/tests/BinaryPrivateSemaphoreTest.cpp
new file mode 100644
index 00000000..fddddc54
--- /dev/null
+++ b/tests/BinaryPrivateSemaphoreTest.cpp
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: LGPL-3.0-or-later
+// Copyright © 2021 Florian Fischer
+#include "BinaryPrivateSemaphore.hpp"
+#include "CountingPrivateSemaphore.hpp"
+#include "Debug.hpp"
+#include "emper-config.h"
+#include "emper.hpp"
+
+static BPS* sems;
+
+static const unsigned CYCLE_LENGTH = 3;
+static const unsigned CYCLE_COUNT = 100;
+static const unsigned ITERATIONS = EMPER_LOG_LEVEL > Info ? 100 : 25000;
+
+void emperTest() {
+	CPS cps;
+	const unsigned count = CYCLE_COUNT * CYCLE_LENGTH;
+	sems = new BPS[count];
+	for (unsigned i = 0; i < count; ++i) {
+		spawn(
+				[=] {
+					const unsigned cycleNum = i / CYCLE_LENGTH;
+					const unsigned cycleStart = CYCLE_LENGTH * cycleNum;
+					BPS& mySem = sems[i];
+					const unsigned next = cycleStart + ((i + 1) % CYCLE_LENGTH);
+					BPS& nextSem = sems[next];
+
+					for (unsigned it = 0; it < ITERATIONS; ++it) {
+						if (i == cycleStart) nextSem.signal();
+
+						mySem.wait();
+						mySem.reset();
+
+						if (i != cycleStart) nextSem.signal();
+					}
+				},
+				cps);
+	}
+
+	cps.wait();
+
+	delete[] sems;
+}
diff --git a/tests/meson.build b/tests/meson.build
index f976cf88..8204a0b7 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -87,6 +87,13 @@ tests = [
 		'dependencies': [liburcu_memb, liburcu_cds]
 	},
 
+	{
+		'source': files('BinaryPrivateSemaphoreTest.cpp'),
+		'name': 'BinaryPrivateSemaphoreTest',
+		'description': 'Concurrent test for BinrayPrivateSemaphores',
+		'test_runner': 'emper',
+	},
+
 	{
 		'source': files('SignalPrivateSemaphoreFromAnywhereTest.cpp'),
 		'name': 'SignalPrivateSemaphoreFromAnywhereTest',
-- 
GitLab