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