]> git.proxmox.com Git - mirror_frr.git/blame - lib/frr_pthread.h
Merge pull request #13278 from FRRouting/mergify/bp/stable/8.5/pr-13269
[mirror_frr.git] / lib / frr_pthread.h
CommitLineData
98f14af8 1/*
a45dc974 2 * Utilities and interfaces for managing POSIX threads within FRR.
d8a8a8de 3 * Copyright (C) 2017 Cumulus Networks, Inc.
896014f4
DL
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
98f14af8
QY
18 */
19
20#ifndef _FRR_PTHREAD_H
21#define _FRR_PTHREAD_H
22
23#include <pthread.h>
a45dc974 24#include "frratomic.h"
0bbb9e72 25#include "memory.h"
3e41733f 26#include "frrcu.h"
98f14af8
QY
27#include "thread.h"
28
5e244469
RW
29#ifdef __cplusplus
30extern "C" {
31#endif
32
57019528
CS
33#define OS_THREAD_NAMELEN 16
34
a45dc974
QY
35struct frr_pthread;
36struct frr_pthread_attr;
37
38struct frr_pthread_attr {
a45dc974
QY
39 void *(*start)(void *);
40 int (*stop)(struct frr_pthread *, void **);
a45dc974
QY
41};
42
98f14af8
QY
43struct frr_pthread {
44
d8a8a8de
QY
45 /*
46 * Mutex protecting this structure. Must be taken for reading some
47 * fields, denoted by a 'Requires: mtx'.
48 */
49 pthread_mutex_t mtx;
50
d62a17ae 51 /* pthread id */
52 pthread_t thread;
98f14af8 53
3e41733f
DL
54 struct rcu_thread *rcu_thread;
55
d62a17ae 56 /* thread master for this pthread's thread.c event loop */
57 struct thread_master *master;
98f14af8 58
a45dc974
QY
59 /* caller-specified data; start & stop funcs, name, id */
60 struct frr_pthread_attr attr;
61
62 /*
63 * Notification mechanism for allowing pthreads to notify their parents
64 * when they are ready to do work. This mechanism has two associated
65 * functions:
66 *
67 * - frr_pthread_wait_running()
68 * This function should be called by the spawning thread after
69 * frr_pthread_run(). It safely waits until the spawned thread
70 * indicates that is ready to do work by posting to the condition
71 * variable.
72 *
73 * - frr_pthread_notify_running()
74 * This function should be called by the spawned thread when it is
75 * ready to do work. It will wake up any threads waiting on the
76 * previously described condition.
77 */
78 pthread_cond_t *running_cond;
79 pthread_mutex_t *running_cond_mtx;
c8a65463 80 atomic_bool running;
a45dc974
QY
81
82 /*
83 * Fake thread-specific storage. No constraints on usage. Helpful when
84 * creating reentrant pthread implementations. Can be used to pass
85 * argument to pthread entry function.
d8a8a8de
QY
86 *
87 * Requires: mtx
a45dc974
QY
88 */
89 void *data;
d8a8a8de
QY
90
91 /*
92 * Human-readable thread name.
93 *
94 * Requires: mtx
95 */
96 char *name;
57019528
CS
97
98 /* Used in pthread_set_name max 16 characters */
99 char os_name[OS_THREAD_NAMELEN];
98f14af8
QY
100};
101
2b64873d 102extern const struct frr_pthread_attr frr_pthread_attr_default;
a45dc974
QY
103
104/*
105 * Initializes this module.
98f14af8
QY
106 *
107 * Must be called before using any of the other functions.
108 */
109void frr_pthread_init(void);
110
a45dc974
QY
111/*
112 * Uninitializes this module.
98f14af8
QY
113 *
114 * Destroys all registered frr_pthread's and internal data structures.
115 *
116 * It is safe to call frr_pthread_init() after this function to reinitialize
117 * the module.
118 */
119void frr_pthread_finish(void);
120
a45dc974
QY
121/*
122 * Creates a new frr_pthread with the given attributes.
98f14af8 123 *
a45dc974
QY
124 * The 'attr' argument should be filled out with the desired attributes,
125 * including ID, start and stop functions and the desired name. Alternatively,
126 * if attr is NULL, the default attributes will be used. The pthread will be
127 * set up to run a basic threadmaster loop and the name will be "Anonymous".
128 * Scheduling tasks onto the threadmaster in the 'master' field of the returned
129 * frr_pthread will cause them to run on that pthread.
98f14af8 130 *
a45dc974 131 * @param attr - the thread attributes
d8a8a8de 132 * @param name - Human-readable name
57019528 133 * @param os_name - 16 characters (including '\0') thread name to set in os,
98f14af8
QY
134 * @return the created frr_pthread upon success, or NULL upon failure
135 */
2b64873d 136struct frr_pthread *frr_pthread_new(const struct frr_pthread_attr *attr,
57019528 137 const char *name, const char *os_name);
d8a8a8de
QY
138
139/*
c80bedb8
DS
140 * Changes the name of the frr_pthread as reported by the operating
141 * system.
d8a8a8de
QY
142 *
143 * @param fpt - the frr_pthread to operate on
57019528 144 * @return - on success returns 0 otherwise nonzero error number.
d8a8a8de 145 */
c80bedb8 146int frr_pthread_set_name(struct frr_pthread *fpt);
98f14af8 147
a45dc974
QY
148/*
149 * Destroys an frr_pthread.
98f14af8
QY
150 *
151 * Assumes that the associated pthread, if any, has already terminated.
152 *
153 * @param fpt - the frr_pthread to destroy
154 */
155void frr_pthread_destroy(struct frr_pthread *fpt);
156
a45dc974
QY
157/*
158 * Creates a new pthread and binds it to a frr_pthread.
98f14af8
QY
159 *
160 * This function is a wrapper for pthread_create. The first parameter is the
161 * frr_pthread to bind the created pthread to. All subsequent arguments are
a45dc974
QY
162 * passed unmodified to pthread_create(). The frr_pthread * provided will be
163 * used as the argument to the pthread entry function. If it is necessary to
164 * pass additional data, the 'data' field in the frr_pthread may be used.
98f14af8
QY
165 *
166 * This function returns the same code as pthread_create(). If the value is
167 * zero, the provided frr_pthread is bound to a running POSIX thread. If the
168 * value is less than zero, the provided frr_pthread is guaranteed to be a
169 * clean instance that may be susbsequently passed to frr_pthread_run().
170 *
a45dc974 171 * @param fpt - frr_pthread * to run
98f14af8 172 * @param attr - see pthread_create(3)
98f14af8
QY
173 *
174 * @return see pthread_create(3)
175 */
a45dc974
QY
176int frr_pthread_run(struct frr_pthread *fpt, const pthread_attr_t *attr);
177
178/*
179 * Waits until the specified pthread has finished setting up and is ready to
180 * begin work.
181 *
182 * If the pthread's code makes use of the startup synchronization mechanism,
183 * this function should be called before attempting to use the functionality
184 * exposed by the pthread. It waits until the 'running' condition is satisfied
185 * (see struct definition of frr_pthread).
186 *
187 * @param fpt - the frr_pthread * to wait on
188 */
189void frr_pthread_wait_running(struct frr_pthread *fpt);
98f14af8 190
a45dc974
QY
191/*
192 * Notifies other pthreads that the calling thread has finished setting up and
193 * is ready to begin work.
194 *
195 * This will allow any other pthreads waiting in 'frr_pthread_wait_running' to
196 * proceed.
98f14af8 197 *
a45dc974
QY
198 * @param fpt - the frr_pthread * that has finished setting up
199 */
200void frr_pthread_notify_running(struct frr_pthread *fpt);
201
202/*
203 * Stops a frr_pthread with a result.
204 *
205 * @param fpt - frr_pthread * to stop
98f14af8
QY
206 * @param result - where to store the thread's result, if any. May be NULL if a
207 * result is not needed.
208 */
a45dc974 209int frr_pthread_stop(struct frr_pthread *fpt, void **result);
98f14af8
QY
210
211/* Stops all frr_pthread's. */
212void frr_pthread_stop_all(void);
213
afc9534f
DS
214#ifndef HAVE_PTHREAD_CONDATTR_SETCLOCK
215#define pthread_condattr_setclock(A, B)
216#endif
217
00dffa8c
DL
218/* mutex auto-lock/unlock */
219
220/* variant 1:
221 * (for short blocks, multiple mutexes supported)
222 * break & return can be used for aborting the block
223 *
224 * frr_with_mutex(&mtx, &mtx2) {
225 * if (error)
226 * break;
227 * ...
228 * }
229 */
230#define _frr_with_mutex(mutex) \
231 *NAMECTR(_mtx_) __attribute__(( \
232 unused, cleanup(_frr_mtx_unlock))) = _frr_mtx_lock(mutex), \
233 /* end */
234
235#define frr_with_mutex(...) \
236 for (pthread_mutex_t MACRO_REPEAT(_frr_with_mutex, ##__VA_ARGS__) \
237 *_once = NULL; _once == NULL; _once = (void *)1) \
238 /* end */
239
240/* variant 2:
241 * (more suitable for long blocks, no extra indentation)
242 *
243 * frr_mutex_lock_autounlock(&mtx);
244 * ...
245 */
246#define frr_mutex_lock_autounlock(mutex) \
247 pthread_mutex_t *NAMECTR(_mtx_) \
248 __attribute__((unused, cleanup(_frr_mtx_unlock))) = \
249 _frr_mtx_lock(mutex) \
250 /* end */
251
252static inline pthread_mutex_t *_frr_mtx_lock(pthread_mutex_t *mutex)
253{
254 pthread_mutex_lock(mutex);
255 return mutex;
256}
257
258static inline void _frr_mtx_unlock(pthread_mutex_t **mutex)
259{
260 if (!*mutex)
261 return;
262 pthread_mutex_unlock(*mutex);
263 *mutex = NULL;
264}
265
5e244469
RW
266#ifdef __cplusplus
267}
268#endif
269
98f14af8 270#endif /* _FRR_PTHREAD_H */