]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/frr_pthread.h
lib: enforce vrf_name_to_id by returning default_vrf when name is null
[mirror_frr.git] / lib / frr_pthread.h
index 7915b43a46d8b59c1d047e1622049d10979baac5..b9e60511d56aa7e725593e87c8533bad699e1202 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Utilities and interfaces for managing POSIX threads
- * Copyright (C) 2017  Cumulus Networks
+ * Utilities and interfaces for managing POSIX threads within FRR.
+ * Copyright (C) 2017  Cumulus Networks, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #define _FRR_PTHREAD_H
 
 #include <pthread.h>
+#include "frratomic.h"
 #include "memory.h"
 #include "thread.h"
 
+DECLARE_MTYPE(FRR_PTHREAD);
 DECLARE_MTYPE(PTHREAD_PRIM);
 
+#define OS_THREAD_NAMELEN 16
+
+struct frr_pthread;
+struct frr_pthread_attr;
+
+struct frr_pthread_attr {
+       void *(*start)(void *);
+       int (*stop)(struct frr_pthread *, void **);
+};
+
 struct frr_pthread {
 
+       /*
+        * Mutex protecting this structure. Must be taken for reading some
+        * fields, denoted by a 'Requires: mtx'.
+        */
+       pthread_mutex_t mtx;
+
        /* pthread id */
        pthread_t thread;
 
-       /* frr thread identifier */
-       unsigned int id;
-
        /* thread master for this pthread's thread.c event loop */
        struct thread_master *master;
 
-       /* start routine */
-       void *(*start_routine)(void *);
-
-       /* stop routine */
-       int (*stop_routine)(void **, struct frr_pthread *);
-
-       /* the (hopefully descriptive) name of this thread */
+       /* caller-specified data; start & stop funcs, name, id */
+       struct frr_pthread_attr attr;
+
+       /*
+        * Notification mechanism for allowing pthreads to notify their parents
+        * when they are ready to do work. This mechanism has two associated
+        * functions:
+        *
+        * - frr_pthread_wait_running()
+        *   This function should be called by the spawning thread after
+        *   frr_pthread_run(). It safely waits until the spawned thread
+        *   indicates that is ready to do work by posting to the condition
+        *   variable.
+        *
+        * - frr_pthread_notify_running()
+        *   This function should be called by the spawned thread when it is
+        *   ready to do work. It will wake up any threads waiting on the
+        *   previously described condition.
+        */
+       pthread_cond_t *running_cond;
+       pthread_mutex_t *running_cond_mtx;
+       _Atomic bool running;
+
+       /*
+        * Fake thread-specific storage. No constraints on usage. Helpful when
+        * creating reentrant pthread implementations. Can be used to pass
+        * argument to pthread entry function.
+        *
+        * Requires: mtx
+        */
+       void *data;
+
+       /*
+        * Human-readable thread name.
+        *
+        * Requires: mtx
+        */
        char *name;
+
+       /* Used in pthread_set_name max 16 characters */
+       char os_name[OS_THREAD_NAMELEN];
 };
 
-/* Initializes this module.
+extern struct frr_pthread_attr frr_pthread_attr_default;
+
+/*
+ * Initializes this module.
  *
  * Must be called before using any of the other functions.
  */
 void frr_pthread_init(void);
 
-/* Uninitializes this module.
+/*
+ * Uninitializes this module.
  *
  * Destroys all registered frr_pthread's and internal data structures.
  *
@@ -62,34 +114,38 @@ void frr_pthread_init(void);
  */
 void frr_pthread_finish(void);
 
