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