Coverage Report

Created: 2025-07-11 06:11

/src/openvswitch/lib/rculist.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2014 Nicira, Inc.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at:
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
#ifndef RCULIST_H
17
#define RCULIST_H 1
18
19
/* A single writer multiple RCU-reader doubly linked list.
20
 *
21
 * RCU readers may iterate over the list at the same time as a writer is
22
 * modifying the list.  Multiple writers can be supported by use of mutual
23
 * exclusion, but rculist does not provide that, as the user of rculist
24
 * typically does that already.
25
 *
26
 * To be RCU-friendly, the struct rculist instances must be freed via
27
 * ovsrcu_postpone().
28
 *
29
 * The API is almost the same as for struct ovs_list, with the following
30
 * exceptions:
31
 *
32
 * - The 'prev' pointer may not be accessed by the user.
33
 * - The 'next' pointer should be accessed via rculist_next() by readers, and
34
 *   rculist_next_protected() by the writer.
35
 * - No rculist_moved(): due to the memory management limitation stated above,
36
 *   rculist instances may not be reallocated, as realloc may instantly free
37
 *   the old memory.
38
 * - rculist_front() returns a const pointer to accommodate for an RCU reader.
39
 * - rculist_splice_hidden(): Spliced elements may not have been visible to
40
 *   RCU readers before the operation.
41
 * - rculist_poison(): Only poisons the 'prev' pointer.
42
 *
43
 * The following functions are variations of the struct ovs_list functions with
44
 * similar names, but are now restricted to the writer use:
45
 *
46
 * - rculist_back_protected()
47
 * - rculist_is_short_protected()
48
 * - rculist_is_singleton_protected()
49
 */
50
51
#include <stdbool.h>
52
#include <stddef.h>
53
#include "ovs-rcu.h"
54
#include "util.h"
55
56
/* A non-existing mutex to make it more difficult for an user to accidentally
57
 * keep using the 'prev' pointer.  This may be helpful when porting code from
58
 * struct ovs_list to rculist. */
59
extern struct ovs_mutex rculist_fake_mutex;
60
61
/* Doubly linked list head or element. */
62
struct rculist {
63
    /* Previous list element. */
64
    struct rculist *prev OVS_GUARDED_BY(rculist_fake_mutex);
65
66
    /* Next list element. */
67
    OVSRCU_TYPE(struct rculist *) next;
68
};
69
70
/* Easier access to 'next' member. */
71
static inline const struct rculist *rculist_next(const struct rculist *);
72
static inline struct rculist *rculist_next_protected(const struct rculist *);
73
74
/* List initialization. */
75
#define RCUOVS_LIST_INITIALIZER(LIST) { LIST, OVSRCU_INITIALIZER(LIST) }
76
77
static inline void rculist_init(struct rculist *list);
78
static inline void rculist_poison(struct rculist *elem);
79
80
/* List insertion. */
81
static inline void rculist_insert(struct rculist *list, struct rculist *elem);
82
static inline void rculist_splice_hidden(struct rculist *before,
83
                                         struct rculist *first,
84
                                         struct rculist *last);
85
static inline void rculist_push_front(struct rculist *list,
86
                                      struct rculist *elem);
87
static inline void rculist_push_back(struct rculist *list,
88
                                     struct rculist *elem);
89
static inline void rculist_replace(struct rculist *replacement,
90
                                   struct rculist *replaced);
91
static inline void rculist_move(struct rculist *dst, struct rculist *src);
92
93
/* List removal. */
94
static inline struct rculist *rculist_remove(struct rculist *elem);
95
static inline struct rculist *rculist_pop_front(struct rculist *list);
96
static inline struct rculist *rculist_pop_back(struct rculist *list);
97
98
/* List elements. */
99
static inline const struct rculist *rculist_front(const struct rculist *);
100
static inline struct rculist *rculist_back_protected(const struct rculist *);
101
102
/* List properties. */
103
static inline size_t rculist_size(const struct rculist *);
104
static inline bool rculist_is_empty(const struct rculist *);
105
static inline bool rculist_is_singleton_protected(const struct rculist *);
106
static inline bool rculist_is_short_protected(const struct rculist *);
107
108

