~lttng/urcu/trunk

« back to all changes in this revision

Viewing changes to doc/examples/urcu-flavors/signal.c

  • Committer: Mathieu Desnoyers
  • Date: 2023-08-21 18:14:30 UTC
  • Revision ID: git-v1:3d003c571cd461aba1935e5d21e1e04da7183970
doc/examples: Remove urcu-signal example

Remove the urcu-signal example from documentation.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: I6497855e63f39420cb1ffa44e07c2cbf5d39c791

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// SPDX-FileCopyrightText: 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
2
 
//
3
 
// SPDX-License-Identifier: LGPL-2.1-or-later
4
 
 
5
 
#include <unistd.h>
6
 
#include <stdlib.h>
7
 
#include <stdio.h>
8
 
#include <stdint.h>
9
 
#include <inttypes.h>
10
 
 
11
 
#include <urcu/urcu-signal.h>   /* Signal-based RCU flavor */
12
 
#include <urcu/rculist.h>       /* List example */
13
 
#include <urcu/compiler.h>      /* For CAA_ARRAY_SIZE */
14
 
 
15
 
/*
16
 
 * Example showing how to use the signal-based Userspace RCU flavor.
17
 
 *
18
 
 * This is a mock-up example where updates and RCU traversals are
19
 
 * performed by the same thread to keep things simple on purpose.
20
 
 */
21
 
 
22
 
static CDS_LIST_HEAD(mylist);
23
 
 
24
 
struct mynode {
25
 
        uint64_t value;
26
 
        struct cds_list_head node;      /* linked-list chaining */
27
 
        struct rcu_head rcu_head;       /* for call_rcu() */
28
 
};
29
 
 
30
 
static
31
 
int add_node(uint64_t v)
32
 
{
33
 
        struct mynode *node;
34
 
 
35
 
        node = calloc(sizeof(*node), 1);
36
 
        if (!node)
37
 
                return -1;
38
 
        node->value = v;
39
 
        cds_list_add_rcu(&node->node, &mylist);
40
 
        return 0;
41
 
}
42
 
 
43
 
static
44
 
void rcu_free_node(struct rcu_head *rh)
45
 
{
46
 
        struct mynode *node = caa_container_of(rh, struct mynode, rcu_head);
47
 
 
48
 
        free(node);
49
 
}
50
 
 
51
 
int main(void)
52
 
{
53
 
        uint64_t values[] = { 42, 36, 24, };
54
 
        unsigned int i;
55
 
        int ret;
56
 
        struct mynode *node, *n;
57
 
 
58
 
        /*
59
 
         * Each thread need using RCU read-side need to be explicitly
60
 
         * registered.
61
 
         */
62
 
        urcu_signal_register_thread();
63
 
 
64
 
        /*
65
 
         * Adding nodes to the linked-list. Safe against concurrent
66
 
         * RCU traversals, require mutual exclusion with list updates.
67
 
         */
68
 
        for (i = 0; i < CAA_ARRAY_SIZE(values); i++) {
69
 
                ret = add_node(values[i]);
70
 
                if (ret)
71
 
                        goto end;
72
 
        }
73
 
 
74
 
        /*
75
 
         * We need to explicitly mark RCU read-side critical sections
76
 
         * with rcu_read_lock() and rcu_read_unlock(). They can be
77
 
         * nested. Those are no-ops for the QSBR flavor.
78
 
         */
79
 
        urcu_signal_read_lock();
80
 
 
81
 
        /*
82
 
         * RCU traversal of the linked list.
83
 
         */
84
 
        cds_list_for_each_entry_rcu(node, &mylist, node) {
85
 
                printf("Value: %" PRIu64 "\n", node->value);
86
 
        }
87
 
        urcu_signal_read_unlock();
88
 
 
89
 
        /*
90
 
         * Removing nodes from linked list. Safe against concurrent RCU
91
 
         * traversals, require mutual exclusion with list updates.
92
 
         */
93
 
        cds_list_for_each_entry_safe(node, n, &mylist, node) {
94
 
                cds_list_del_rcu(&node->node);
95
 
                /*
96
 
                 * call_rcu() will ensure that the handler
97
 
                 * "rcu_free_node" is executed after a grace period.
98
 
                 * call_rcu() can be called from RCU read-side critical
99
 
                 * sections.
100
 
                 */
101
 
                urcu_signal_call_rcu(&node->rcu_head, rcu_free_node);
102
 
        }
103
 
 
104
 
        /*
105
 
         * We can also wait for a quiescent state by calling
106
 
         * synchronize_rcu() rather than using call_rcu(). It is usually
107
 
         * a slower approach than call_rcu(), because the latter can
108
 
         * batch work. Moreover, call_rcu() can be called from a RCU
109
 
         * read-side critical section, but synchronize_rcu() should not.
110
 
         */
111
 
        urcu_signal_synchronize_rcu();
112
 
 
113
 
        sleep(1);
114
 
 
115
 
        /*
116
 
         * Waiting for previously called call_rcu handlers to complete
117
 
         * before program exits, or in library destructors, is a good
118
 
         * practice.
119
 
         */
120
 
        urcu_signal_barrier();
121
 
 
122
 
end:
123
 
        urcu_signal_unregister_thread();
124
 
        return ret;
125
 
}