diff --git a/tests/BinaryPrivateSemaphoreTest.cpp b/tests/BinaryPrivateSemaphoreTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fddddc547ae6f7b0ee97ac110cc99efa4b083a9e
--- /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 f976cf881c26e027cdd656e0846d3271a0a5f372..8204a0b7602990d0d968049febcfdb84f7ebaff4 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',