tests: Add tests for checking race conditions
[urcu.git] / tests / unit / test_wfcqueue.c
CommitLineData
59fdcc3a
OD
1/*
2 * test_wfcqueue.c
3 *
4 * Userspace RCU library - test wfcqueue race conditions
5 *
6 * Copyright 2023 - Olivier Dion <odion@efficios.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23#define _LGPL_SOURCE
24
25#include <stdlib.h>
26
27#include <pthread.h>
28
29#include <urcu/wfcqueue.h>
30
31#include "tap.h"
32
33#define NR_TESTS 1
34#define NR_PRODUCERS 4
35#define LOOP 100
36
37struct queue {
38 struct cds_wfcq_head head;
39 struct cds_wfcq_tail tail;
40};
41
42static void async_run(struct queue *queue)
43{
44 struct cds_wfcq_node *node = malloc(sizeof(*node));
45
46 cds_wfcq_node_init(node);
47
48 cds_wfcq_enqueue(&queue->head, &queue->tail, node);
49}
50static void do_async_loop(size_t *k, struct queue *queue)
51{
52 struct queue my_queue;
53 enum cds_wfcq_ret state;
54 struct cds_wfcq_node *node, *next;
55
56 cds_wfcq_init(&my_queue.head, &my_queue.tail);
57
58 state = cds_wfcq_splice_blocking(&my_queue.head,
59 &my_queue.tail,
60 &queue->head,
61 &queue->tail);
62
63 if (state == CDS_WFCQ_RET_SRC_EMPTY) {
64 return;
65 }
66
67 __cds_wfcq_for_each_blocking_safe(&my_queue.head,
68 &my_queue.tail,
69 node, next) {
70 free(node);
71 (*k)++;
72 }
73}
74
75static void *async_loop(void *queue)
76{
77 size_t k = 0;
78
79 while (k < LOOP * NR_PRODUCERS) {
80 (void) poll(NULL, 0, 10);
81 do_async_loop(&k, queue);
82 }
83
84 return NULL;
85}
86
87static void *spawn_jobs(void *queue)
88{
89 for (size_t k = 0; k < LOOP; ++k) {
90 async_run(queue);
91 }
92
93 return 0;
94}
95
96int main(void)
97{
98 pthread_t consumer;
99 pthread_t producers[NR_PRODUCERS];
100 struct queue queue;
101
102 plan_tests(NR_TESTS);
103
104 cds_wfcq_init(&queue.head, &queue.tail);
105 pthread_create(&consumer, NULL, async_loop, &queue);
106
107 for (size_t k = 0; k < NR_PRODUCERS; ++k) {
108 pthread_create(&producers[k], NULL, spawn_jobs, &queue);
109 }
110
111 pthread_join(consumer, NULL);
112 for (size_t k = 0; k < NR_PRODUCERS; ++k) {
113 pthread_join(producers[k], NULL);
114 }
115
116 ok1("No race conditions");
117
118 return exit_status();
119}
This page took 0.026481 seconds and 4 git commands to generate.