-/* Creates a new frr_pthread.
- *
- * If the provided ID is already assigned to an existing frr_pthread, the
- * return value will be NULL.
- *
- * @param name - the name of the thread. Doesn't have to be unique, but it
- * probably should be. This value is copied and may be safely free'd upon
- * return.
- *
- * @param id - the integral ID of the thread. MUST be unique. The caller may
- * use this id to retrieve the thread.
- *
- * @param start_routine - start routine for the pthread, will be passed to
- * pthread_create (see those docs for details)
- *
- * @param stop_routine - stop routine for the pthread, called to terminate the
- * thread. This function should gracefully stop the pthread and clean up any
- * thread-specific resources. The passed pointer is used to return a data
- * result.
- *
+/*
+ * Creates a new frr_pthread with the given attributes.
+ *
+ * The 'attr' argument should be filled out with the desired attributes,
+ * including ID, start and stop functions and the desired name. Alternatively,
+ * if attr is NULL, the default attributes will be used. The pthread will be
+ * set up to run a basic threadmaster loop and the name will be "Anonymous".
+ * Scheduling tasks onto the threadmaster in the 'master' field of the returned
+ * frr_pthread will cause them to run on that pthread.
+ *
+ * @param attr - the thread attributes
+ * @param name - Human-readable name
+ * @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(const char *name, unsigned int id,
-                                   void *(*start_routine)(void *),
-                                   int (*stop_routine)(void **,
-                                                       struct frr_pthread *));
+struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr,
+                                   const char *name, const char *os_name);
 
-/* Destroys an frr_pthread.
+/*
+ * Changes the name of the frr_pthread.
+ *
+ * @param fpt - the frr_pthread to operate on
+ * @param name - Human-readable name
+ * @param os_name - 16 characters thread name , including the null
+ * terminator ('\0') to set in os.
+ * @return -  on success returns 0 otherwise nonzero error number.
+ */
+int frr_pthread_set_name(struct frr_pthread *fpt, const char *name,
+                        const char *os_name);
+
+/*
+ * Destroys an frr_pthread.
  *
  * Assumes that the associated pthread, if any, has already terminated.
  *
@@ -97,55 +153,65 @@ struct frr_pthread *frr_pthread_new(const char *name, unsigned int id,
  */
 void frr_pthread_destroy(struct frr_pthread *fpt);
 
-/* Gets an existing frr_pthread by its id.
- *
- * @return frr_thread associated with the provided id, or NULL on error
- */
-struct frr_pthread *frr_pthread_get(unsigned int id);
-
-/* Creates a new pthread and binds it to a frr_pthread.
+/*
+ * Creates a new pthread and binds it to a frr_pthread.
  *
  * This function is a wrapper for pthread_create. The first parameter is the
  * frr_pthread to bind the created pthread to. All subsequent arguments are
- * passed unmodified to pthread_create().
+ * passed unmodified to pthread_create(). The frr_pthread * provided will be
+ * used as the argument to the pthread entry function. If it is necessary to
+ * pass additional data, the 'data' field in the frr_pthread may be used.
  *
  * This function returns the same code as pthread_create(). If the value is
  * zero, the provided frr_pthread is bound to a running POSIX thread. If the
  * value is less than zero, the provided frr_pthread is guaranteed to be a
  * clean instance that may be susbsequently passed to frr_pthread_run().
  *
- * @param id - frr_pthread to bind the created pthread to
+ * @param fpt - frr_pthread * to run
  * @param attr - see pthread_create(3)
- * @param arg - see pthread_create(3)
  *
  * @return see pthread_create(3)
  */
-int frr_pthread_run(unsigned int id, const pthread_attr_t *attr, void *arg);
+int frr_pthread_run(struct frr_pthread *fpt, const pthread_attr_t *attr);
 
-/* Stops an frr_pthread with a result.
+/*
+ * Waits until the specified pthread has finished setting up and is ready to
+ * begin work.
+ *
+ * If the pthread's code makes use of the startup synchronization mechanism,
+ * this function should be called before attempting to use the functionality
+ * exposed by the pthread. It waits until the 'running' condition is satisfied
+ * (see struct definition of frr_pthread).
  *
- * @param id - frr_pthread to stop
+ * @param fpt - the frr_pthread * to wait on
+ */
+void frr_pthread_wait_running(struct frr_pthread *fpt);
+
+/*
+ * Notifies other pthreads that the calling thread has finished setting up and
+ * is ready to begin work.
+ *
+ * This will allow any other pthreads waiting in 'frr_pthread_wait_running' to
+ * proceed.
+ *
+ * @param fpt - the frr_pthread * that has finished setting up
+ */
+void frr_pthread_notify_running(struct frr_pthread *fpt);
+
+/*
+ * Stops a frr_pthread with a result.
+ *
+ * @param fpt - frr_pthread * to stop
  * @param result - where to store the thread's result, if any. May be NULL if a
  * result is not needed.
  */
-int frr_pthread_stop(unsigned int id, void **result);
+int frr_pthread_stop(struct frr_pthread *fpt, void **result);
 
 /* Stops all frr_pthread's. */
 void frr_pthread_stop_all(void);
 
-/* Yields the current thread of execution */
-void frr_pthread_yield(void);
-
-/* Returns a unique identifier for use with frr_pthread_new().
- *
- * Internally, this is an integer that increments after each call to this
- * function. Because the number of pthreads created should never exceed INT_MAX
- * during the life of the program, there is no overflow protection. If by
- * chance this function returns an ID which is already in use,
- * frr_pthread_new() will fail when it is provided.
- *
- * @return unique identifier
- */
-unsigned int frr_pthread_get_id(void);
+#ifndef HAVE_PTHREAD_CONDATTR_SETCLOCK
+#define pthread_condattr_setclock(A, B)
+#endif
 
 #endif /* _FRR_PTHREAD_H */