109
/* Inline implementations. */
110
111
static inline const struct rculist *
112
rculist_next(const struct rculist *list)
113
0
{
114
0
    return ovsrcu_get(struct rculist *, &list->next);
115
0
}
Unexecuted instantiation: meta-flow.c:rculist_next
Unexecuted instantiation: nx-match.c:rculist_next
Unexecuted instantiation: ofp-util.c:rculist_next
Unexecuted instantiation: ovs-router.c:rculist_next
Unexecuted instantiation: tnl-ports.c:rculist_next
Unexecuted instantiation: classifier.c:rculist_next
Unexecuted instantiation: conntrack.c:rculist_next
Unexecuted instantiation: conntrack-icmp.c:rculist_next
Unexecuted instantiation: conntrack-tcp.c:rculist_next
Unexecuted instantiation: conntrack-tp.c:rculist_next
Unexecuted instantiation: conntrack-other.c:rculist_next
116
117
static inline struct rculist *
118
rculist_next_protected(const struct rculist *list)
119
120
0
{
121
0
    return ovsrcu_get_protected(struct rculist *, &list->next);
122
0
}
Unexecuted instantiation: meta-flow.c:rculist_next_protected
Unexecuted instantiation: nx-match.c:rculist_next_protected
Unexecuted instantiation: ofp-util.c:rculist_next_protected
Unexecuted instantiation: ovs-router.c:rculist_next_protected
Unexecuted instantiation: tnl-ports.c:rculist_next_protected
Unexecuted instantiation: classifier.c:rculist_next_protected
Unexecuted instantiation: conntrack.c:rculist_next_protected
Unexecuted instantiation: conntrack-icmp.c:rculist_next_protected
Unexecuted instantiation: conntrack-tcp.c:rculist_next_protected
Unexecuted instantiation: conntrack-tp.c:rculist_next_protected
Unexecuted instantiation: conntrack-other.c:rculist_next_protected
123
124
static inline void
125
rculist_init(struct rculist *list)
126
    OVS_NO_THREAD_SAFETY_ANALYSIS
127
0
{
128
0
    list->prev = list;
129
0
    ovsrcu_init(&list->next, list);
130
0
}
Unexecuted instantiation: meta-flow.c:rculist_init
Unexecuted instantiation: nx-match.c:rculist_init
Unexecuted instantiation: ofp-util.c:rculist_init
Unexecuted instantiation: ovs-router.c:rculist_init
Unexecuted instantiation: tnl-ports.c:rculist_init
Unexecuted instantiation: classifier.c:rculist_init
Unexecuted instantiation: conntrack.c:rculist_init
Unexecuted instantiation: conntrack-icmp.c:rculist_init
Unexecuted instantiation: conntrack-tcp.c:rculist_init
Unexecuted instantiation: conntrack-tp.c:rculist_init
Unexecuted instantiation: conntrack-other.c:rculist_init
131
132
0
#define RCULIST_POISON (struct rculist *)(UINTPTR_MAX / 0xf * 0xc)
133
134
/* Initializes 'list' with pointers that will (probably) cause segfaults if
135
 * dereferenced and, better yet, show up clearly in a debugger. */
136
static inline void
137
rculist_poison(struct rculist *list)
138
    OVS_NO_THREAD_SAFETY_ANALYSIS
139
0
{
140
0
    list->prev = RCULIST_POISON;
141
0
}
Unexecuted instantiation: meta-flow.c:rculist_poison
Unexecuted instantiation: nx-match.c:rculist_poison
Unexecuted instantiation: ofp-util.c:rculist_poison
Unexecuted instantiation: ovs-router.c:rculist_poison
Unexecuted instantiation: tnl-ports.c:rculist_poison
Unexecuted instantiation: classifier.c:rculist_poison
Unexecuted instantiation: conntrack.c:rculist_poison
Unexecuted instantiation: conntrack-icmp.c:rculist_poison
Unexecuted instantiation: conntrack-tcp.c:rculist_poison
Unexecuted instantiation: conntrack-tp.c:rculist_poison
Unexecuted instantiation: conntrack-other.c:rculist_poison
142
143
/* Initializes 'list' with pointers that will (probably) cause segfaults if
144
 * dereferenced and, better yet, show up clearly in a debugger.
145
 *
146
 * This variant poisons also the next pointer, so this may not be called if
147
 * this list element is still visible to RCU readers. */
