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