back to topotato report
topotato coverage report
Current view: top level - lib - thread.h (source / functions) Hit Total Coverage
Test: test_bgp_as_wide_bgp_identifier.py::TestBGPAsWideBGPIdentifier Lines: 6 6 100.0 %
Date: 2023-02-24 18:36:46 Functions: 0 0 -

          Line data    Source code
       1             : /* Thread management routine header.
       2             :  * Copyright (C) 1998 Kunihiro Ishiguro
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #ifndef _ZEBRA_THREAD_H
      22             : #define _ZEBRA_THREAD_H
      23             : 
      24             : #include <zebra.h>
      25             : #include <pthread.h>
      26             : #include <poll.h>
      27             : #include "monotime.h"
      28             : #include "frratomic.h"
      29             : #include "typesafe.h"
      30             : #include "xref.h"
      31             : 
      32             : #ifdef __cplusplus
      33             : extern "C" {
      34             : #endif
      35             : 
      36             : extern bool cputime_enabled;
      37             : extern unsigned long cputime_threshold;
      38             : /* capturing wallclock time is always enabled since it is fast (reading
      39             :  * hardware TSC w/o syscalls)
      40             :  */
      41             : extern unsigned long walltime_threshold;
      42             : 
      43             : struct rusage_t {
      44             : #ifdef HAVE_CLOCK_THREAD_CPUTIME_ID
      45             :         struct timespec cpu;
      46             : #else
      47             :         struct rusage cpu;
      48             : #endif
      49             :         struct timeval real;
      50             : };
      51             : #define RUSAGE_T        struct rusage_t
      52             : 
      53             : #define GETRUSAGE(X) thread_getrusage(X)
      54             : 
      55             : PREDECL_LIST(thread_list);
      56             : PREDECL_HEAP(thread_timer_list);
      57             : 
      58             : struct fd_handler {
      59             :         /* number of pfd that fit in the allocated space of pfds. This is a
      60             :          * constant and is the same for both pfds and copy.
      61             :          */
      62             :         nfds_t pfdsize;
      63             : 
      64             :         /* file descriptors to monitor for i/o */
      65             :         struct pollfd *pfds;
      66             :         /* number of pollfds stored in pfds */
      67             :         nfds_t pfdcount;
      68             : 
      69             :         /* chunk used for temp copy of pollfds */
      70             :         struct pollfd *copy;
      71             :         /* number of pollfds stored in copy */
      72             :         nfds_t copycount;
      73             : };
      74             : 
      75             : struct xref_threadsched {
      76             :         struct xref xref;
      77             : 
      78             :         const char *funcname;
      79             :         const char *dest;
      80             :         uint32_t thread_type;
      81             : };
      82             : 
      83             : /* Master of the theads. */
      84             : struct thread_master {
      85             :         char *name;
      86             : 
      87             :         struct thread **read;
      88             :         struct thread **write;
      89             :         struct thread_timer_list_head timer;
      90             :         struct thread_list_head event, ready, unuse;
      91             :         struct list *cancel_req;
      92             :         bool canceled;
      93             :         pthread_cond_t cancel_cond;
      94             :         struct hash *cpu_record;
      95             :         int io_pipe[2];
      96             :         int fd_limit;
      97             :         struct fd_handler handler;
      98             :         unsigned long alloc;
      99             :         long selectpoll_timeout;
     100             :         bool spin;
     101             :         bool handle_signals;
     102             :         pthread_mutex_t mtx;
     103             :         pthread_t owner;
     104             : 
     105             :         bool ready_run_loop;
     106             :         RUSAGE_T last_getrusage;
     107             : };
     108             : 
     109             : /* Thread itself. */
     110             : struct thread {
     111             :         uint8_t type;             /* thread type */
     112             :         uint8_t add_type;         /* thread type */
     113             :         struct thread_list_item threaditem;
     114             :         struct thread_timer_list_item timeritem;
     115             :         struct thread **ref;      /* external reference (if given) */
     116             :         struct thread_master *master; /* pointer to the struct thread_master */
     117             :         void (*func)(struct thread *); /* event function */
     118             :         void *arg;                    /* event argument */
     119             :         union {
     120             :                 int val;              /* second argument of the event. */
     121             :                 int fd;               /* file descriptor in case of r/w */
     122             :                 struct timeval sands; /* rest of time sands value. */
     123             :         } u;
     124             :         struct timeval real;
     125             :         struct cpu_thread_history *hist; /* cache pointer to cpu_history */
     126             :         unsigned long yield;             /* yield time in microseconds */
     127             :         const struct xref_threadsched *xref;   /* origin location */
     128             :         pthread_mutex_t mtx;   /* mutex for thread.c functions */
     129             :         bool ignore_timer_late;
     130             : };
     131             : 
     132             : #ifdef _FRR_ATTRIBUTE_PRINTFRR
     133             : #pragma FRR printfrr_ext "%pTH" (struct thread *)
     134             : #endif
     135             : 
     136             : struct cpu_thread_history {
     137             :         void (*func)(struct thread *);
     138             :         atomic_size_t total_cpu_warn;
     139             :         atomic_size_t total_wall_warn;
     140             :         atomic_size_t total_starv_warn;
     141             :         atomic_size_t total_calls;
     142             :         atomic_size_t total_active;
     143             :         struct time_stats {
     144             :                 atomic_size_t total, max;
     145             :         } real;
     146             :         struct time_stats cpu;
     147             :         atomic_uint_fast32_t types;
     148             :         const char *funcname;
     149             : };
     150             : 
     151             : /* Struct timeval's tv_usec one second value.  */
     152             : #define TIMER_SECOND_MICRO 1000000L
     153             : 
     154             : /* Thread types. */
     155             : #define THREAD_READ           0
     156             : #define THREAD_WRITE          1
     157             : #define THREAD_TIMER          2
     158             : #define THREAD_EVENT          3
     159             : #define THREAD_READY          4
     160             : #define THREAD_UNUSED         5
     161             : #define THREAD_EXECUTE        6
     162             : 
     163             : /* Thread yield time.  */
     164             : #define THREAD_YIELD_TIME_SLOT     10 * 1000L /* 10ms */
     165             : 
     166             : #define THREAD_TIMER_STRLEN 12
     167             : 
     168             : /* Macros. */
     169             : #define THREAD_ARG(X) ((X)->arg)
     170             : #define THREAD_FD(X)  ((X)->u.fd)
     171             : #define THREAD_VAL(X) ((X)->u.val)
     172             : 
     173             : /*
     174             :  * Please consider this macro deprecated, and do not use it in new code.
     175             :  */
     176             : #define THREAD_OFF(thread)                                             \
     177             :         do {                                                           \
     178             :                 if ((thread))                                          \
     179             :                         thread_cancel(&(thread));                      \
     180             :         } while (0)
     181             : 
     182             : /*
     183             :  * Macro wrappers to generate xrefs for all thread add calls.  Includes
     184             :  * file/line/function info for debugging/tracing.
     185             :  */
     186             : #include "lib/xref.h"
     187             : 
     188             : #define _xref_t_a(addfn, type, m, f, a, v, t)                                  \
     189             :         ({                                                                     \
     190             :                 static const struct xref_threadsched _xref                     \
     191             :                                 __attribute__((used)) = {                      \
     192             :                         .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__),  \
     193             :                         .funcname = #f,                                        \
     194             :                         .dest = #t,                                            \
     195             :                         .thread_type = THREAD_ ## type,                        \
     196             :                 };                                                             \
     197             :                 XREF_LINK(_xref.xref);                                         \
     198             :                 _thread_add_ ## addfn(&_xref, m, f, a, v, t);                  \
     199             :         })                                                                     \
     200             :         /* end */
     201             : 
     202             : #define thread_add_read(m,f,a,v,t)       _xref_t_a(read_write, READ,  m,f,a,v,t)
     203             : #define thread_add_write(m,f,a,v,t)      _xref_t_a(read_write, WRITE, m,f,a,v,t)
     204             : #define thread_add_timer(m,f,a,v,t)      _xref_t_a(timer,      TIMER, m,f,a,v,t)
     205             : #define thread_add_timer_msec(m,f,a,v,t) _xref_t_a(timer_msec, TIMER, m,f,a,v,t)
     206             : #define thread_add_timer_tv(m,f,a,v,t)   _xref_t_a(timer_tv,   TIMER, m,f,a,v,t)
     207             : #define thread_add_event(m,f,a,v,t)      _xref_t_a(event,      EVENT, m,f,a,v,t)
     208             : 
     209             : #define thread_execute(m,f,a,v)                                                \
     210             :         ({                                                                     \
     211             :                 static const struct xref_threadsched _xref                     \
     212             :                                 __attribute__((used)) = {                      \
     213             :                         .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__),  \
     214             :                         .funcname = #f,                                        \
     215             :                         .dest = NULL,                                          \
     216             :                         .thread_type = THREAD_EXECUTE,                         \
     217             :                 };                                                             \
     218             :                 XREF_LINK(_xref.xref);                                         \
     219             :                 _thread_execute(&_xref, m, f, a, v);                           \
     220             :         }) /* end */
     221             : 
     222             : /* Prototypes. */
     223             : extern struct thread_master *thread_master_create(const char *);
     224             : void thread_master_set_name(struct thread_master *master, const char *name);
     225             : extern void thread_master_free(struct thread_master *);
     226             : extern void thread_master_free_unused(struct thread_master *);
     227             : 
     228             : extern void _thread_add_read_write(const struct xref_threadsched *xref,
     229             :                                    struct thread_master *master,
     230             :                                    void (*fn)(struct thread *), void *arg,
     231             :                                    int fd, struct thread **tref);
     232             : 
     233             : extern void _thread_add_timer(const struct xref_threadsched *xref,
     234             :                               struct thread_master *master,
     235             :                               void (*fn)(struct thread *), void *arg, long t,
     236             :                               struct thread **tref);
     237             : 
     238             : extern void _thread_add_timer_msec(const struct xref_threadsched *xref,
     239             :                                    struct thread_master *master,
     240             :                                    void (*fn)(struct thread *), void *arg,
     241             :                                    long t, struct thread **tref);
     242             : 
     243             : extern void _thread_add_timer_tv(const struct xref_threadsched *xref,
     244             :                                  struct thread_master *master,
     245             :                                  void (*fn)(struct thread *), void *arg,
     246             :                                  struct timeval *tv, struct thread **tref);
     247             : 
     248             : extern void _thread_add_event(const struct xref_threadsched *xref,
     249             :                               struct thread_master *master,
     250             :                               void (*fn)(struct thread *), void *arg, int val,
     251             :                               struct thread **tref);
     252             : 
     253             : extern void _thread_execute(const struct xref_threadsched *xref,
     254             :                             struct thread_master *master,
     255             :                             void (*fn)(struct thread *), void *arg, int val);
     256             : 
     257             : extern void thread_cancel(struct thread **event);
     258             : extern void thread_cancel_async(struct thread_master *, struct thread **,
     259             :                                 void *);
     260             : /* Cancel ready tasks with an arg matching 'arg' */
     261             : extern void thread_cancel_event_ready(struct thread_master *m, void *arg);
     262             : /* Cancel all tasks with an arg matching 'arg', including timers and io */
     263             : extern void thread_cancel_event(struct thread_master *m, void *arg);
     264             : extern struct thread *thread_fetch(struct thread_master *, struct thread *);
     265             : extern void thread_call(struct thread *);
     266             : extern unsigned long thread_timer_remain_second(struct thread *);
     267             : extern struct timeval thread_timer_remain(struct thread *);
     268             : extern unsigned long thread_timer_remain_msec(struct thread *);
     269             : extern int thread_should_yield(struct thread *);
     270             : /* set yield time for thread */
     271             : extern void thread_set_yield_time(struct thread *, unsigned long);
     272             : 
     273             : /* Internal libfrr exports */
     274             : extern void thread_getrusage(RUSAGE_T *);
     275             : extern void thread_cmd_init(void);
     276             : 
     277             : /* Returns elapsed real (wall clock) time. */
     278             : extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before,
     279             :                                           unsigned long *cpu_time_elapsed);
     280             : 
     281             : /* only for use in logging functions! */
     282             : extern pthread_key_t thread_current;
     283             : extern char *thread_timer_to_hhmmss(char *buf, int buf_size,
     284             :                 struct thread *t_timer);
     285             : 
     286         112 : static inline bool thread_is_scheduled(struct thread *thread)
     287             : {
     288         112 :         if (thread)
     289          13 :                 return true;
     290             : 
     291             :         return false;
     292             : }
     293             : 
     294             : /* Debug signal mask */
     295             : void debug_signals(const sigset_t *sigs);
     296             : 
     297          16 : static inline void thread_ignore_late_timer(struct thread *thread)
     298             : {
     299          16 :         thread->ignore_timer_late = true;
     300          10 : }
     301             : 
     302             : #ifdef __cplusplus
     303             : }
     304             : #endif
     305             : 
     306             : #endif /* _ZEBRA_THREAD_H */

Generated by: LCOV version v1.16-topotato