148
static inline void
149
rculist_poison__(struct rculist *list)
150
    OVS_NO_THREAD_SAFETY_ANALYSIS
151
0
{
152
0
    rculist_poison(list);
153
0
    ovsrcu_set_hidden(&list->next, RCULIST_POISON);
154
0
}
Unexecuted instantiation: meta-flow.c:rculist_poison__
Unexecuted instantiation: nx-match.c:rculist_poison__
Unexecuted instantiation: ofp-util.c:rculist_poison__
Unexecuted instantiation: ovs-router.c:rculist_poison__
Unexecuted instantiation: tnl-ports.c:rculist_poison__
Unexecuted instantiation: classifier.c:rculist_poison__
Unexecuted instantiation: conntrack.c:rculist_poison__
Unexecuted instantiation: conntrack-icmp.c:rculist_poison__
Unexecuted instantiation: conntrack-tcp.c:rculist_poison__
Unexecuted instantiation: conntrack-tp.c:rculist_poison__
Unexecuted instantiation: conntrack-other.c:rculist_poison__
155
156
/* rculist insertion. */
157
static inline void
158
rculist_insert(struct rculist *before, struct rculist *elem)
159
    OVS_NO_THREAD_SAFETY_ANALYSIS
160
0
{
161
0
    elem->prev = before->prev;
162
0
    ovsrcu_set_hidden(&elem->next, before);
163
0
    ovsrcu_set(&before->prev->next, elem);
164
0
    before->prev = elem;
165
0
}
Unexecuted instantiation: meta-flow.c:rculist_insert
Unexecuted instantiation: nx-match.c:rculist_insert
Unexecuted instantiation: ofp-util.c:rculist_insert
Unexecuted instantiation: ovs-router.c:rculist_insert
Unexecuted instantiation: tnl-ports.c:rculist_insert
Unexecuted instantiation: classifier.c:rculist_insert
Unexecuted instantiation: conntrack.c:rculist_insert
Unexecuted instantiation: conntrack-icmp.c:rculist_insert
Unexecuted instantiation: conntrack-tcp.c:rculist_insert
Unexecuted instantiation: conntrack-tp.c:rculist_insert
Unexecuted instantiation: conntrack-other.c:rculist_insert
166
167
/* Removes elements 'first' though 'last' (exclusive) from their current list,
168
 * which may NOT be visible to any other threads (== be hidden from them),
169
 * then inserts them just before 'before'. */
170
static inline void
171
rculist_splice_hidden(struct rculist *before, struct rculist *first,
172
                      struct rculist *last)
173
    OVS_NO_THREAD_SAFETY_ANALYSIS
174
0
{
175
0
    struct rculist *last_next;
176
0
177
0
    if (first == last) {
178
0
        return;
179
0
    }
180
0
    last = last->prev;
181
0
182
0
    /* Cleanly remove 'first'...'last' from its current list. */
183
0
    last_next = rculist_next_protected(last);
184
0
    last_next->prev = first->prev;
185
0
    ovsrcu_set_hidden(&first->prev->next, last_next);
186
0
187
0
    /* Splice 'first'...'last' into new list. */
188
0
    first->prev = before->prev;
189
0
    ovsrcu_set(&last->next, before);
190
0
    ovsrcu_set(&before->prev->next, first);
191
0
    before->prev = last;
192
0
}
Unexecuted instantiation: meta-flow.c:rculist_splice_hidden
Unexecuted instantiation: nx-match.c:rculist_splice_hidden
Unexecuted instantiation: ofp-util.c:rculist_splice_hidden
Unexecuted instantiation: ovs-router.c:rculist_splice_hidden
Unexecuted instantiation: tnl-ports.c:rculist_splice_hidden
Unexecuted instantiation: classifier.c:rculist_splice_hidden
Unexecuted instantiation: conntrack.c:rculist_splice_hidden
Unexecuted instantiation: conntrack-icmp.c:rculist_splice_hidden
Unexecuted instantiation: conntrack-tcp.c:rculist_splice_hidden
Unexecuted instantiation: conntrack-tp.c:rculist_splice_hidden
Unexecuted instantiation: conntrack-other.c:rculist_splice_hidden
193
194
/* Inserts 'elem' at the beginning of 'list', so that it becomes the front in
195
 * 'list'. */
