]> git.proxmox.com Git - mirror_frr.git/blame - lib/frr_pthread.h
*: Convert `struct event_master` to `struct event_loop`
[mirror_frr.git] / lib / frr_pthread.h
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
98f14af8 2/*
a45dc974 3 * Utilities and interfaces for managing POSIX threads within FRR.
d8a8a8de 4 * Copyright (C) 2017 Cumulus Networks, Inc.
98f14af8
QY
5 */
6
7#ifndef _FRR_PTHREAD_H
8#define _FRR_PTHREAD_H
9
10#include <pthread.h>
a45dc974 11#include "frratomic.h"
0bbb9e72 12#include "memory.h"
3e41733f 13#include "frrcu.h"
cb37cb33 14#include "event.h"
98f14af8 15
5e244469
RW
16#ifdef __cplusplus
17extern "C" {
18#endif
19
57019528
CS
20#define OS_THREAD_NAMELEN 16
21
a45dc974
QY
22struct frr_pthread;
23struct frr_pthread_attr;
24
25struct frr_pthread_attr {
a45dc974
QY
26 void *(*start)(void *);
27 int (*stop)(struct frr_pthread *, void **);
a45dc974
QY
28};
29
98f14af8
QY
30struct frr_pthread {
31
d8a8a8de
QY
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
d62a17ae 38 /* pthread id */
39 pthread_t thread;
98f14af8 40
3e41733f
DL
41 struct rcu_thread *rcu_thread;
42
d62a17ae 43 /* thread master for this pthread's thread.c event loop */
cd9d0537 44 struct event_loop *master;
98f14af8 45
a45dc974
QY
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;
c8a65463 67 atomic_bool running;
a45dc974
QY
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.
d8a8a8de
QY
73 *
74 * Requires: mtx
a45dc974
QY
75 */
76 void *data;
d8a8a8de
QY
77
78 /*
79 * Human-readable thread name.
80 *
81 * Requires: mtx
82 */
83 char *name;
57019528
CS
84
85 /* Used in pthread_set_name max 16 characters */
86 char os_name[OS_THREAD_NAMELEN];
98f14af8
QY
87};
88
2b64873d 89extern const struct frr_pthread_attr frr_pthread_attr_default;
a45dc974
QY
90
91/*
92 * Initializes this module.
98f14af8
QY
93 *
94 * Must be called before using any of the other functions.
95 */
96void frr_pthread_init(void);
97
a45dc974
QY
98/*
99 * Uninitializes this module.
98f14af8
QY
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 */
106void frr_pthread_finish(void);
107
a45dc974
QY
108/*
109 * Creates a new frr_pthread with the given attributes.
98f14af8 110 *
a45dc974
QY
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.
98f14af8 117 *
a45dc974 118 * @param attr - the thread attributes
d8a8a8de 119 * @param name - Human-readable name
57019528 120 * @param os_name - 16 characters (including '\0') thread name to set in os,
98f14af8
QY
121 * @return the created frr_pthread upon success, or NULL upon failure
122 */
2b64873d 123struct frr_pthread *frr_pthread_new(const struct frr_pthread_attr *attr,
57019528 124 const char *name, const char *os_name);
d8a8a8de
QY
125
126/*
c80bedb8
DS
127 * Changes the name of the frr_pthread as reported by the operating
128 * system.
d8a8a8de
QY
129 *
130 * @param fpt - the frr_pthread to operate on
57019528 131 * @return - on success returns 0 otherwise nonzero error number.
d8a8a8de 132 */
c80bedb8 133int frr_pthread_set_name(struct frr_pthread *fpt);
98f14af8 134
a45dc974
QY
135/*
136 * Destroys an frr_pthread.
98f14af8
QY
137 *
138 * Assumes that the associated pthread, if any, has already terminated.
139 *
140 * @param fpt - the frr_pthread to destroy
141 */
142void frr_pthread_destroy(struct frr_pthread *fpt);
143
a45dc974
QY
144/*
145 * Creates a new pthread and binds it to a frr_pthread.
98f14af8
QY
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
a45dc974
QY
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.
98f14af8
QY
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 *
a45dc974 158 * @param fpt - frr_pthread * to run
98f14af8 159 * @param attr - see pthread_create(3)
98f14af8
QY
160 *
161 * @return see pthread_create(3)
162 */
a45dc974
QY
163int 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 */
176void frr_pthread_wait_running(struct frr_pthread *fpt);
98f14af8 177
a45dc974
QY
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.
98f14af8 184 *
a45dc974
QY
185 * @param fpt - the frr_pthread * that has finished setting up
186 */
187void 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
98f14af8
QY
193 * @param result - where to store the thread's result, if any. May be NULL if a
194 * result is not needed.
195 */
a45dc974 196int frr_pthread_stop(struct frr_pthread *fpt, void **result);
98f14af8
QY
197
198/* Stops all frr_pthread's. */
199void frr_pthread_stop_all(void);
200
afc9534f
DS
201#ifndef HAVE_PTHREAD_CONDATTR_SETCLOCK
202#define pthread_condattr_setclock(A, B)
203#endif
204
00dffa8c
DL
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 *NAMECTR(_mtx_) __attribute__(( \
219 unused, cleanup(_frr_mtx_unlock))) = _frr_mtx_lock(mutex), \
220 /* end */
221
222#define frr_with_mutex(...) \
223 for (pthread_mutex_t MACRO_REPEAT(_frr_with_mutex, ##__VA_ARGS__) \
224 *_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 pthread_mutex_t *NAMECTR(_mtx_) \
235 __attribute__((unused, cleanup(_frr_mtx_unlock))) = \
236 _frr_mtx_lock(mutex) \
237 /* end */
238
239static inline pthread_mutex_t *_frr_mtx_lock(pthread_mutex_t *mutex)
240{
241 pthread_mutex_lock(mutex);
242 return mutex;
243}
244
245static inline void _frr_mtx_unlock(pthread_mutex_t **mutex)
246{
247 if (!*mutex)
248 return;
249 pthread_mutex_unlock(*mutex);
250 *mutex = NULL;
251}
252
5e244469
RW
253#ifdef __cplusplus
254}
255#endif
256
98f14af8 257#endif /* _FRR_PTHREAD_H */