/src/frr/lib/frr_pthread.h
Line | Count | Source (jump to first uncovered line) |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | /* |
3 | | * Utilities and interfaces for managing POSIX threads within FRR. |
4 | | * Copyright (C) 2017 Cumulus Networks, Inc. |
5 | | */ |
6 | | |
7 | | #ifndef _FRR_PTHREAD_H |
8 | | #define _FRR_PTHREAD_H |
9 | | |
10 | | #include <pthread.h> |
11 | | #include "frratomic.h" |
12 | | #include "memory.h" |
13 | | #include "frrcu.h" |
14 | | #include "frrevent.h" |
15 | | |
16 | | #ifdef __cplusplus |
17 | | extern "C" { |
18 | | #endif |
19 | | |
20 | 0 | #define OS_THREAD_NAMELEN 16 |
21 | | |
22 | | struct frr_pthread; |
23 | | struct frr_pthread_attr; |
24 | | |
25 | | struct frr_pthread_attr { |
26 | | void *(*start)(void *); |
27 | | int (*stop)(struct frr_pthread *, void **); |
28 | | }; |
29 | | |
30 | | struct frr_pthread { |
31 | | |
32 | | /* |
33 | | * Mutex protecting this structure. Must be taken for reading some |
34 | | * fields, denoted by a 'Requires: mtx'. |
35 | | */ |
36 | | pthread_mutex_t mtx; |
37 | | |
38 | | /* pthread id */ |
39 | | pthread_t thread; |
40 | | |
41 | | struct rcu_thread *rcu_thread; |
42 | | |
43 | | /* thread master for this pthread's thread.c event loop */ |
44 | | struct event_loop *master; |
45 | | |
46 | | /* caller-specified data; start & stop funcs, name, id */ |
47 | | struct frr_pthread_attr attr; |
48 | | |
49 | | /* |
50 | | * Notification mechanism for allowing pthreads to notify their parents |
51 | | * when they are ready to do work. This mechanism has two associated |
52 | | * functions: |
53 | | * |
54 | | * - frr_pthread_wait_running() |
55 | | * This function should be called by the spawning thread after |
56 | | * frr_pthread_run(). It safely waits until the spawned thread |
57 | | * indicates that is ready to do work by posting to the condition |
58 | | * variable. |
59 | | * |
60 | | * - frr_pthread_notify_running() |
61 | | * This function should be called by the spawned thread when it is |
62 | | * ready to do work. It will wake up any threads waiting on the |
63 | | * previously described condition. |
64 | | */ |
65 | | pthread_cond_t *running_cond; |
66 | | pthread_mutex_t *running_cond_mtx; |
67 | | atomic_bool running; |
68 | | |
69 | | /* |
70 | | * Fake thread-specific storage. No constraints on usage. Helpful when |
71 | | * creating reentrant pthread implementations. Can be used to pass |
72 | | * argument to pthread entry function. |
73 | | * |
74 | | * Requires: mtx |
75 | | */ |
76 | | void *data; |
77 | | |
78 | | /* |
79 | | * Human-readable thread name. |
80 | | * |
81 | | * Requires: mtx |
82 | | */ |
83 | | char *name; |
84 | | |
85 | | /* Used in pthread_set_name max 16 characters */ |
86 | | char os_name[OS_THREAD_NAMELEN]; |
87 | | }; |
88 | | |
89 | | extern const struct frr_pthread_attr frr_pthread_attr_default; |
90 | | |
91 | | /* |
92 | | * Initializes this module. |
93 | | * |
94 | | * Must be called before using any of the other functions. |
95 | | */ |
96 | | void frr_pthread_init(void); |
97 | | |
98 | | /* |
99 | | * Uninitializes this module. |
100 | | * |
101 | | * Destroys all registered frr_pthread's and internal data structures. |
102 | | * |
103 | | * It is safe to call frr_pthread_init() after this function to reinitialize |
104 | | * the module. |
105 | | */ |
106 | | void frr_pthread_finish(void); |
107 | | |
108 | | /* |
109 | | * Creates a new frr_pthread with the given attributes. |
110 | | * |
111 | | * The 'attr' argument should be filled out with the desired attributes, |
112 | | * including ID, start and stop functions and the desired name. Alternatively, |
113 | | * if attr is NULL, the default attributes will be used. The pthread will be |
114 | | * set up to run a basic threadmaster loop and the name will be "Anonymous". |
115 | | * Scheduling tasks onto the threadmaster in the 'master' field of the returned |
116 | | * frr_pthread will cause them to run on that pthread. |
117 | | * |
118 | | * @param attr - the thread attributes |
119 | | * @param name - Human-readable name |
120 | | * @param os_name - 16 characters (including '\0') thread name to set in os, |
121 | | * @return the created frr_pthread upon success, or NULL upon failure |
122 | | */ |
123 | | struct frr_pthread *frr_pthread_new(const struct frr_pthread_attr *attr, |
124 | | const char *name, const char *os_name); |
125 | | |
126 | | /* |
127 | | * Changes the name of the frr_pthread as reported by the operating |
128 | | * system. |
129 | | * |
130 | | * @param fpt - the frr_pthread to operate on |
131 | | * @return - on success returns 0 otherwise nonzero error number. |
132 | | */ |
133 | | int frr_pthread_set_name(struct frr_pthread *fpt); |
134 | | |
135 | | /* |
136 | | * Destroys an frr_pthread. |
137 | | * |
138 | | * Assumes that the associated pthread, if any, has already terminated. |
139 | | * |
140 | | * @param fpt - the frr_pthread to destroy |
141 | | */ |
142 | | void frr_pthread_destroy(struct frr_pthread *fpt); |
143 | | |
144 | | /* |
145 | | * Creates a new pthread and binds it to a frr_pthread. |
146 | | * |
147 | | * This function is a wrapper for pthread_create. The first parameter is the |
148 | | * frr_pthread to bind the created pthread to. All subsequent arguments are |
149 | | * passed unmodified to pthread_create(). The frr_pthread * provided will be |
150 | | * used as the argument to the pthread entry function. If it is necessary to |
151 | | * pass additional data, the 'data' field in the frr_pthread may be used. |
152 | | * |
153 | | * This function returns the same code as pthread_create(). If the value is |
154 | | * zero, the provided frr_pthread is bound to a running POSIX thread. If the |
155 | | * value is less than zero, the provided frr_pthread is guaranteed to be a |
156 | | * clean instance that may be susbsequently passed to frr_pthread_run(). |
157 | | * |
158 | | * @param fpt - frr_pthread * to run |
159 | | * @param attr - see pthread_create(3) |
160 | | * |
161 | | * @return see pthread_create(3) |
162 | | */ |
163 | | int frr_pthread_run(struct frr_pthread *fpt, const pthread_attr_t *attr); |
164 | | |
165 | | /* |
166 | | * Waits until the specified pthread has finished setting up and is ready to |
167 | | * begin work. |
168 | | * |
169 | | * If the pthread's code makes use of the startup synchronization mechanism, |
170 | | * this function should be called before attempting to use the functionality |
171 | | * exposed by the pthread. It waits until the 'running' condition is satisfied |
172 | | * (see struct definition of frr_pthread). |
173 | | * |
174 | | * @param fpt - the frr_pthread * to wait on |
175 | | */ |
176 | | void frr_pthread_wait_running(struct frr_pthread *fpt); |
177 | | |
178 | | /* |
179 | | * Notifies other pthreads that the calling thread has finished setting up and |
180 | | * is ready to begin work. |
181 | | * |
182 | | * This will allow any other pthreads waiting in 'frr_pthread_wait_running' to |
183 | | * proceed. |
184 | | * |
185 | | * @param fpt - the frr_pthread * that has finished setting up |
186 | | */ |
187 | | void frr_pthread_notify_running(struct frr_pthread *fpt); |
188 | | |
189 | | /* |
190 | | * Stops a frr_pthread with a result. |
191 | | * |
192 | | * @param fpt - frr_pthread * to stop |
193 | | * @param result - where to store the thread's result, if any. May be NULL if a |
194 | | * result is not needed. |
195 | | */ |
196 | | int frr_pthread_stop(struct frr_pthread *fpt, void **result); |
197 | | |
198 | | /* Stops all frr_pthread's. */ |
199 | | void frr_pthread_stop_all(void); |
200 | | |
201 | | #ifndef HAVE_PTHREAD_CONDATTR_SETCLOCK |
202 | | #define pthread_condattr_setclock(A, B) |
203 | | #endif |
204 | | |
205 | | /* mutex auto-lock/unlock */ |
206 | | |
207 | | /* variant 1: |
208 | | * (for short blocks, multiple mutexes supported) |
209 | | * break & return can be used for aborting the block |
210 | | * |
211 | | * frr_with_mutex(&mtx, &mtx2) { |
212 | | * if (error) |
213 | | * break; |
214 | | * ... |
215 | | * } |
216 | | */ |
217 | | #define _frr_with_mutex(mutex) \ |
218 | 50.0k | *NAMECTR(_mtx_) __attribute__(( \ |
219 | 50.0k | unused, cleanup(_frr_mtx_unlock))) = _frr_mtx_lock(mutex), \ |
220 | | /* end */ |
221 | | |
222 | | #define frr_with_mutex(...) \ |
223 | 50.0k | for (pthread_mutex_t MACRO_REPEAT(_frr_with_mutex, ##__VA_ARGS__) \ |
224 | 100k | *_once = NULL; _once == NULL; _once = (void *)1) \ |
225 | | /* end */ |
226 | | |
227 | | /* variant 2: |
228 | | * (more suitable for long blocks, no extra indentation) |
229 | | * |
230 | | * frr_mutex_lock_autounlock(&mtx); |
231 | | * ... |
232 | | */ |
233 | | #define frr_mutex_lock_autounlock(mutex) \ |
234 | 0 | pthread_mutex_t *NAMECTR(_mtx_) \ |
235 | 0 | __attribute__((unused, cleanup(_frr_mtx_unlock))) = \ |
236 | 0 | _frr_mtx_lock(mutex) \ |
237 | | /* end */ |
238 | | |
239 | | static inline pthread_mutex_t *_frr_mtx_lock(pthread_mutex_t *mutex) |
240 | 50.0k | { |
241 | 50.0k | pthread_mutex_lock(mutex); |
242 | 50.0k | return mutex; |
243 | 50.0k | } Line | Count | Source | 240 | 9 | { | 241 | 9 | pthread_mutex_lock(mutex); | 242 | 9 | return mutex; | 243 | 9 | } |
Unexecuted instantiation: frr_pthread.c:_frr_mtx_lock Line | Count | Source | 240 | 49.9k | { | 241 | 49.9k | pthread_mutex_lock(mutex); | 242 | 49.9k | return mutex; | 243 | 49.9k | } |
Unexecuted instantiation: libfrr.c:_frr_mtx_lock Unexecuted instantiation: log.c:_frr_mtx_lock Unexecuted instantiation: log_filter.c:_frr_mtx_lock Unexecuted instantiation: northbound.c:_frr_mtx_lock Unexecuted instantiation: privs.c:_frr_mtx_lock Unexecuted instantiation: stream.c:_frr_mtx_lock Line | Count | Source | 240 | 2 | { | 241 | 2 | pthread_mutex_lock(mutex); | 242 | 2 | return mutex; | 243 | 2 | } |
Unexecuted instantiation: zlog_5424.c:_frr_mtx_lock zlog_targets.c:_frr_mtx_lock Line | Count | Source | 240 | 2 | { | 241 | 2 | pthread_mutex_lock(mutex); | 242 | 2 | return mutex; | 243 | 2 | } |
Unexecuted instantiation: main.c:_frr_mtx_lock Unexecuted instantiation: zebra_dplane.c:_frr_mtx_lock Unexecuted instantiation: zebra_mlag.c:_frr_mtx_lock Unexecuted instantiation: zebra_opaque.c:_frr_mtx_lock Unexecuted instantiation: zebra_rib.c:_frr_mtx_lock Unexecuted instantiation: zserv.c:_frr_mtx_lock Unexecuted instantiation: bgp_main.c:_frr_mtx_lock Unexecuted instantiation: bgp_attr.c:_frr_mtx_lock Unexecuted instantiation: bgp_attr_evpn.c:_frr_mtx_lock Unexecuted instantiation: bgp_clist.c:_frr_mtx_lock Unexecuted instantiation: bgp_community.c:_frr_mtx_lock Unexecuted instantiation: bgp_community_alias.c:_frr_mtx_lock Unexecuted instantiation: bgp_debug.c:_frr_mtx_lock Unexecuted instantiation: bgp_dump.c:_frr_mtx_lock Unexecuted instantiation: bgp_ecommunity.c:_frr_mtx_lock Unexecuted instantiation: bgp_evpn.c:_frr_mtx_lock Unexecuted instantiation: bgp_evpn_mh.c:_frr_mtx_lock Unexecuted instantiation: bgp_evpn_vty.c:_frr_mtx_lock Unexecuted instantiation: bgp_filter.c:_frr_mtx_lock Unexecuted instantiation: bgp_flowspec_vty.c:_frr_mtx_lock Unexecuted instantiation: bgp_fsm.c:_frr_mtx_lock Unexecuted instantiation: bgp_io.c:_frr_mtx_lock Unexecuted instantiation: bgp_keepalives.c:_frr_mtx_lock Unexecuted instantiation: bgp_labelpool.c:_frr_mtx_lock Unexecuted instantiation: bgp_lcommunity.c:_frr_mtx_lock Unexecuted instantiation: bgp_mac.c:_frr_mtx_lock Unexecuted instantiation: bgp_mpath.c:_frr_mtx_lock Unexecuted instantiation: bgp_mplsvpn.c:_frr_mtx_lock Unexecuted instantiation: bgp_network.c:_frr_mtx_lock Unexecuted instantiation: bgp_nexthop.c:_frr_mtx_lock Unexecuted instantiation: bgp_nht.c:_frr_mtx_lock Unexecuted instantiation: bgp_packet.c:_frr_mtx_lock Unexecuted instantiation: bgp_pbr.c:_frr_mtx_lock Unexecuted instantiation: bgp_rd.c:_frr_mtx_lock Unexecuted instantiation: bgp_regex.c:_frr_mtx_lock Unexecuted instantiation: bgp_route.c:_frr_mtx_lock Unexecuted instantiation: bgp_routemap.c:_frr_mtx_lock Unexecuted instantiation: bgp_routemap_nb.c:_frr_mtx_lock Unexecuted instantiation: bgp_routemap_nb_config.c:_frr_mtx_lock Unexecuted instantiation: bgp_table.c:_frr_mtx_lock Unexecuted instantiation: bgp_updgrp.c:_frr_mtx_lock Unexecuted instantiation: bgp_updgrp_adv.c:_frr_mtx_lock Unexecuted instantiation: bgp_updgrp_packet.c:_frr_mtx_lock Unexecuted instantiation: bgp_vpn.c:_frr_mtx_lock Unexecuted instantiation: bgp_vty.c:_frr_mtx_lock Unexecuted instantiation: bgp_zebra.c:_frr_mtx_lock Unexecuted instantiation: bgpd.c:_frr_mtx_lock Unexecuted instantiation: bgp_rfapi_cfg.c:_frr_mtx_lock Unexecuted instantiation: rfapi_import.c:_frr_mtx_lock Unexecuted instantiation: rfapi.c:_frr_mtx_lock Unexecuted instantiation: rfapi_ap.c:_frr_mtx_lock Unexecuted instantiation: rfapi_encap_tlv.c:_frr_mtx_lock Unexecuted instantiation: rfapi_nve_addr.c:_frr_mtx_lock Unexecuted instantiation: rfapi_monitor.c:_frr_mtx_lock Unexecuted instantiation: rfapi_rib.c:_frr_mtx_lock Unexecuted instantiation: rfapi_vty.c:_frr_mtx_lock Unexecuted instantiation: vnc_export_bgp.c:_frr_mtx_lock Unexecuted instantiation: vnc_export_table.c:_frr_mtx_lock Unexecuted instantiation: vnc_import_bgp.c:_frr_mtx_lock Unexecuted instantiation: vnc_zebra.c:_frr_mtx_lock Unexecuted instantiation: bgp_addpath.c:_frr_mtx_lock Unexecuted instantiation: bgp_advertise.c:_frr_mtx_lock Unexecuted instantiation: bgp_aspath.c:_frr_mtx_lock Unexecuted instantiation: bgp_bfd.c:_frr_mtx_lock Unexecuted instantiation: bgp_conditional_adv.c:_frr_mtx_lock Unexecuted instantiation: bgp_damp.c:_frr_mtx_lock Unexecuted instantiation: bgp_encap_tlv.c:_frr_mtx_lock Unexecuted instantiation: bgp_flowspec.c:_frr_mtx_lock Unexecuted instantiation: bgp_flowspec_util.c:_frr_mtx_lock Unexecuted instantiation: bgp_label.c:_frr_mtx_lock Unexecuted instantiation: bgp_open.c:_frr_mtx_lock Unexecuted instantiation: rfp_example.c:_frr_mtx_lock |
244 | | |
245 | | static inline void _frr_mtx_unlock(pthread_mutex_t **mutex) |
246 | 50.0k | { |
247 | 50.0k | if (!*mutex) |
248 | 0 | return; |
249 | 50.0k | pthread_mutex_unlock(*mutex); |
250 | 50.0k | *mutex = NULL; |
251 | 50.0k | } Line | Count | Source | 246 | 9 | { | 247 | 9 | if (!*mutex) | 248 | 0 | return; | 249 | 9 | pthread_mutex_unlock(*mutex); | 250 | 9 | *mutex = NULL; | 251 | 9 | } |
Unexecuted instantiation: frr_pthread.c:_frr_mtx_unlock Line | Count | Source | 246 | 49.9k | { | 247 | 49.9k | if (!*mutex) | 248 | 0 | return; | 249 | 49.9k | pthread_mutex_unlock(*mutex); | 250 | 49.9k | *mutex = NULL; | 251 | 49.9k | } |
Unexecuted instantiation: libfrr.c:_frr_mtx_unlock Unexecuted instantiation: log.c:_frr_mtx_unlock Unexecuted instantiation: log_filter.c:_frr_mtx_unlock Unexecuted instantiation: northbound.c:_frr_mtx_unlock Unexecuted instantiation: privs.c:_frr_mtx_unlock Unexecuted instantiation: stream.c:_frr_mtx_unlock Line | Count | Source | 246 | 2 | { | 247 | 2 | if (!*mutex) | 248 | 0 | return; | 249 | 2 | pthread_mutex_unlock(*mutex); | 250 | 2 | *mutex = NULL; | 251 | 2 | } |
Unexecuted instantiation: zlog_5424.c:_frr_mtx_unlock zlog_targets.c:_frr_mtx_unlock Line | Count | Source | 246 | 2 | { | 247 | 2 | if (!*mutex) | 248 | 0 | return; | 249 | 2 | pthread_mutex_unlock(*mutex); | 250 | 2 | *mutex = NULL; | 251 | 2 | } |
Unexecuted instantiation: main.c:_frr_mtx_unlock Unexecuted instantiation: zebra_dplane.c:_frr_mtx_unlock Unexecuted instantiation: zebra_mlag.c:_frr_mtx_unlock Unexecuted instantiation: zebra_opaque.c:_frr_mtx_unlock Unexecuted instantiation: zebra_rib.c:_frr_mtx_unlock Unexecuted instantiation: zserv.c:_frr_mtx_unlock Unexecuted instantiation: bgp_main.c:_frr_mtx_unlock Unexecuted instantiation: bgp_attr.c:_frr_mtx_unlock Unexecuted instantiation: bgp_attr_evpn.c:_frr_mtx_unlock Unexecuted instantiation: bgp_clist.c:_frr_mtx_unlock Unexecuted instantiation: bgp_community.c:_frr_mtx_unlock Unexecuted instantiation: bgp_community_alias.c:_frr_mtx_unlock Unexecuted instantiation: bgp_debug.c:_frr_mtx_unlock Unexecuted instantiation: bgp_dump.c:_frr_mtx_unlock Unexecuted instantiation: bgp_ecommunity.c:_frr_mtx_unlock Unexecuted instantiation: bgp_evpn.c:_frr_mtx_unlock Unexecuted instantiation: bgp_evpn_mh.c:_frr_mtx_unlock Unexecuted instantiation: bgp_evpn_vty.c:_frr_mtx_unlock Unexecuted instantiation: bgp_filter.c:_frr_mtx_unlock Unexecuted instantiation: bgp_flowspec_vty.c:_frr_mtx_unlock Unexecuted instantiation: bgp_fsm.c:_frr_mtx_unlock Unexecuted instantiation: bgp_io.c:_frr_mtx_unlock Unexecuted instantiation: bgp_keepalives.c:_frr_mtx_unlock Unexecuted instantiation: bgp_labelpool.c:_frr_mtx_unlock Unexecuted instantiation: bgp_lcommunity.c:_frr_mtx_unlock Unexecuted instantiation: bgp_mac.c:_frr_mtx_unlock Unexecuted instantiation: bgp_mpath.c:_frr_mtx_unlock Unexecuted instantiation: bgp_mplsvpn.c:_frr_mtx_unlock Unexecuted instantiation: bgp_network.c:_frr_mtx_unlock Unexecuted instantiation: bgp_nexthop.c:_frr_mtx_unlock Unexecuted instantiation: bgp_nht.c:_frr_mtx_unlock Unexecuted instantiation: bgp_packet.c:_frr_mtx_unlock Unexecuted instantiation: bgp_pbr.c:_frr_mtx_unlock Unexecuted instantiation: bgp_rd.c:_frr_mtx_unlock Unexecuted instantiation: bgp_regex.c:_frr_mtx_unlock Unexecuted instantiation: bgp_route.c:_frr_mtx_unlock Unexecuted instantiation: bgp_routemap.c:_frr_mtx_unlock Unexecuted instantiation: bgp_routemap_nb.c:_frr_mtx_unlock Unexecuted instantiation: bgp_routemap_nb_config.c:_frr_mtx_unlock Unexecuted instantiation: bgp_table.c:_frr_mtx_unlock Unexecuted instantiation: bgp_updgrp.c:_frr_mtx_unlock Unexecuted instantiation: bgp_updgrp_adv.c:_frr_mtx_unlock Unexecuted instantiation: bgp_updgrp_packet.c:_frr_mtx_unlock Unexecuted instantiation: bgp_vpn.c:_frr_mtx_unlock Unexecuted instantiation: bgp_vty.c:_frr_mtx_unlock Unexecuted instantiation: bgp_zebra.c:_frr_mtx_unlock Unexecuted instantiation: bgpd.c:_frr_mtx_unlock Unexecuted instantiation: bgp_rfapi_cfg.c:_frr_mtx_unlock Unexecuted instantiation: rfapi_import.c:_frr_mtx_unlock Unexecuted instantiation: rfapi.c:_frr_mtx_unlock Unexecuted instantiation: rfapi_ap.c:_frr_mtx_unlock Unexecuted instantiation: rfapi_encap_tlv.c:_frr_mtx_unlock Unexecuted instantiation: rfapi_nve_addr.c:_frr_mtx_unlock Unexecuted instantiation: rfapi_monitor.c:_frr_mtx_unlock Unexecuted instantiation: rfapi_rib.c:_frr_mtx_unlock Unexecuted instantiation: rfapi_vty.c:_frr_mtx_unlock Unexecuted instantiation: vnc_export_bgp.c:_frr_mtx_unlock Unexecuted instantiation: vnc_export_table.c:_frr_mtx_unlock Unexecuted instantiation: vnc_import_bgp.c:_frr_mtx_unlock Unexecuted instantiation: vnc_zebra.c:_frr_mtx_unlock Unexecuted instantiation: bgp_addpath.c:_frr_mtx_unlock Unexecuted instantiation: bgp_advertise.c:_frr_mtx_unlock Unexecuted instantiation: bgp_aspath.c:_frr_mtx_unlock Unexecuted instantiation: bgp_bfd.c:_frr_mtx_unlock Unexecuted instantiation: bgp_conditional_adv.c:_frr_mtx_unlock Unexecuted instantiation: bgp_damp.c:_frr_mtx_unlock Unexecuted instantiation: bgp_encap_tlv.c:_frr_mtx_unlock Unexecuted instantiation: bgp_flowspec.c:_frr_mtx_unlock Unexecuted instantiation: bgp_flowspec_util.c:_frr_mtx_unlock Unexecuted instantiation: bgp_label.c:_frr_mtx_unlock Unexecuted instantiation: bgp_open.c:_frr_mtx_unlock Unexecuted instantiation: rfp_example.c:_frr_mtx_unlock |
252 | | |
253 | | #ifdef __cplusplus |
254 | | } |
255 | | #endif |
256 | | |
257 | | #endif /* _FRR_PTHREAD_H */ |