[lttng-dev] [PATCH v2 12/12] tests: Add tests for checking race conditions

Olivier Dion via lttng-dev <[email protected]>
Newsgroups org.lttng.lists.lttng-dev
Message-ID <[email protected]>
These tests do nothing useful except of stress testing a
single-consumer, multiple-producers program on various data structures.

These tests are only meaningful when compiling liburcu with TSAN.

Change-Id: If22b27ed0fb95bf890947fc4e75f923edb5ada8f
Signed-off-by: Olivier Dion <[email protected]>
---
 tests/unit/test_lfstack.c  |  90 ++++++++++++++++++++++++++++
 tests/unit/test_wfcqueue.c | 119 +++++++++++++++++++++++++++++++++++++
 tests/unit/test_wfqueue.c  |  91 ++++++++++++++++++++++++++++
 tests/unit/test_wfstack.c  |  90 ++++++++++++++++++++++++++++
 4 files changed, 390 insertions(+)
 create mode 100644 tests/unit/test_lfstack.c
 create mode 100644 tests/unit/test_wfcqueue.c
 create mode 100644 tests/unit/test_wfqueue.c
 create mode 100644 tests/unit/test_wfstack.c

diff --git a/tests/unit/test_lfstack.c b/tests/unit/test_lfstack.c
new file mode 100644
index 0000000..a1f99f0
--- /dev/null
+++ b/tests/unit/test_lfstack.c
@@ -0,0 +1,90 @@
+/*
+ * test_lfstack.c
+ *
+ * Userspace RCU library - test wftack race conditions
+ *
+ * Copyright 2023 - Olivier Dion <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _LGPL_SOURCE
+
+#include <stdlib.h>
+
+#include <pthread.h>
+
+#include <urcu/lfstack.h>
+
+#include "tap.h"
+
+#define NR_TESTS 1
+#define NR_PRODUCERS 4
+#define LOOP 100
+
+static void async_run(struct cds_lfs_stack *queue)
+{
+	struct cds_lfs_node *node = malloc(sizeof(*node));
+
+	cds_lfs_node_init(node);
+
+	cds_lfs_push(queue, node);
+}
+
+static void *async_loop(void *queue)
+{
+	size_t k = 0;
+
+	while (k < LOOP * NR_PRODUCERS) {
+		free(cds_lfs_pop_blocking(queue));
+		++k;
+	}
+
+	return NULL;
+}
+
+static void *spawn_jobs(void *queue)
+{
+	for (size_t k = 0; k < LOOP; ++k) {
+		async_run(queue);
+	}
+
+	return 0;
+}
+
+int main(void)
+{
+	pthread_t consumer;
+	pthread_t producers[NR_PRODUCERS];
+	struct cds_lfs_stack queue;
+
+	plan_tests(NR_TESTS);
+
+	cds_lfs_init(&queue);
+	pthread_create(&consumer, NULL, async_loop, &queue);
+
+	for (size_t k = 0; k < NR_PRODUCERS; ++k) {
+		pthread_create(&producers[k], NULL, spawn_jobs, &queue);
+	}
+
+	pthread_join(consumer, NULL);
+	for (size_t k = 0; k < NR_PRODUCERS; ++k) {
+		pthread_join(producers[k], NULL);
+	}
+
+	ok1("No race conditions");
+
+	return exit_status();
+}
diff --git a/tests/unit/test_wfcqueue.c b/tests/unit/test_wfcqueue.c
new file mode 100644
index 0000000..338aa07
--- /dev/null
+++ b/tests/unit/test_wfcqueue.c
@@ -0,0 +1,119 @@
+/*
+ * test_wfcqueue.c
+ *
+ * Userspace RCU library - test wfcqueue race conditions
+ *
+ * Copyright 2023 - Olivier Dion <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _LGPL_SOURCE
+
+#include <stdlib.h>
+
+#include <pthread.h>
+
+#include <urcu/wfcqueue.h>
+
+#include "tap.h"
+
+#define NR_TESTS 1
+#define NR_PRODUCERS 4
+#define LOOP 100
+
+struct queue {
+	struct cds_wfcq_head head;
+	struct cds_wfcq_tail tail;
+};
+
+static void async_run(struct queue *queue)
+{
+	struct cds_wfcq_node *node = malloc(sizeof(*node));
+
+	cds_wfcq_node_init(node);
+
+	cds_wfcq_enqueue(&queue->head, &queue->tail, node);
+}
+static void do_async_loop(size_t *k, struct queue *queue)
+{
+	struct queue my_queue;
+	enum cds_wfcq_ret state;
+	struct cds_wfcq_node *node, *next;
+
+	cds_wfcq_init(&my_queue.head, &my_queue.tail);
+
+	state = cds_wfcq_splice_blocking(&my_queue.head,
+					&my_queue.tail,
+					&queue->head,
+					&queue->tail);
+
+	if (state == CDS_WFCQ_RET_SRC_EMPTY) {
+		return;
+	}
+
+	__cds_wfcq_for_each_blocking_safe(&my_queue.head,
+					&my_queue.tail,
+					node, next) {
+		free(node);
+		(*k)++;
+	}
+}
+
+static void *async_loop(void *queue)
+{
+	size_t k = 0;
+
+	while (k < LOOP * NR_PRODUCERS) {
+		(void) poll(NULL, 0, 10);
+		do_async_loop(&k, queue);
+	}
+
+	return NULL;
+}
+
+static void *spawn_jobs(void *queue)
+{
+	for (size_t k = 0; k < LOOP; ++k) {
+		async_run(queue);
+	}
+
+	return 0;
+}
+
+int main(void)
+{
+	pthread_t consumer;
+	pthread_t producers[NR_PRODUCERS];
+	struct queue queue;
+
+	plan_tests(NR_TESTS);
+
+	cds_wfcq_init(&queue.head, &queue.tail);
+	pthread_create(&consumer, NULL, async_loop, &queue);
+
+	for (size_t k = 0; k < NR_PRODUCERS; ++k) {
+		pthread_create(&producers[k], NULL, spawn_jobs, &queue);
+	}
+
+	pthread_join(consumer, NULL);
+	for (size_t k = 0; k < NR_PRODUCERS; ++k) {
+		pthread_join(producers[k], NULL);
+	}
+
+	ok1("No race conditions");
+
+	return exit_status();
+}
diff --git a/tests/unit/test_wfqueue.c b/tests/unit/test_wfqueue.c
new file mode 100644
index 0000000..57afaba
--- /dev/null
+++ b/tests/unit/test_wfqueue.c
@@ -0,0 +1,91 @@
+/*
+ * test_wfqueue.c
+ *
+ * Userspace RCU library - test wfqueue race conditions
+ *
+ * Copyright 2023 - Olivier Dion <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _LGPL_SOURCE
+
+#include <stdlib.h>
+
+#include <pthread.h>
+
+#define CDS_WFQ_DEPRECATED
+#include <urcu/wfqueue.h>
+
+#include "tap.h"
+
+#define NR_TESTS 1
+#define NR_PRODUCERS 4
+#define LOOP 100
+
+static void async_run(struct cds_wfq_queue *queue)
+{
+	struct cds_wfq_node *node = malloc(sizeof(*node));
+
+	cds_wfq_node_init(node);
+
+	cds_wfq_enqueue(queue, node);
+}
+
+static void *async_loop(void *queue)
+{
+	size_t k = 0;
+
+	while (k < LOOP * NR_PRODUCERS) {
+		free(cds_wfq_dequeue_blocking(queue));
+		++k;
+	}
+
+	return NULL;
+}
+
+static void *spawn_jobs(void *queue)
+{
+	for (size_t k = 0; k < LOOP; ++k) {
+		async_run(queue);
+	}
+
+	return 0;
+}
+
+int main(void)
+{
+	pthread_t consumer;
+	pthread_t producers[NR_PRODUCERS];
+	struct cds_wfq_queue queue;
+
+	plan_tests(NR_TESTS);
+
+	cds_wfq_init(&queue);
+	pthread_create(&consumer, NULL, async_loop, &queue);
+
+	for (size_t k = 0; k < NR_PRODUCERS; ++k) {
+		pthread_create(&producers[k], NULL, spawn_jobs, &queue);
+	}
+
+	pthread_join(consumer, NULL);
+	for (size_t k = 0; k < NR_PRODUCERS; ++k) {
+		pthread_join(producers[k], NULL);
+	}
+
+	ok1("No race conditions");
+
+	return exit_status();
+}
diff --git a/tests/unit/test_wfstack.c b/tests/unit/test_wfstack.c
new file mode 100644
index 0000000..578ae92
--- /dev/null
+++ b/tests/unit/test_wfstack.c
@@ -0,0 +1,90 @@
+/*
+ * test_wfstack.c
+ *
+ * Userspace RCU library - test wftack race conditions
+ *
+ * Copyright 2023 - Olivier Dion <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _LGPL_SOURCE
+
+#include <stdlib.h>
+
+#include <pthread.h>
+
+#include <urcu/wfstack.h>
+
+#include "tap.h"
+
+#define NR_TESTS 1
+#define NR_PRODUCERS 4
+#define LOOP 100
+
+static void async_run(struct cds_wfs_stack *queue)
+{
+	struct cds_wfs_node *node = malloc(sizeof(*node));
+
+	cds_wfs_node_init(node);
+
+	cds_wfs_push(queue, node);
+}
+
+static void *async_loop(void *queue)
+{
+	size_t k = 0;
+
+	while (k < LOOP * NR_PRODUCERS) {
+		free(cds_wfs_pop_blocking(queue));
+		++k;
+	}
+
+	return NULL;
+}
+
+static void *spawn_jobs(void *queue)
+{
+	for (size_t k = 0; k < LOOP; ++k) {
+		async_run(queue);
+	}
+
+	return 0;
+}
+
+int main(void)
+{
+	pthread_t consumer;
+	pthread_t producers[NR_PRODUCERS];
+	struct cds_wfs_stack queue;
+
+	plan_tests(NR_TESTS);
+
+	cds_wfs_init(&queue);
+	pthread_create(&consumer, NULL, async_loop, &queue);
+
+	for (size_t k = 0; k < NR_PRODUCERS; ++k) {
+		pthread_create(&producers[k], NULL, spawn_jobs, &queue);
+	}
+
+	pthread_join(consumer, NULL);
+	for (size_t k = 0; k < NR_PRODUCERS; ++k) {
+		pthread_join(producers[k], NULL);
+	}
+
+	ok1("No race conditions");
+
+	return exit_status();
+}
-- 
2.40.1

_______________________________________________
lttng-dev mailing list
[email protected]
https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.