196
static inline void
197
rculist_push_front(struct rculist *list, struct rculist *elem)
198
0
{
199
0
    rculist_insert(rculist_next_protected(list), elem);
200
0
}
Unexecuted instantiation: meta-flow.c:rculist_push_front
Unexecuted instantiation: nx-match.c:rculist_push_front
Unexecuted instantiation: ofp-util.c:rculist_push_front
Unexecuted instantiation: ovs-router.c:rculist_push_front
Unexecuted instantiation: tnl-ports.c:rculist_push_front
Unexecuted instantiation: classifier.c:rculist_push_front
Unexecuted instantiation: conntrack.c:rculist_push_front
Unexecuted instantiation: conntrack-icmp.c:rculist_push_front
Unexecuted instantiation: conntrack-tcp.c:rculist_push_front
Unexecuted instantiation: conntrack-tp.c:rculist_push_front
Unexecuted instantiation: conntrack-other.c:rculist_push_front
201
202
/* Inserts 'elem' at the end of 'list', so that it becomes the back in
203
 * 'list'. */
204
static inline void
205
rculist_push_back(struct rculist *list, struct rculist *elem)
206
0
{
207
0
    rculist_insert(list, elem);
208
0
}
Unexecuted instantiation: meta-flow.c:rculist_push_back
Unexecuted instantiation: nx-match.c:rculist_push_back
Unexecuted instantiation: ofp-util.c:rculist_push_back
Unexecuted instantiation: ovs-router.c:rculist_push_back
Unexecuted instantiation: tnl-ports.c:rculist_push_back
Unexecuted instantiation: classifier.c:rculist_push_back
Unexecuted instantiation: conntrack.c:rculist_push_back
Unexecuted instantiation: conntrack-icmp.c:rculist_push_back
Unexecuted instantiation: conntrack-tcp.c:rculist_push_back
Unexecuted instantiation: conntrack-tp.c:rculist_push_back
Unexecuted instantiation: conntrack-other.c:rculist_push_back
209
210
/* Puts 'element' in the position currently occupied by 'position'.
211
 *
212
 * Afterward, 'position' is not linked to from the list any more, but still
213
 * links to the nodes in the list, and may still be referenced by other threads
214
 * until all other threads quiesce.  The replaced node ('position') may not be
215
 * re-inserted, re-initialized, or deleted until after all other threads have
216
 * quiesced (use ovsrcu_postpone). */
217
static inline void
218
rculist_replace(struct rculist *element, struct rculist *position)
219
    OVS_NO_THREAD_SAFETY_ANALYSIS
220
0
{
221
0
    struct rculist *position_next = rculist_next_protected(position);
222
223
0
    ovsrcu_set_hidden(&element->next, position_next);
224
0
    position_next->prev = element;
225
0
    element->prev = position->prev;
226
0
    ovsrcu_set(&element->prev->next, element);
227
0
    rculist_poison(position);
228
0
}
Unexecuted instantiation: meta-flow.c:rculist_replace
Unexecuted instantiation: nx-match.c:rculist_replace
Unexecuted instantiation: ofp-util.c:rculist_replace
Unexecuted instantiation: ovs-router.c:rculist_replace
Unexecuted instantiation: tnl-ports.c:rculist_replace
Unexecuted instantiation: classifier.c:rculist_replace
Unexecuted instantiation: conntrack.c:rculist_replace
Unexecuted instantiation: conntrack-icmp.c:rculist_replace
Unexecuted instantiation: conntrack-tcp.c:rculist_replace
Unexecuted instantiation: conntrack-tp.c:rculist_replace
Unexecuted instantiation: conntrack-other.c:rculist_replace
229
230
/* Initializes 'dst' with the contents of 'src', compensating for moving it
231
 * around in memory.  The effect is that, if 'src' was the head of a list, now
232
 * 'dst' is the head of a list containing the same elements.
233
 *
234
 * Memory for 'src' must be kept around until the next RCU quiescent period.
235
 * rculist cannot be simply reallocated, so there is no rculist_moved(). */
