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 17 * along with GNU Zebra; see the file COPYING. If not, write to the Free 18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 * 02111-1307, USA. 20 */ 21 22 #ifndef _ZEBRA_THREAD_H 23 #define _ZEBRA_THREAD_H 24 25 #include <zebra.h> 26 27 struct rusage_t 28 { 29 #ifdef HAVE_RUSAGE 30 struct rusage cpu; 31 #endif 32 struct timeval real; 33 }; 34 #define RUSAGE_T struct rusage_t 35 36 #define GETRUSAGE(X) thread_getrusage(X) 37 38 /* Linked list of thread. */ 39 struct thread_list 40 { 41 struct thread *head; 42 struct thread *tail; 43 int count; 44 }; 45 46 struct pqueue; 47 48 /* 49 * Abstract it so we can use different methodologies to 50 * select on data. 51 */ 52 typedef fd_set thread_fd_set; 53 54 /* Master of the theads. */ 55 struct thread_master 56 { 57 struct thread **read; 58 struct thread **write; 59 struct pqueue *timer; 60 struct thread_list event; 61 struct thread_list ready; 62 struct thread_list unuse; 63 struct pqueue *background; 64 int fd_limit; 65 thread_fd_set readfd; 66 thread_fd_set writefd; 67 thread_fd_set exceptfd; 68 unsigned long alloc; 69 }; 70 71 typedef unsigned char thread_type; 72 73 /* Thread itself. */ 74 struct thread 75 { 76 thread_type type; /* thread type */ 77 thread_type add_type; /* thread type */ 78 struct thread *next; /* next pointer of the thread */ 79 struct thread *prev; /* previous pointer of the thread */ 80 struct thread_master *master; /* pointer to the struct thread_master. */ 81 int (*func) (struct thread *); /* event function */ 82 void *arg; /* event argument */ 83 union { 84 int val; /* second argument of the event. */ 85 int fd; /* file descriptor in case of read/write. */ 86 struct timeval sands; /* rest of time sands value. */ 87 } u; 88 int index; /* used for timers to store position in queue */ 89 struct timeval real; 90 struct cpu_thread_history *hist; /* cache pointer to cpu_history */ 91 const char *funcname; 92 const char *schedfrom; 93 int schedfrom_line; 94 }; 95 96 struct cpu_thread_history 97 { 98 int (*func)(struct thread *); 99 unsigned int total_calls; 100 struct time_stats 101 { 102 unsigned long total, max; 103 } real; 104 #ifdef HAVE_RUSAGE 105 struct time_stats cpu; 106 #endif 107 thread_type types; 108 const char *funcname; 109 }; 110 111 /* Clocks supported by Quagga */ 112 enum quagga_clkid { 113 QUAGGA_CLK_REALTIME = 0, /* ala gettimeofday() */ 114 QUAGGA_CLK_MONOTONIC, /* monotonic, against an indeterminate base */ 115 QUAGGA_CLK_REALTIME_STABILISED, /* like realtime, but non-decrementing */ 116 }; 117 118 /* Thread types. */ 119 #define THREAD_READ 0 120 #define THREAD_WRITE 1 121 #define THREAD_TIMER 2 122 #define THREAD_EVENT 3 123 #define THREAD_READY 4 124 #define THREAD_BACKGROUND 5 125 #define THREAD_UNUSED 6 126 #define THREAD_EXECUTE 7 127 128 /* Thread yield time. */ 129 #define THREAD_YIELD_TIME_SLOT 10 * 1000L /* 10ms */ 130 131 /* Macros. */ 132 #define THREAD_ARG(X) ((X)->arg) 133 #define THREAD_FD(X) ((X)->u.fd) 134 #define THREAD_VAL(X) ((X)->u.val) 135 136 #define THREAD_READ_ON(master,thread,func,arg,sock) \ 137 do { \ 138 if (! thread) \ 139 thread = thread_add_read (master, func, arg, sock); \ 140 } while (0) 141 142 #define THREAD_WRITE_ON(master,thread,func,arg,sock) \ 143 do { \ 144 if (! thread) \ 145 thread = thread_add_write (master, func, arg, sock); \ 146 } while (0) 147 148 #define THREAD_TIMER_ON(master,thread,func,arg,time) \ 149 do { \ 150 if (! thread) \ 151 thread = thread_add_timer (master, func, arg, time); \ 152 } while (0) 153 154 #define THREAD_TIMER_MSEC_ON(master,thread,func,arg,time) \ 155 do { \ 156 if (! thread) \ 157 thread = thread_add_timer_msec (master, func, arg, time); \ 158 } while (0) 159 160 #define THREAD_OFF(thread) \ 161 do { \ 162 if (thread) \ 163 { \ 164 thread_cancel (thread); \ 165 thread = NULL; \ 166 } \ 167 } while (0) 168 169 #define THREAD_READ_OFF(thread) THREAD_OFF(thread) 170 #define THREAD_WRITE_OFF(thread) THREAD_OFF(thread) 171 #define THREAD_TIMER_OFF(thread) THREAD_OFF(thread) 172 173 #define debugargdef const char *funcname, const char *schedfrom, int fromln 174 175 #define thread_add_read(m,f,a,v) funcname_thread_add_read(m,f,a,v,#f,__FILE__,__LINE__) 176 #define thread_add_write(m,f,a,v) funcname_thread_add_write(m,f,a,v,#f,__FILE__,__LINE__) 177 #define thread_add_timer(m,f,a,v) funcname_thread_add_timer(m,f,a,v,#f,__FILE__,__LINE__) 178 #define thread_add_timer_msec(m,f,a,v) funcname_thread_add_timer_msec(m,f,a,v,#f,__FILE__,__LINE__) 179 #define thread_add_timer_tv(m,f,a,v) funcname_thread_add_timer_tv(m,f,a,v,#f,__FILE__,__LINE__) 180 #define thread_add_event(m,f,a,v) funcname_thread_add_event(m,f,a,v,#f,__FILE__,__LINE__) 181 #define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__) 182 183 /* The 4th arg to thread_add_background is the # of milliseconds to delay. */ 184 #define thread_add_background(m,f,a,v) funcname_thread_add_background(m,f,a,v,#f,__FILE__,__LINE__) 185 186 /* Prototypes. */ 187 extern struct thread_master *thread_master_create (void); 188 extern void thread_master_free (struct thread_master *); 189 190 extern struct thread *funcname_thread_add_read (struct thread_master *, 191 int (*)(struct thread *), 192 void *, int, debugargdef); 193 extern struct thread *funcname_thread_add_write (struct thread_master *, 194 int (*)(struct thread *), 195 void *, int, debugargdef); 196 extern struct thread *funcname_thread_add_timer (struct thread_master *, 197 int (*)(struct thread *), 198 void *, long, debugargdef); 199 extern struct thread *funcname_thread_add_timer_msec (struct thread_master *, 200 int (*)(struct thread *), 201 void *, long, debugargdef); 202 extern struct thread *funcname_thread_add_timer_tv (struct thread_master *, 203 int (*)(struct thread *), 204 void *, struct timeval *, 205 debugargdef); 206 extern struct thread *funcname_thread_add_event (struct thread_master *, 207 int (*)(struct thread *), 208 void *, int, debugargdef); 209 extern struct thread *funcname_thread_add_background (struct thread_master *, 210 int (*func)(struct thread *), 211 void *arg, 212 long milliseconds_to_delay, 213 debugargdef); 214 extern struct thread *funcname_thread_execute (struct thread_master *, 215 int (*)(struct thread *), 216 void *, int, debugargdef); 217 #undef debugargdef 218 219 extern void thread_cancel (struct thread *); 220 extern unsigned int thread_cancel_event (struct thread_master *, void *); 221 extern void thread_main (struct thread_master *); 222 extern unsigned long thread_timer_remain_second (struct thread *); 223 extern struct timeval thread_timer_remain(struct thread*); 224 extern int thread_should_yield (struct thread *); 225 extern unsigned long timeval_elapsed (struct timeval a, struct timeval b); 226 227 /* Internal libzebra exports */ 228 extern void thread_getrusage (RUSAGE_T *); 229 extern struct cmd_element show_thread_cpu_cmd; 230 extern struct cmd_element clear_thread_cpu_cmd; 231 232 /* replacements for the system gettimeofday(), clock_gettime() and 233 * time() functions, providing support for non-decrementing clock on 234 * all systems, and fully monotonic on /some/ systems. 235 */ 236 extern int quagga_gettime (enum quagga_clkid, struct timeval *); 237 extern time_t quagga_time (time_t *); 238 239 /* Returns elapsed real (wall clock) time. */ 240 extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before, 241 unsigned long *cpu_time_elapsed); 242 243 /* Global variable containing a recent result from gettimeofday. This can 244 be used instead of calling gettimeofday if a recent value is sufficient. 245 This is guaranteed to be refreshed before a thread is called. */ 246 extern struct timeval recent_time; 247 /* Similar to recent_time, but a monotonically increasing time value */ 248 extern struct timeval recent_relative_time (void); 249 250 /* only for use in logging functions! */ 251 extern struct thread *thread_current; 252 253 #endif /* _ZEBRA_THREAD_H */ 254