back to topotato report
topotato coverage report
Current view: top level - lib - frr_pthread.h (source / functions) Hit Total Coverage
Test: test_pim6_basic.py::PIM6Basic Lines: 7 7 100.0 %
Date: 2023-02-24 18:38:38 Functions: 0 0 -

          Line data    Source code
       1             : /*
       2             :  * Utilities and interfaces for managing POSIX threads within FRR.
       3             :  * Copyright (C) 2017  Cumulus Networks, Inc.
       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
      18             :  */
      19             : 
      20             : #ifndef _FRR_PTHREAD_H
      21             : #define _FRR_PTHREAD_H
      22             : 
      23             : #include <pthread.h>
      24             : #include "frratomic.h"
      25             : #include "memory.h"
      26             : #include "frrcu.h"
      27             : #include "thread.h"
      28             : 
      29             : #ifdef __cplusplus
      30             : extern "C" {
      31             : #endif
      32             : 
      33             : #define OS_THREAD_NAMELEN 16
      34             : 
      35             : struct frr_pthread;
      36             : struct frr_pthread_attr;
      37             : 
      38             : struct frr_pthread_attr {
      39             :         void *(*start)(void *);
      40             :         int (*stop)(struct frr_pthread *, void **);
      41             : };
      42             : 
      43             : struct frr_pthread {
      44             : 
      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             : 
      51             :         /* pthread id */
      52             :         pthread_t thread;
      53             : 
      54             :         struct rcu_thread *rcu_thread;
      55             : 
      56             :         /* thread master for this pthread's thread.c event loop */
      57             :         struct thread_master *master;
      58             : 
      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;
      80             :         atomic_bool running;
      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.
      86             :          *
      87             :          * Requires: mtx
      88             :          */
      89             :         void *data;
      90             : 
      91             :         /*
      92             :          * Human-readable thread name.
      93             :          *
      94             :          * Requires: mtx
      95             :          */
      96             :         char *name;
      97             : 
      98             :         /* Used in pthread_set_name max 16 characters */
      99             :         char os_name[OS_THREAD_NAMELEN];
     100             : };
     101             : 
     102             : extern const struct frr_pthread_attr frr_pthread_attr_default;
     103             : 
     104             : /*
     105             :  * Initializes this module.
     106             :  *
     107             :  * Must be called before using any of the other functions.
     108             :  */
     109             : void frr_pthread_init(void);
     110             : 
     111             : /*
     112             :  * Uninitializes this module.
     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             :  */
     119             : void frr_pthread_finish(void);
     120             : 
     121             : /*
     122             :  * Creates a new frr_pthread with the given attributes.
     123             :  *
     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.
     130             :  *
     131             :  * @param attr - the thread attributes
     132             :  * @param name - Human-readable name
     133             :  * @param os_name - 16 characters (including '\0') thread name to set in os,
     134             :  * @return the created frr_pthread upon success, or NULL upon failure
     135             :  */
     136             : struct frr_pthread *frr_pthread_new(const struct frr_pthread_attr *attr,
     137             :                                     const char *name, const char *os_name);
     138             : 
     139             : /*
     140             :  * Changes the name of the frr_pthread as reported by the operating
     141             :  * system.
     142             :  *
     143             :  * @param fpt - the frr_pthread to operate on
     144             :  * @return -  on success returns 0 otherwise nonzero error number.
     145             :  */
     146             : int frr_pthread_set_name(struct frr_pthread *fpt);
     147             : 
     148             : /*
     149             :  * Destroys an frr_pthread.
     150             :  *
     151             :  * Assumes that the associated pthread, if any, has already terminated.
     152             :  *
     153             :  * @param fpt - the frr_pthread to destroy
     154             :  */
     155             : void frr_pthread_destroy(struct frr_pthread *fpt);
     156             : 
     157             : /*
     158             :  * Creates a new pthread and binds it to a frr_pthread.
     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
     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.
     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             :  *
     171             :  * @param fpt - frr_pthread * to run
     172             :  * @param attr - see pthread_create(3)
     173             :  *
     174             :  * @return see pthread_create(3)
     175             :  */
     176             : int 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             :  */
     189             : void frr_pthread_wait_running(struct frr_pthread *fpt);
     190             : 
     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.
     197             :  *
     198             :  * @param fpt - the frr_pthread * that has finished setting up
     199             :  */
     200             : void 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
     206             :  * @param result - where to store the thread's result, if any. May be NULL if a
     207             :  * result is not needed.
     208             :  */
     209             : int frr_pthread_stop(struct frr_pthread *fpt, void **result);
     210             : 
     211             : /* Stops all frr_pthread's. */
     212             : void frr_pthread_stop_all(void);
     213             : 
     214             : #ifndef HAVE_PTHREAD_CONDATTR_SETCLOCK
     215             : #define pthread_condattr_setclock(A, B)
     216             : #endif
     217             : 
     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             : 
     252        5461 : static inline pthread_mutex_t *_frr_mtx_lock(pthread_mutex_t *mutex)
     253             : {
     254        5306 :         pthread_mutex_lock(mutex);
     255        5443 :         return mutex;
     256             : }
     257             : 
     258        5473 : static inline void _frr_mtx_unlock(pthread_mutex_t **mutex)
     259             : {
     260        5407 :         if (!*mutex)
     261             :                 return;
     262        5265 :         pthread_mutex_unlock(*mutex);
     263        2946 :         *mutex = NULL;
     264             : }
     265             : 
     266             : #ifdef __cplusplus
     267             : }
     268             : #endif
     269             : 
     270             : #endif /* _FRR_PTHREAD_H */

Generated by: LCOV version v1.16-topotato