236
static inline void
237
rculist_move(struct rculist *dst, struct rculist *src)
238
    OVS_NO_THREAD_SAFETY_ANALYSIS
239
0
{
240
0
    if (!rculist_is_empty(src)) {
241
0
        struct rculist *src_next = rculist_next_protected(src);
242
0
243
0
        dst->prev = src->prev;
244
0
        ovsrcu_set_hidden(&dst->next, src_next);
245
0
246
0
        src_next->prev = dst;
247
0
        ovsrcu_set(&src->prev->next, dst);
248
0
    } else {
249
0
        rculist_init(dst);
250
0
    }
251
0
    rculist_poison(src);
252
0
}
Unexecuted instantiation: meta-flow.c:rculist_move
Unexecuted instantiation: nx-match.c:rculist_move
Unexecuted instantiation: ofp-util.c:rculist_move
Unexecuted instantiation: ovs-router.c:rculist_move
Unexecuted instantiation: tnl-ports.c:rculist_move
Unexecuted instantiation: classifier.c:rculist_move
Unexecuted instantiation: conntrack.c:rculist_move
Unexecuted instantiation: conntrack-icmp.c:rculist_move
Unexecuted instantiation: conntrack-tcp.c:rculist_move
Unexecuted instantiation: conntrack-tp.c:rculist_move
Unexecuted instantiation: conntrack-other.c:rculist_move
253
254
/* Removes 'elem' from its list and returns the element that followed it.
255
 * Has no effect when 'elem' is initialized, but not in a list.
256
 * Undefined behavior if 'elem' is not initialized.
257
 *
258
 * Afterward, 'elem' is not linked to from the list any more, but still links
259
 * to the nodes in the list, and may still be referenced by other threads until
260
 * all other threads quiesce.  The removed node ('elem') may not be
261
 * re-inserted, re-initialized, or deleted until after all other threads have
262
 * quiesced (use ovsrcu_postpone).
263
 */
264
static inline struct rculist *
265
rculist_remove(struct rculist *elem)
266
    OVS_NO_THREAD_SAFETY_ANALYSIS
267
0
{
268
0
    struct rculist *elem_next = rculist_next_protected(elem);
269
270
0
    elem_next->prev = elem->prev;
271
0
    ovsrcu_set(&elem->prev->next, elem_next);
272
0
    rculist_poison(elem);
273
0
    return elem_next;
274
0
}
Unexecuted instantiation: meta-flow.c:rculist_remove
Unexecuted instantiation: nx-match.c:rculist_remove
Unexecuted instantiation: ofp-util.c:rculist_remove
Unexecuted instantiation: ovs-router.c:rculist_remove
Unexecuted instantiation: tnl-ports.c:rculist_remove
Unexecuted instantiation: classifier.c:rculist_remove
Unexecuted instantiation: conntrack.c:rculist_remove
Unexecuted instantiation: conntrack-icmp.c:rculist_remove
Unexecuted instantiation: conntrack-tcp.c:rculist_remove
Unexecuted instantiation: conntrack-tp.c:rculist_remove
Unexecuted instantiation: conntrack-other.c:rculist_remove
275
276
/* Removes the front element from 'list' and returns it.  Undefined behavior if
277
 * 'list' is empty before removal.
278
 *
279
 * Afterward, teh returned former first node is not linked to from the list any
280
 * more, but still links to the nodes in the list, and may still be referenced
281
 * by other threads until all other threads quiesce.  The returned node may not
282
 * be re-inserted, re-initialized, or deleted until after all other threads
283
 * have quiesced (use ovsrcu_postpone). */
284
static inline struct rculist *
285
rculist_pop_front(struct rculist *list)
286
    OVS_NO_THREAD_SAFETY_ANALYSIS
