]> git.proxmox.com Git - mirror_frr.git/blob - lib/thread.h
*: reindent
[mirror_frr.git] / lib / thread.h
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 #include "monotime.h"
27
28 struct rusage_t {
29 struct rusage cpu;
30 struct timeval real;
31 };
32 #define RUSAGE_T struct rusage_t
33
34 #define GETRUSAGE(X) thread_getrusage(X)
35
36 /* Linked list of thread. */
37 struct thread_list {
38 struct thread *head;
39 struct thread *tail;
40 int count;
41 };
42
43 struct pqueue;
44
45 /*
46 * Abstract it so we can use different methodologies to
47 * select on data.
48 */
49 typedef fd_set thread_fd_set;
50
51 #if defined(HAVE_POLL_CALL)
52 #include <poll.h>
53 struct fd_handler {
54 /* number of pfd stored in pfds */
55 nfds_t pfdcount;
56 /* number of pfd stored in pfds + number of snmp pfd */
57 nfds_t pfdcountsnmp;
58 /* number of pfd that fit in the allocated space of pfds */
59 nfds_t pfdsize;
60 struct pollfd *pfds;
61 };
62 #else
63 struct fd_handler {
64 fd_set readfd;
65 fd_set writefd;
66 fd_set exceptfd;
67 };
68 #endif
69
70 /* Master of the theads. */
71 struct thread_master {
72 struct thread **read;
73 struct thread **write;
74 struct pqueue *timer;
75 struct thread_list event;
76 struct thread_list ready;
77 struct thread_list unuse;
78 struct pqueue *background;
79 int fd_limit;
80 struct fd_handler handler;
81 unsigned long alloc;
82 };
83
84 typedef unsigned char thread_type;
85
86 /* Thread itself. */
87 struct thread {
88 thread_type type; /* thread type */
89 thread_type add_type; /* thread type */
90 struct thread *next; /* next pointer of the thread */
91 struct thread *prev; /* previous pointer of the thread */
92 struct thread_master *master; /* pointer to the struct thread_master. */
93 int (*func)(struct thread *); /* event function */
94 void *arg; /* event argument */
95 union {
96 int val; /* second argument of the event. */
97 int fd; /* file descriptor in case of read/write. */
98 struct timeval sands; /* rest of time sands value. */
99 } u;
100 int index; /* used for timers to store position in queue */
101 struct timeval real;
102 struct cpu_thread_history *hist; /* cache pointer to cpu_history */
103 unsigned long yield; /* yield time in us */
104 const char *funcname;
105 const char *schedfrom;
106 int schedfrom_line;
107 };
108
109 struct cpu_thread_history {
110 int (*func)(struct thread *);
111 unsigned int total_calls;
112 unsigned int total_active;
113 struct time_stats {
114 unsigned long total, max;
115 } real;
116 struct time_stats cpu;
117 thread_type types;
118 const char *funcname;
119 };
120
121 /* Struct timeval's tv_usec one second value. */
122 #define TIMER_SECOND_MICRO 1000000L
123
124 /* Thread types. */
125 #define THREAD_READ 0
126 #define THREAD_WRITE 1
127 #define THREAD_TIMER 2
128 #define THREAD_EVENT 3
129 #define THREAD_READY 4
130 #define THREAD_BACKGROUND 5
131 #define THREAD_UNUSED 6
132 #define THREAD_EXECUTE 7
133
134 /* Thread yield time. */
135 #define THREAD_YIELD_TIME_SLOT 10 * 1000L /* 10ms */
136
137 /* Macros. */
138 #define THREAD_ARG(X) ((X)->arg)
139 #define THREAD_FD(X) ((X)->u.fd)
140 #define THREAD_VAL(X) ((X)->u.val)
141
142 #define THREAD_READ_ON(master, thread, func, arg, sock) \
143 do { \
144 if (!thread) \
145 thread = thread_add_read(master, func, arg, sock); \
146 } while (0)
147
148 #define THREAD_WRITE_ON(master, thread, func, arg, sock) \
149 do { \
150 if (!thread) \
151 thread = thread_add_write(master, func, arg, sock); \
152 } while (0)
153
154 #define THREAD_TIMER_ON(master, thread, func, arg, time) \
155 do { \
156 if (!thread) \
157 thread = thread_add_timer(master, func, arg, time); \
158 } while (0)
159
160 #define THREAD_TIMER_MSEC_ON(master, thread, func, arg, time) \
161 do { \
162 if (!thread) \
163 thread = thread_add_timer_msec(master, func, arg, \
164 time); \
165 } while (0)
166
167 #define THREAD_OFF(thread) \
168 do { \
169 if (thread) { \
170 thread_cancel(thread); \
171 thread = NULL; \
172 } \
173 } while (0)
174
175 #define THREAD_READ_OFF(thread) THREAD_OFF(thread)
176 #define THREAD_WRITE_OFF(thread) THREAD_OFF(thread)
177 #define THREAD_TIMER_OFF(thread) THREAD_OFF(thread)
178
179 #define debugargdef const char *funcname, const char *schedfrom, int fromln
180
181 #define thread_add_read(m,f,a,v) funcname_thread_add_read_write(THREAD_READ,m,f,a,v,#f,__FILE__,__LINE__)
182 #define thread_add_write(m,f,a,v) funcname_thread_add_read_write(THREAD_WRITE,m,f,a,v,#f,__FILE__,__LINE__)
183 #define thread_add_timer(m,f,a,v) funcname_thread_add_timer(m,f,a,v,#f,__FILE__,__LINE__)
184 #define thread_add_timer_msec(m,f,a,v) funcname_thread_add_timer_msec(m,f,a,v,#f,__FILE__,__LINE__)
185 #define thread_add_timer_tv(m,f,a,v) funcname_thread_add_timer_tv(m,f,a,v,#f,__FILE__,__LINE__)
186 #define thread_add_event(m,f,a,v) funcname_thread_add_event(m,f,a,v,#f,__FILE__,__LINE__)
187 #define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__)
188
189 /* The 4th arg to thread_add_background is the # of milliseconds to delay. */
190 #define thread_add_background(m,f,a,v) funcname_thread_add_background(m,f,a,v,#f,__FILE__,__LINE__)
191
192 /* Prototypes. */
193 extern struct thread_master *thread_master_create(void);
194 extern void thread_master_free(struct thread_master *);
195 extern void thread_master_free_unused(struct thread_master *);
196
197 extern struct thread *funcname_thread_add_read_write(int dir,
198 struct thread_master *,
199 int (*)(struct thread *),
200 void *, int, debugargdef);
201 extern struct thread *funcname_thread_add_timer(struct thread_master *,
202 int (*)(struct thread *),
203 void *, long, debugargdef);
204 extern struct thread *funcname_thread_add_timer_msec(struct thread_master *,
205 int (*)(struct thread *),
206 void *, long, debugargdef);
207 extern struct thread *funcname_thread_add_timer_tv(struct thread_master *,
208 int (*)(struct thread *),
209 void *, struct timeval *,
210 debugargdef);
211 extern struct thread *funcname_thread_add_event(struct thread_master *,
212 int (*)(struct thread *),
213 void *, int, debugargdef);
214 extern struct thread *
215 funcname_thread_add_background(struct thread_master *,
216 int (*func)(struct thread *), void *arg,
217 long milliseconds_to_delay, debugargdef);
218 extern struct thread *funcname_thread_execute(struct thread_master *,
219 int (*)(struct thread *), void *,
220 int, debugargdef);
221 #undef debugargdef
222
223 extern void thread_cancel(struct thread *);
224 extern unsigned int thread_cancel_event(struct thread_master *, void *);
225 extern struct thread *thread_fetch(struct thread_master *, struct thread *);
226 extern void thread_call(struct thread *);
227 extern unsigned long thread_timer_remain_second(struct thread *);
228 extern struct timeval thread_timer_remain(struct thread *);
229 extern int thread_should_yield(struct thread *);
230 /* set yield time for thread */
231 extern void thread_set_yield_time(struct thread *, unsigned long);
232
233 /* Internal libfrr exports */
234 extern void thread_getrusage(RUSAGE_T *);
235 extern void thread_cmd_init(void);
236
237 /* Returns elapsed real (wall clock) time. */
238 extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before,
239 unsigned long *cpu_time_elapsed);
240
241 /* only for use in logging functions! */
242 extern struct thread *thread_current;
243
244 #endif /* _ZEBRA_THREAD_H */