Home | History | Annotate | Line # | Download | only in unit
test_wfcqueue.c revision 1.1
      1 // SPDX-FileCopyrightText: 2023 Olivier Dion <odion (at) efficios.com>
      2 //
      3 // SPDX-License-Identifier: GPL-2.0-or-later
      4 
      5 /*
      6  * test_wfcqueue.c
      7  *
      8  * Userspace RCU library - test wfcqueue race conditions
      9  */
     10 
     11 #define _LGPL_SOURCE
     12 
     13 #include <stdlib.h>
     14 
     15 #include <pthread.h>
     16 
     17 #include <urcu/wfcqueue.h>
     18 
     19 #include "tap.h"
     20 
     21 #define NR_TESTS 1
     22 #define NR_PRODUCERS 4
     23 #define LOOP 100
     24 
     25 struct queue {
     26 	struct cds_wfcq_head head;
     27 	struct cds_wfcq_tail tail;
     28 };
     29 
     30 static void async_run(struct queue *queue)
     31 {
     32 	struct cds_wfcq_node *node = malloc(sizeof(*node));
     33 
     34 	cds_wfcq_node_init(node);
     35 
     36 	cds_wfcq_enqueue(&queue->head, &queue->tail, node);
     37 }
     38 static void do_async_loop(size_t *k, struct queue *queue)
     39 {
     40 	struct queue my_queue;
     41 	enum cds_wfcq_ret state;
     42 	struct cds_wfcq_node *node, *next;
     43 
     44 	cds_wfcq_init(&my_queue.head, &my_queue.tail);
     45 
     46 	state = cds_wfcq_splice_blocking(&my_queue.head,
     47 					&my_queue.tail,
     48 					&queue->head,
     49 					&queue->tail);
     50 
     51 	if (state == CDS_WFCQ_RET_SRC_EMPTY) {
     52 		return;
     53 	}
     54 
     55 	__cds_wfcq_for_each_blocking_safe(&my_queue.head,
     56 					&my_queue.tail,
     57 					node, next) {
     58 		free(node);
     59 		(*k)++;
     60 	}
     61 }
     62 
     63 static void *async_loop(void *queue)
     64 {
     65 	size_t k = 0;
     66 
     67 	while (k < LOOP * NR_PRODUCERS) {
     68 		(void) poll(NULL, 0, 10);
     69 		do_async_loop(&k, queue);
     70 	}
     71 
     72 	return NULL;
     73 }
     74 
     75 static void *spawn_jobs(void *queue)
     76 {
     77 	for (size_t k = 0; k < LOOP; ++k) {
     78 		async_run(queue);
     79 	}
     80 
     81 	return 0;
     82 }
     83 
     84 int main(void)
     85 {
     86 	pthread_t consumer;
     87 	pthread_t producers[NR_PRODUCERS];
     88 	struct queue queue;
     89 
     90 	plan_tests(NR_TESTS);
     91 
     92 	cds_wfcq_init(&queue.head, &queue.tail);
     93 	pthread_create(&consumer, NULL, async_loop, &queue);
     94 
     95 	for (size_t k = 0; k < NR_PRODUCERS; ++k) {
     96 		pthread_create(&producers[k], NULL, spawn_jobs, &queue);
     97 	}
     98 
     99 	pthread_join(consumer, NULL);
    100 	for (size_t k = 0; k < NR_PRODUCERS; ++k) {
    101 		pthread_join(producers[k], NULL);
    102 	}
    103 
    104 	ok1("No race conditions");
    105 
    106 	return exit_status();
    107 }
    108