287
0
{
288
0
    struct rculist *front = rculist_next_protected(list);
289
0
    rculist_remove(front);
290
0
    return front;
291
0
}
Unexecuted instantiation: meta-flow.c:rculist_pop_front
Unexecuted instantiation: nx-match.c:rculist_pop_front
Unexecuted instantiation: ofp-util.c:rculist_pop_front
Unexecuted instantiation: ovs-router.c:rculist_pop_front
Unexecuted instantiation: tnl-ports.c:rculist_pop_front
Unexecuted instantiation: classifier.c:rculist_pop_front
Unexecuted instantiation: conntrack.c:rculist_pop_front
Unexecuted instantiation: conntrack-icmp.c:rculist_pop_front
Unexecuted instantiation: conntrack-tcp.c:rculist_pop_front
Unexecuted instantiation: conntrack-tp.c:rculist_pop_front
Unexecuted instantiation: conntrack-other.c:rculist_pop_front
292
293
/* Removes the back element from 'list' and returns it.
294
 * Undefined behavior if 'list' is empty before removal.
295
 *
296
 * Afterward, teh returned former last node is not linked to from the list any
297
 * more, but still links to the nodes in the list, and may still be referenced
298
 * by other threads until all other threads quiesce.  The returned node may not
299
 * be re-inserted, re-initialized, or deleted until after all other threads
300
 * have quiesced (use ovsrcu_postpone). */
301
static inline struct rculist *
302
rculist_pop_back(struct rculist *list)
303
    OVS_NO_THREAD_SAFETY_ANALYSIS
304
0
{
305
0
    struct rculist *back = list->prev;
306
0
    rculist_remove(back);
307
0
    return back;
308
0
}
Unexecuted instantiation: meta-flow.c:rculist_pop_back
Unexecuted instantiation: nx-match.c:rculist_pop_back
Unexecuted instantiation: ofp-util.c:rculist_pop_back
Unexecuted instantiation: ovs-router.c:rculist_pop_back
Unexecuted instantiation: tnl-ports.c:rculist_pop_back
Unexecuted instantiation: classifier.c:rculist_pop_back
Unexecuted instantiation: conntrack.c:rculist_pop_back
Unexecuted instantiation: conntrack-icmp.c:rculist_pop_back
Unexecuted instantiation: conntrack-tcp.c:rculist_pop_back
Unexecuted instantiation: conntrack-tp.c:rculist_pop_back
Unexecuted instantiation: conntrack-other.c:rculist_pop_back
309
310
/* Returns the front element in 'list_'.
311
 * Undefined behavior if 'list_' is empty. */
312
static inline const struct rculist *
313
rculist_front(const struct rculist *list)
314
0
{
315
0
    ovs_assert(!rculist_is_empty(list));
316
0
317
0
    return rculist_next(list);
318
0
}
Unexecuted instantiation: meta-flow.c:rculist_front
Unexecuted instantiation: nx-match.c:rculist_front
Unexecuted instantiation: ofp-util.c:rculist_front
Unexecuted instantiation: ovs-router.c:rculist_front
Unexecuted instantiation: tnl-ports.c:rculist_front
Unexecuted instantiation: classifier.c:rculist_front
Unexecuted instantiation: conntrack.c:rculist_front
Unexecuted instantiation: conntrack-icmp.c:rculist_front
Unexecuted instantiation: conntrack-tcp.c:rculist_front
Unexecuted instantiation: conntrack-tp.c:rculist_front
Unexecuted instantiation: conntrack-other.c:rculist_front
319
320
/* Returns the back element in 'list_'.
321
 * Returns the 'list_' itself, if 'list_' is empty. */
322
static inline struct rculist *
323
rculist_back_protected(const struct rculist *list)
324
    OVS_NO_THREAD_SAFETY_ANALYSIS
325
0
{
326
0
    return CONST_CAST(struct rculist *, list)->prev;
327
0
}
Unexecuted instantiation: meta-flow.c:rculist_back_protected
Unexecuted instantiation: nx-match.c:rculist_back_protected
Unexecuted instantiation: ofp-util.c:rculist_back_protected
Unexecuted instantiation: ovs-router.c:rculist_back_protected
Unexecuted instantiation: tnl-ports.c:rculist_back_protected
Unexecuted instantiation: classifier.c:rculist_back_protected
Unexecuted instantiation: conntrack.c:rculist_back_protected
Unexecuted instantiation: conntrack-icmp.c:rculist_back_protected
Unexecuted instantiation: conntrack-tcp.c:rculist_back_protected
Unexecuted instantiation: conntrack-tp.c:rculist_back_protected
Unexecuted instantiation: conntrack-other.c:rculist_back_protected
328
329
/* Returns the number of elements in 'list'.
330
 * Runs in O(n) in the number of elements. */
