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 _THREAD_H_
23 #define _THREAD_H_
24 
25 struct rusage_t
26 {
27   struct timeval real;
28 };
29 #define RUSAGE_T        struct rusage_t
30 
31 #define GETRUSAGE(X) thread_getrusage(X)
32 
33 /* Linked list of thread. */
34 struct thread_list
35 {
36   struct thread *head;
37   struct thread *tail;
38   int count;
39 };
40 
41 /* Master of the theads. */
42 struct thread_master
43 {
44   struct thread_list read;
45   struct thread_list write;
46   struct thread_list timer;
47   struct thread_list event;
48   struct thread_list ready;
49   struct thread_list unuse;
50   struct thread_list background;
51   fd_set readfd;
52   fd_set writefd;
53   fd_set exceptfd;
54   unsigned long alloc;
55 };
56 
57 typedef unsigned char thread_type;
58 
59 /* Thread itself. */
60 struct thread
61 {
62   thread_type type;		/* thread type */
63   thread_type add_type;		/* thread type */
64   struct thread *next;		/* next pointer of the thread */
65   struct thread *prev;		/* previous pointer of the thread */
66   struct thread_master *master;	/* pointer to the struct thread_master. */
67   int (*func) (struct thread *); /* event function */
68   void *arg;			/* event argument */
69   union {
70     int val;			/* second argument of the event. */
71     int fd;			/* file descriptor in case of read/write. */
72     struct timeval sands;	/* rest of time sands value. */
73   } u;
74   RUSAGE_T ru;			/* Indepth usage info.  */
75   struct cpu_thread_history *hist; /* cache pointer to cpu_history */
76   char* funcname;
77 };
78 
79 struct cpu_thread_history
80 {
81   int (*func)(struct thread *);
82   char *funcname;
83   unsigned int total_calls;
84   struct time_stats
85   {
86     unsigned long total, max;
87   } real;
88   thread_type types;
89 };
90 
91 /* Clocks supported by Quagga */
92 enum quagga_clkid {
93   QUAGGA_CLK_REALTIME = 0,	/* ala gettimeofday() */
94   QUAGGA_CLK_MONOTONIC,		/* monotonic, against an indeterminate base */
95   QUAGGA_CLK_REALTIME_STABILISED, /* like realtime, but non-decrementing */
96 };
97 
98 /* Thread types. */
99 #define THREAD_READ           0
100 #define THREAD_WRITE          1
101 #define THREAD_TIMER          2
102 #define THREAD_EVENT          3
103 #define THREAD_READY          4
104 #define THREAD_BACKGROUND     5
105 #define THREAD_UNUSED         6
106 #define THREAD_EXECUTE        7
107 
108 /* Thread yield time.  */
109 #define THREAD_YIELD_TIME_SLOT     10 * 1000L /* 10ms */
110 
111 /* Macros. */
112 #define THREAD_ARG(X) ((X)->arg)
113 #define THREAD_FD(X)  ((X)->u.fd)
114 #define THREAD_VAL(X) ((X)->u.val)
115 
116 #define THREAD_READ_ON(master,thread,func,arg,sock) \
117   do { \
118     if (! thread) \
119       thread = thread_add_read (master, func, arg, sock); \
120   } while (0)
121 
122 #define THREAD_WRITE_ON(master,thread,func,arg,sock) \
123   do { \
124     if (! thread) \
125       thread = thread_add_write (master, func, arg, sock); \
126   } while (0)
127 
128 #define THREAD_TIMER_ON(master,thread,func,arg,time) \
129   do { \
130     if (! thread) \
131       thread = thread_add_timer (master, func, arg, time); \
132   } while (0)
133 
134 #define THREAD_OFF(thread) \
135   do { \
136     if (thread) \
137       { \
138         thread_cancel (thread); \
139         thread = NULL; \
140       } \
141   } while (0)
142 
143 #define THREAD_READ_OFF(thread)  THREAD_OFF(thread)
144 #define THREAD_WRITE_OFF(thread)  THREAD_OFF(thread)
145 #define THREAD_TIMER_OFF(thread)  THREAD_OFF(thread)
146 
147 #define thread_add_read(m,f,a,v) funcname_thread_add_read(m,f,a,v,#f)
148 #define thread_add_write(m,f,a,v) funcname_thread_add_write(m,f,a,v,#f)
149 #define thread_add_timer(m,f,a,v) funcname_thread_add_timer(m,f,a,v,#f)
150 #define thread_add_timer_msec(m,f,a,v) funcname_thread_add_timer_msec(m,f,a,v,#f)
151 #define thread_add_event(m,f,a,v) funcname_thread_add_event(m,f,a,v,#f)
152 #define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f)
153 
154 /* The 4th arg to thread_add_background is the # of milliseconds to delay. */
155 #define thread_add_background(m,f,a,v) funcname_thread_add_background(m,f,a,v,#f)
156 
157 /* Prototypes. */
158 extern struct thread_master *thread_master_create (void);
159 extern void thread_master_free (struct thread_master *);
160 extern struct thread *funcname_thread_add_read (struct thread_master *, int (*)(struct thread *), void *, int, const char *);
161 extern struct thread *funcname_thread_add_write (struct thread_master *, int (*)(struct thread *), void *, int, const char *);
162 extern struct thread *funcname_thread_add_timer (struct thread_master *, int (*)(struct thread *), void *, long, const char *);
163 extern struct thread *funcname_thread_add_timer_msec (struct thread_master *, int (*)(struct thread *), void *, long, const char *);
164 extern struct thread *funcname_thread_add_event (struct thread_master *, int (*)(struct thread *), void *, int, const char *);
165 extern struct thread *funcname_thread_add_background (struct thread_master *, int (*func)(struct thread *), void *arg, long, const char *);
166 extern struct thread *funcname_thread_execute (struct thread_master *, int (*)(struct thread *), void *, int, const char *);
167 extern void thread_cancel (struct thread *);
168 extern unsigned int thread_cancel_event (struct thread_master *, void *);
169 extern struct thread *thread_fetch (struct thread_master *, struct thread *);
170 extern void thread_call (struct thread *);
171 extern unsigned long thread_timer_remain_second (struct thread *);
172 extern int thread_should_yield (struct thread *);
173 extern void thread_getrusage (RUSAGE_T *);
174 extern int quagga_gettime (enum quagga_clkid, struct timeval *);
175 extern time_t quagga_time (time_t *);
176 extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before, unsigned long *cpu_time_elapsed);
177 
178 /* Global variable containing a recent result from gettimeofday.  This can
179    be used instead of calling gettimeofday if a recent value is sufficient.
180    This is guaranteed to be refreshed before a thread is called. */
181 extern struct timeval recent_time;
182 /* Similar to recent_time, but a monotonically increasing time value */
183 extern struct timeval recent_relative_time (void);
184 
185 #endif /* _THREAD_H_ */
186