]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/frr_pthread.h
bgpd: Zebra lib for Graceful Restart.
[mirror_frr.git] / lib / frr_pthread.h
index e6b3f031b3325447e09235c0e7b4316a03224989..89519abae0165402010a2a9a54d8ed006be746dc 100644 (file)
 #include <pthread.h>
 #include "frratomic.h"
 #include "memory.h"
+#include "frrcu.h"
 #include "thread.h"
 
-DECLARE_MTYPE(FRR_PTHREAD);
-DECLARE_MTYPE(PTHREAD_PRIM);
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 #define OS_THREAD_NAMELEN 16
 
@@ -49,6 +51,8 @@ struct frr_pthread {
        /* pthread id */
        pthread_t thread;
 
+       struct rcu_thread *rcu_thread;
+
        /* thread master for this pthread's thread.c event loop */
        struct thread_master *master;
 
@@ -73,7 +77,7 @@ struct frr_pthread {
         */
        pthread_cond_t *running_cond;
        pthread_mutex_t *running_cond_mtx;
-       _Atomic bool running;
+       atomic_bool running;
 
        /*
         * Fake thread-specific storage. No constraints on usage. Helpful when
@@ -95,7 +99,7 @@ struct frr_pthread {
        char os_name[OS_THREAD_NAMELEN];
 };
 
-extern struct frr_pthread_attr frr_pthread_attr_default;
+extern const struct frr_pthread_attr frr_pthread_attr_default;
 
 /*
  * Initializes this module.
@@ -129,7 +133,7 @@ void frr_pthread_finish(void);
  * @param os_name - 16 characters (including '\0') thread name to set in os,
  * @return the created frr_pthread upon success, or NULL upon failure
  */
-struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr,
+struct frr_pthread *frr_pthread_new(const struct frr_pthread_attr *attr,
                                    const char *name, const char *os_name);
 
 /*
@@ -211,4 +215,56 @@ void frr_pthread_stop_all(void);
 #define pthread_condattr_setclock(A, B)
 #endif
 
+/* mutex auto-lock/unlock */
+
+/* variant 1:
+ * (for short blocks, multiple mutexes supported)
+ * break & return can be used for aborting the block
+ *
+ * frr_with_mutex(&mtx, &mtx2) {
+ *    if (error)
+ *       break;
+ *    ...
+ * }
+ */
+#define _frr_with_mutex(mutex)                                                 \
+       *NAMECTR(_mtx_) __attribute__((                                        \
+               unused, cleanup(_frr_mtx_unlock))) = _frr_mtx_lock(mutex),     \
+       /* end */
+
+#define frr_with_mutex(...)                                                    \
+       for (pthread_mutex_t MACRO_REPEAT(_frr_with_mutex, ##__VA_ARGS__)      \
+            *_once = NULL; _once == NULL; _once = (void *)1)                  \
+       /* end */
+
+/* variant 2:
+ * (more suitable for long blocks, no extra indentation)
+ *
+ * frr_mutex_lock_autounlock(&mtx);
+ * ...
+ */
+#define frr_mutex_lock_autounlock(mutex)                                       \
+       pthread_mutex_t *NAMECTR(_mtx_)                                        \
+               __attribute__((unused, cleanup(_frr_mtx_unlock))) =            \
+                                   _frr_mtx_lock(mutex)                       \
+       /* end */
+
+static inline pthread_mutex_t *_frr_mtx_lock(pthread_mutex_t *mutex)
+{
+       pthread_mutex_lock(mutex);
+       return mutex;
+}
+
+static inline void _frr_mtx_unlock(pthread_mutex_t **mutex)
+{
+       if (!*mutex)
+               return;
+       pthread_mutex_unlock(*mutex);
+       *mutex = NULL;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _FRR_PTHREAD_H */