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 31 #ifdef __cplusplus 32 extern "C" { 33 #endif 34 35 struct rusage_t { 36 struct rusage cpu; 37 struct timeval real; 38 }; 39 #define RUSAGE_T struct rusage_t 40 41 #define GETRUSAGE(X) thread_getrusage(X) 42 43 PREDECL_LIST(thread_list) 44 PREDECL_HEAP(thread_timer_list) 45 46 struct fd_handler { 47 /* number of pfd that fit in the allocated space of pfds. This is a 48 * constant 49 * and is the same for both pfds and copy. */ 50 nfds_t pfdsize; 51 52 /* file descriptors to monitor for i/o */ 53 struct pollfd *pfds; 54 /* number of pollfds stored in pfds */ 55 nfds_t pfdcount; 56 57 /* chunk used for temp copy of pollfds */ 58 struct pollfd *copy; 59 /* number of pollfds stored in copy */ 60 nfds_t copycount; 61 }; 62 63 struct cancel_req { 64 struct thread *thread; 65 void *eventobj; 66 struct thread **threadref; 67 }; 68 69 /* Master of the theads. */ 70 struct thread_master { 71 char *name; 72 73 struct thread **read; 74 struct thread **write; 75 struct thread_timer_list_head timer; 76 struct thread_list_head event, ready, unuse; 77 struct list *cancel_req; 78 bool canceled; 79 pthread_cond_t cancel_cond; 80 struct hash *cpu_record; 81 int io_pipe[2]; 82 int fd_limit; 83 struct fd_handler handler; 84 unsigned long alloc; 85 long selectpoll_timeout; 86 bool spin; 87 bool handle_signals; 88 pthread_mutex_t mtx; 89 pthread_t owner; 90 }; 91 92 /* Thread itself. */ 93 struct thread { 94 uint8_t type; /* thread type */ 95 uint8_t add_type; /* thread type */ 96 struct thread_list_item threaditem; 97 struct thread_timer_list_item timeritem; 98 struct thread **ref; /* external reference (if given) */ 99 struct thread_master *master; /* pointer to the struct thread_master */ 100 int (*func)(struct thread *); /* event function */ 101 void *arg; /* event argument */ 102 union { 103 int val; /* second argument of the event. */ 104 int fd; /* file descriptor in case of r/w */ 105 struct timeval sands; /* rest of time sands value. */ 106 } u; 107 struct timeval real; 108 struct cpu_thread_history *hist; /* cache pointer to cpu_history */ 109 unsigned long yield; /* yield time in microseconds */ 110 const char *funcname; /* name of thread function */ 111 const char *schedfrom; /* source file thread was scheduled from */ 112 int schedfrom_line; /* line number of source file */ 113 pthread_mutex_t mtx; /* mutex for thread.c functions */ 114 }; 115 116 struct cpu_thread_history { 117 int (*func)(struct thread *); 118 atomic_uint_fast32_t total_calls; 119 atomic_uint_fast32_t total_active; 120 struct time_stats { 121 atomic_size_t total, max; 122 } real; 123 struct time_stats cpu; 124 atomic_uint_fast32_t types; 125 const char *funcname; 126 }; 127 128 /* Struct timeval's tv_usec one second value. */ 129 #define TIMER_SECOND_MICRO 1000000L 130 131 /* Thread types. */ 132 #define THREAD_READ 0 133 #define THREAD_WRITE 1 134 #define THREAD_TIMER 2 135 #define THREAD_EVENT 3 136 #define THREAD_READY 4 137 #define THREAD_UNUSED 5 138 #define THREAD_EXECUTE 6 139 140 /* Thread yield time. */ 141 #define THREAD_YIELD_TIME_SLOT 10 * 1000L /* 10ms */ 142 143 #define THREAD_TIMER_STRLEN 12 144 145 /* Macros. */ 146 #define THREAD_ARG(X) ((X)->arg) 147 #define THREAD_FD(X) ((X)->u.fd) 148 #define THREAD_VAL(X) ((X)->u.val) 149 150 #define THREAD_OFF(thread) \ 151 do { \ 152 if (thread) { \ 153 thread_cancel(thread); \ 154 thread = NULL; \ 155 } \ 156 } while (0) 157 158 #define THREAD_READ_OFF(thread) THREAD_OFF(thread) 159 #define THREAD_WRITE_OFF(thread) THREAD_OFF(thread) 160 #define THREAD_TIMER_OFF(thread) THREAD_OFF(thread) 161 162 #define debugargdef const char *funcname, const char *schedfrom, int fromln 163 164 #define thread_add_read(m,f,a,v,t) funcname_thread_add_read_write(THREAD_READ,m,f,a,v,t,#f,__FILE__,__LINE__) 165 #define thread_add_write(m,f,a,v,t) funcname_thread_add_read_write(THREAD_WRITE,m,f,a,v,t,#f,__FILE__,__LINE__) 166 #define thread_add_timer(m,f,a,v,t) funcname_thread_add_timer(m,f,a,v,t,#f,__FILE__,__LINE__) 167 #define thread_add_timer_msec(m,f,a,v,t) funcname_thread_add_timer_msec(m,f,a,v,t,#f,__FILE__,__LINE__) 168 #define thread_add_timer_tv(m,f,a,v,t) funcname_thread_add_timer_tv(m,f,a,v,t,#f,__FILE__,__LINE__) 169 #define thread_add_event(m,f,a,v,t) funcname_thread_add_event(m,f,a,v,t,#f,__FILE__,__LINE__) 170 #define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__) 171 #define thread_execute_name(m, f, a, v, n) \ 172 funcname_thread_execute(m, f, a, v, n, __FILE__, __LINE__) 173 174 /* Prototypes. */ 175 extern struct thread_master *thread_master_create(const char *); 176 void thread_master_set_name(struct thread_master *master, const char *name); 177 extern void thread_master_free(struct thread_master *); 178 extern void thread_master_free_unused(struct thread_master *); 179 180 extern struct thread * 181 funcname_thread_add_read_write(int dir, struct thread_master *, 182 int (*)(struct thread *), void *, int, 183 struct thread **, debugargdef); 184 185 extern struct thread *funcname_thread_add_timer(struct thread_master *, 186 int (*)(struct thread *), 187 void *, long, struct thread **, 188 debugargdef); 189 190 extern struct thread * 191 funcname_thread_add_timer_msec(struct thread_master *, int (*)(struct thread *), 192 void *, long, struct thread **, debugargdef); 193 194 extern struct thread *funcname_thread_add_timer_tv(struct thread_master *, 195 int (*)(struct thread *), 196 void *, struct timeval *, 197 struct thread **, 198 debugargdef); 199 200 extern struct thread *funcname_thread_add_event(struct thread_master *, 201 int (*)(struct thread *), 202 void *, int, struct thread **, 203 debugargdef); 204 205 extern void funcname_thread_execute(struct thread_master *, 206 int (*)(struct thread *), void *, int, 207 debugargdef); 208 #undef debugargdef 209 210 extern void thread_cancel(struct thread *); 211 extern void thread_cancel_async(struct thread_master *, struct thread **, 212 void *); 213 extern void thread_cancel_event(struct thread_master *, void *); 214 extern struct thread *thread_fetch(struct thread_master *, struct thread *); 215 extern void thread_call(struct thread *); 216 extern unsigned long thread_timer_remain_second(struct thread *); 217 extern struct timeval thread_timer_remain(struct thread *); 218 extern unsigned long thread_timer_remain_msec(struct thread *); 219 extern int thread_should_yield(struct thread *); 220 /* set yield time for thread */ 221 extern void thread_set_yield_time(struct thread *, unsigned long); 222 223 /* Internal libfrr exports */ 224 extern void thread_getrusage(RUSAGE_T *); 225 extern void thread_cmd_init(void); 226 227 /* Returns elapsed real (wall clock) time. */ 228 extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before, 229 unsigned long *cpu_time_elapsed); 230 231 /* only for use in logging functions! */ 232 extern pthread_key_t thread_current; 233 extern char *thread_timer_to_hhmmss(char *buf, int buf_size, 234 struct thread *t_timer); 235 236 /* Debug signal mask */ 237 void debug_signals(const sigset_t *sigs); 238 239 #ifdef __cplusplus 240 } 241 #endif 242 243 #endif /* _ZEBRA_THREAD_H */ 244