VLC 4.0.0-dev
rcu.h
Go to the documentation of this file.
1/**
2 * \file rcu.h Read-Copy-Update (RCU) declarations
3 * \ingroup rcu
4 */
5/*****************************************************************************
6 * Copyright © 2021 Rémi Denis-Courmont
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
22
23#ifndef VLC_RCU_H_
24#define VLC_RCU_H_
25
26#include <stdatomic.h>
27
28/**
29 * \defgroup rcu Read-Copy-Update synchronisation
30 * \ingroup threads
31 * The Read-Copy-Update (RCU) mechanism is a paradigm of memory synchronisation
32 * first popularised by the Linux kernel.
33 * It is essentially a mean to safely use atomic pointers, without encountering
34 * use-after-free and other lifecycle bugs.
35 *
36 * It is an advantageous substitute for
37 * the classic reader/writer lock with the following notable differences:
38 * - The read side is completely lock-free and wait-free.
39 * - The write side is guaranteed to make forward progress even if there are
40 * perpetually active readers, provided that all read sides are each
41 * individually finitely long.
42 * - The protected data consists of a single atomic object,
43 * typically an atomic pointer
44 * (not to be confused with a pointer to an atomic object).
45 * - There is no synchronisation object. RCU maintains its state globally,
46 * and with a modicum of per-thread state.
47 *
48 * The practical use of RCU differs from reader/writer lock in the following
49 * ways:
50 * - There is no synchronisation object, so there are no needs for
51 * initialisation and destruction.
52 * - The directly protected objects are atom, so they must be accessed with
53 * atomic type-generics. Specifically:
54 * - Objects are read with atomic load-acquire.
55 * - Objects are written with atomic store-release.
56 * - There are no writer lock and unlock functions. Instead there is a
57 * synchronisation function, vlc_rcu_synchronize(), which waits for all
58 * earlier read-side critical sections to complete.
59 * - Synchronisation between concurrent writers is not provided. If multiple
60 * writers can race against each other, a separate mutual exclusion lock
61 * for interlocking.
62 *
63 * @{
64 */
65
66/**
67 * Begins a read-side RCU critical section.
68 *
69 * This function marks the beginning of a read-side RCU critical section.
70 * For the duration of the critical section, RCU-protected data is guaranteed
71 * to remain valid, although it might be slightly stale.
72 *
73 * To access RCU-protect data, an atomic load-acquire should be used.
74 *
75 * \note Read-side RCU critical section can be nested.
76 */
77void vlc_rcu_read_lock(void);
78
79/**
80 * Ends a read-side RCU critical section.
81 *
82 * This function marks the end of a read-side RCU critical section. After this
83 * function is called, RCU-protected data may be destroyed and can no longer
84 * be accessed safely.
85 *
86 * \note In the case of nested critical sections, this function notionally ends
87 * the inner-most critical section. In practice, this makes no differences, as
88 * the calling thread remains in a critical section until the number of
89 * vlc_rcu_read_unlock() calls equals that of vlc_rcu_read_lock() calls.
90 */
91void vlc_rcu_read_unlock(void);
92
93/**
94 * Checks if the thread is in an read-side RCU critical section.
95 *
96 * This function checks if the thread is in a middle of one or more read-side
97 * RCU critical section(s). It has no side effects and is primarily meant for
98 * self-debugging.
99 *
100 * \retval true the calling thread is in a read-side RCU critical section.
101 * \retval false the calling thread is not in a read-side RCU critical section.
102 */
104bool vlc_rcu_read_held(void);
105
106/**
107 * Waits for completion of earlier read-side RCU critical section.
108 *
109 * This functions waits until all read-side RCU critical sections that had
110 * begun before to complete. Then it is safe to release resources associated
111 * with the earlier value(s) of any RCU-protected atomic object.
112 */
113void vlc_rcu_synchronize(void);
114
115/** @} */
116#endif /* !VLC_RCU_H_ */
#define VLC_USED
Definition: fourcc_gen.c:32
void vlc_rcu_read_unlock(void)
Ends a read-side RCU critical section.
Definition: rcu.c:69
void vlc_rcu_synchronize(void)
Waits for completion of earlier read-side RCU critical section.
Definition: rcu.c:98
VLC_USED bool vlc_rcu_read_held(void)
Checks if the thread is in an read-side RCU critical section.
Definition: rcu.c:46
void vlc_rcu_read_lock(void)
Begins a read-side RCU critical section.
Definition: rcu.c:55