331
static inline size_t
332
rculist_size(const struct rculist *list)
333
0
{
334
0
    const struct rculist *e;
335
0
    size_t cnt = 0;
336
0
337
0
    for (e = rculist_next(list); e != list; e = rculist_next(e)) {
338
0
        cnt++;
339
0
    }
340
0
    return cnt;
341
0
}
Unexecuted instantiation: meta-flow.c:rculist_size
Unexecuted instantiation: nx-match.c:rculist_size
Unexecuted instantiation: ofp-util.c:rculist_size
Unexecuted instantiation: ovs-router.c:rculist_size
Unexecuted instantiation: tnl-ports.c:rculist_size
Unexecuted instantiation: classifier.c:rculist_size
Unexecuted instantiation: conntrack.c:rculist_size
Unexecuted instantiation: conntrack-icmp.c:rculist_size
Unexecuted instantiation: conntrack-tcp.c:rculist_size
Unexecuted instantiation: conntrack-tp.c:rculist_size
Unexecuted instantiation: conntrack-other.c:rculist_size
342
343
/* Returns true if 'list' is empty, false otherwise. */
344
static inline bool
345
rculist_is_empty(const struct rculist *list)
346
0
{
347
0
    return rculist_next(list) == list;
348
0
}
Unexecuted instantiation: meta-flow.c:rculist_is_empty
Unexecuted instantiation: nx-match.c:rculist_is_empty
Unexecuted instantiation: ofp-util.c:rculist_is_empty
Unexecuted instantiation: ovs-router.c:rculist_is_empty
Unexecuted instantiation: tnl-ports.c:rculist_is_empty
Unexecuted instantiation: classifier.c:rculist_is_empty
Unexecuted instantiation: conntrack.c:rculist_is_empty
Unexecuted instantiation: conntrack-icmp.c:rculist_is_empty
Unexecuted instantiation: conntrack-tcp.c:rculist_is_empty
Unexecuted instantiation: conntrack-tp.c:rculist_is_empty
Unexecuted instantiation: conntrack-other.c:rculist_is_empty
349
350
/* Returns true if 'list' has 0 or 1 elements, false otherwise. */
351
static inline bool
352
rculist_is_short_protected(const struct rculist *list)
353
    OVS_NO_THREAD_SAFETY_ANALYSIS
354
0
{
355
0
    return rculist_next_protected(list) == list->prev;
356
0
}
Unexecuted instantiation: meta-flow.c:rculist_is_short_protected
Unexecuted instantiation: nx-match.c:rculist_is_short_protected
Unexecuted instantiation: ofp-util.c:rculist_is_short_protected
Unexecuted instantiation: ovs-router.c:rculist_is_short_protected
Unexecuted instantiation: tnl-ports.c:rculist_is_short_protected
Unexecuted instantiation: classifier.c:rculist_is_short_protected
Unexecuted instantiation: conntrack.c:rculist_is_short_protected
Unexecuted instantiation: conntrack-icmp.c:rculist_is_short_protected
Unexecuted instantiation: conntrack-tcp.c:rculist_is_short_protected
Unexecuted instantiation: conntrack-tp.c:rculist_is_short_protected
Unexecuted instantiation: conntrack-other.c:rculist_is_short_protected
357
358
/* Returns true if 'list' has exactly 1 element, false otherwise. */
359
static inline bool
360
rculist_is_singleton_protected(const struct rculist *list)
361
    OVS_NO_THREAD_SAFETY_ANALYSIS
362
0
{
363
0
    const struct rculist *list_next = rculist_next_protected(list);
364
0
365
0
    return list_next == list->prev && list_next != list;
366
0
}
Unexecuted instantiation: meta-flow.c:rculist_is_singleton_protected
Unexecuted instantiation: nx-match.c:rculist_is_singleton_protected
Unexecuted instantiation: ofp-util.c:rculist_is_singleton_protected
Unexecuted instantiation: ovs-router.c:rculist_is_singleton_protected
Unexecuted instantiation: tnl-ports.c:rculist_is_singleton_protected
Unexecuted instantiation: classifier.c:rculist_is_singleton_protected
Unexecuted instantiation: conntrack.c:rculist_is_singleton_protected
Unexecuted instantiation: conntrack-icmp.c:rculist_is_singleton_protected
Unexecuted instantiation: conntrack-tcp.c:rculist_is_singleton_protected
Unexecuted instantiation: conntrack-tp.c:rculist_is_singleton_protected
Unexecuted instantiation: conntrack-other.c:rculist_is_singleton_protected
367
368
#define RCULIST_FOR_EACH(ITER, MEMBER, RCULIST)                               \
369
0
    for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(RCULIST),                   \
