1 // SPDX-FileCopyrightText: 2013 Mathieu Desnoyers <mathieu.desnoyers (at) efficios.com> 2 // 3 // SPDX-License-Identifier: MIT 4 5 /* 6 * This example shows how to dequeue nodes from a RCU lock-free queue. 7 * This queue requires using a RCU scheme. 8 */ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 13 #include <urcu/urcu-memb.h> /* RCU flavor */ 14 #include <urcu/rculfqueue.h> /* RCU Lock-free queue */ 15 #include <urcu/compiler.h> /* For CAA_ARRAY_SIZE */ 16 17 /* 18 * Nodes populated into the queue. 19 */ 20 struct mynode { 21 int value; /* Node content */ 22 struct cds_lfq_node_rcu node; /* Chaining in queue */ 23 struct rcu_head rcu_head; /* For call_rcu() */ 24 }; 25 26 static 27 void free_node(struct rcu_head *head) 28 { 29 struct mynode *node = 30 caa_container_of(head, struct mynode, rcu_head); 31 32 free(node); 33 } 34 35 int main(void) 36 { 37 int values[] = { -5, 42, 36, 24, }; 38 struct cds_lfq_queue_rcu myqueue; /* Queue */ 39 unsigned int i; 40 int ret = 0; 41 42 /* 43 * Each thread need using RCU read-side need to be explicitly 44 * registered. 45 */ 46 urcu_memb_register_thread(); 47 48 cds_lfq_init_rcu(&myqueue, urcu_memb_call_rcu); 49 50 /* 51 * Enqueue nodes. 52 */ 53 for (i = 0; i < CAA_ARRAY_SIZE(values); i++) { 54 struct mynode *node; 55 56 node = malloc(sizeof(*node)); 57 if (!node) { 58 ret = -1; 59 goto end; 60 } 61 62 cds_lfq_node_init_rcu(&node->node); 63 node->value = values[i]; 64 /* 65 * Both enqueue and dequeue need to be called within RCU 66 * read-side critical section. 67 */ 68 urcu_memb_read_lock(); 69 cds_lfq_enqueue_rcu(&myqueue, &node->node); 70 urcu_memb_read_unlock(); 71 } 72 73 /* 74 * Dequeue each node from the queue. Those will be dequeued from 75 * the oldest (first enqueued) to the newest (last enqueued). 76 */ 77 printf("dequeued content:"); 78 for (;;) { 79 struct cds_lfq_node_rcu *qnode; 80 struct mynode *node; 81 82 /* 83 * Both enqueue and dequeue need to be called within RCU 84 * read-side critical section. 85 */ 86 urcu_memb_read_lock(); 87 qnode = cds_lfq_dequeue_rcu(&myqueue); 88 urcu_memb_read_unlock(); 89 if (!qnode) { 90 break; /* Queue is empty. */ 91 } 92 /* Getting the container structure from the node */ 93 node = caa_container_of(qnode, struct mynode, node); 94 printf(" %d", node->value); 95 urcu_memb_call_rcu(&node->rcu_head, free_node); 96 } 97 printf("\n"); 98 /* 99 * Release memory used by the queue. 100 */ 101 ret = cds_lfq_destroy_rcu(&myqueue); 102 if (ret) { 103 printf("Error destroying queue (non-empty)\n"); 104 } 105 end: 106 urcu_memb_unregister_thread(); 107 return ret; 108 } 109