diff options
author | Quentin Young <qlyoung@cumulusnetworks.com> | 2018-04-21 22:51:54 +0200 |
---|---|---|
committer | Quentin Young <qlyoung@cumulusnetworks.com> | 2018-05-07 17:37:07 +0200 |
commit | 363e24c65140d07c2ced580698bd1427c6b99a55 (patch) | |
tree | 9fa78138b63b883535e8b1a8f099d7fd721eb17a /lib/stream.h | |
parent | Merge pull request #2156 from donaldsharp/zebra_doc (diff) | |
download | frr-363e24c65140d07c2ced580698bd1427c6b99a55.tar.xz frr-363e24c65140d07c2ced580698bd1427c6b99a55.zip |
lib: add mt-safe variants for stream_fifo ops
stream_fifo is used as our standard internal message queue. Message
queues are useful in multithreaded environments. Up until now I have
been doing my own synchronization when using stream_fifo in this way;
this patch gets rid of the need for that boilerplate and decreases the
risk of locking mistakes when working with this datastructure.
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'lib/stream.h')
-rw-r--r-- | lib/stream.h | 93 |
1 files changed, 91 insertions, 2 deletions
diff --git a/lib/stream.h b/lib/stream.h index cc74e22a6..e5d325e43 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -22,6 +22,9 @@ #ifndef _ZEBRA_STREAM_H #define _ZEBRA_STREAM_H +#include <pthread.h> + +#include "frratomic.h" #include "mpls.h" #include "prefix.h" @@ -107,7 +110,11 @@ struct stream { /* First in first out queue structure. */ struct stream_fifo { - size_t count; + /* lock for mt-safe operations */ + pthread_mutex_t mtx; + + /* number of streams in this fifo */ + _Atomic size_t count; struct stream *head; struct stream *tail; @@ -240,12 +247,94 @@ extern int stream_empty(struct stream *); /* is the stream empty? */ /* deprecated */ extern uint8_t *stream_pnt(struct stream *); -/* Stream fifo. */ +/* + * Operations on struct stream_fifo. + * + * Each function has a safe variant, which ensures that the operation performed + * is atomic with respect to the operations performed by all other safe + * variants. In other words, the safe variants lock the stream_fifo's mutex + * before performing their action. These are provided for convenience when + * using stream_fifo in a multithreaded context, to alleviate the need for the + * caller to implement their own synchronization around the stream_fifo. + * + * The following functions do not have safe variants. The caller must ensure + * that these operations are performed safely in a multithreaded context: + * - stream_fifo_new + * - stream_fifo_free + */ + +/* + * Create a new stream_fifo. + * + * Returns: + * newly created stream_fifo + */ extern struct stream_fifo *stream_fifo_new(void); + +/* + * Push a stream onto a stream_fifo. + * + * fifo + * the stream_fifo to push onto + * + * s + * the stream to push onto the stream_fifo + */ extern void stream_fifo_push(struct stream_fifo *fifo, struct stream *s); +extern void stream_fifo_push_safe(struct stream_fifo *fifo, struct stream *s); + +/* + * Pop a stream off a stream_fifo. + * + * fifo + * the stream_fifo to pop from + * + * Returns: + * the next stream in the stream_fifo + */ extern struct stream *stream_fifo_pop(struct stream_fifo *fifo); +extern struct stream *stream_fifo_pop_safe(struct stream_fifo *fifo); + +/* + * Retrieve the next stream from a stream_fifo without popping it. + * + * fifo + * the stream_fifo to operate on + * + * Returns: + * the next stream that would be returned from stream_fifo_pop + */ extern struct stream *stream_fifo_head(struct stream_fifo *fifo); +extern struct stream *stream_fifo_head_safe(struct stream_fifo *fifo); + +/* + * Remove all streams from a stream_fifo. + * + * fifo + * the stream_fifo to clean + */ extern void stream_fifo_clean(struct stream_fifo *fifo); +extern void stream_fifo_clean_safe(struct stream_fifo *fifo); + +/* + * Retrieve number of streams on a stream_fifo. + * + * fifo + * the stream_fifo to retrieve the count for + * + * Returns: + * the number of streams on the stream_fifo + */ +extern size_t stream_fifo_count_safe(struct stream_fifo *fifo); + +/* + * Free a stream_fifo. + * + * Calls stream_fifo_clean, then deinitializes the stream_fifo and frees it. + * + * fifo + * the stream_fifo to free + */ extern void stream_fifo_free(struct stream_fifo *fifo); /* This is here because "<< 24" is particularly problematic in C. |