370
0
                       const struct rculist);                                 \
371
0
         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
372
0
         UPDATE_MULTIVAR(ITER, rculist_next(ITER_VAR(ITER))))
373
374
#define RCULIST_FOR_EACH_CONTINUE(ITER, MEMBER, RCULIST)                      \
375
0
    for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(&(ITER)->MEMBER),           \
376
0
                       const struct rculist);                                 \
377
0
         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
378
0
         UPDATE_MULTIVAR(ITER, rculist_next(ITER_VAR(ITER))))
379
380
#define RCULIST_FOR_EACH_REVERSE_PROTECTED(ITER, MEMBER, RCULIST)             \
381
    for (INIT_MULTIVAR(ITER, MEMBER, rculist_back_protected(RCULIST),         \
382
                       struct rculist);                                       \
383
         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
384
         UPDATE_MULTIVAR(ITER, rculist_back_protected(ITER_VAR(ITER))))
385
386
#define RCULIST_FOR_EACH_REVERSE_PROTECTED_CONTINUE(ITER, MEMBER, RCULIST)    \
387
    for (INIT_MULTIVAR(ITER, MEMBER, rculist_back_protected(ITER->MEMBER),    \
388
                       struct rculist);                                       \
389
         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
390
         UPDATE_MULTIVAR(ITER, ITER_VAR(ITER)->prev))
391
392
#define RCULIST_FOR_EACH_PROTECTED(ITER, MEMBER, RCULIST)                     \
393
    for (INIT_MULTIVAR(ITER, MEMBER, rculist_next_protected(RCULIST),         \
394
                       struct rculist);                                       \
395
         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
396
         UPDATE_MULTIVAR(ITER, rculist_next_protected(ITER_VAR(ITER))))       \
397
398
#define RCULIST_FOR_EACH_SAFE_SHORT_PROTECTED(ITER, MEMBER, RCULIST)          \
399
    for (INIT_MULTIVAR_SAFE_SHORT(ITER, MEMBER,                               \
400
                                  rculist_next_protected(RCULIST),            \
401
                                  struct rculist);                            \
402
         CONDITION_MULTIVAR_SAFE_SHORT(ITER, MEMBER,                          \
403
                                       ITER_VAR(ITER) != (RCULIST),           \
404
             ITER_NEXT_VAR(ITER) = rculist_next_protected(ITER_VAR(ITER)));   \
405
        UPDATE_MULTIVAR_SAFE_SHORT(ITER))
406
407
#define RCULIST_FOR_EACH_SAFE_LONG_PROTECTED(ITER, NEXT, MEMBER, RCULIST)     \
408
    for (INIT_MULTIVAR_SAFE_LONG(ITER, NEXT, MEMBER,                          \
409
                                 rculist_next_protected(RCULIST),             \
410
                                 struct rculist);                             \
411
         CONDITION_MULTIVAR_SAFE_LONG(ITER, NEXT, MEMBER,                     \
412
                                      ITER_VAR(ITER) != (RCULIST),            \
413
             ITER_VAR(NEXT) = rculist_next_protected(ITER_VAR(ITER)),         \
414
                                      ITER_VAR(NEXT) != (RCULIST));           \
415
        UPDATE_MULTIVAR_SAFE_LONG(ITER, NEXT))
416
417
#define RCULIST_FOR_EACH_SAFE_PROTECTED(...)                                  \
418
    OVERLOAD_SAFE_MACRO(RCULIST_FOR_EACH_SAFE_LONG_PROTECTED,                 \
419
                        RCULIST_FOR_EACH_SAFE_SHORT_PROTECTED,                \
420
                        4, __VA_ARGS__)
421
422
423
#endif /* rculist.h */