forked from acassen/keepalived
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscheduler.h
305 lines (272 loc) · 9.2 KB
/
scheduler.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
/*
* Soft: Keepalived is a failover program for the LVS project
* <www.linuxvirtualserver.org>. It monitor & manipulate
* a loadbalanced server pool using multi-layer checks.
*
* Part: scheduler.c include file.
*
* Author: Alexandre Cassen, <[email protected]>
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Copyright (C) 2001-2017 Alexandre Cassen, <[email protected]>
*/
#ifndef _SCHEDULER_H
#define _SCHEDULER_H
/* system includes */
#include <sys/types.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/timerfd.h>
#ifdef _WITH_SNMP_
#include <sys/select.h>
#endif
#ifdef THREAD_DUMP
#include <stdio.h>
#endif
#include "timer.h"
#include "list_head.h"
#include "rbtree_ka.h"
/* Thread types. */
typedef enum {
THREAD_READ, /* thread_master.read rb tree */
THREAD_WRITE, /* thread_master.write rb tree */
THREAD_TIMER, /* thread_master.timer rb tree */
THREAD_TIMER_SHUTDOWN, /* thread_master.timer rb tree */
THREAD_CHILD, /* thread_master.child rb tree */
#define THREAD_MAX_WAITING THREAD_CHILD
THREAD_UNUSED, /* thread_master.unuse list_head */
/* The following are all on the thread_master.e_list list_head */
THREAD_READY,
THREAD_EVENT,
THREAD_WRITE_TIMEOUT,
THREAD_READ_TIMEOUT,
THREAD_CHILD_TIMEOUT,
THREAD_CHILD_TERMINATED,
THREAD_TERMINATE_START,
THREAD_TERMINATE,
THREAD_READY_TIMER,
THREAD_READY_READ_FD,
THREAD_READY_WRITE_FD,
THREAD_READ_ERROR,
THREAD_WRITE_ERROR,
#ifdef USE_SIGNAL_THREADS
THREAD_SIGNAL,
#endif
} thread_type_t;
/* Thread Event flags */
enum thread_flags {
THREAD_FL_READ_BIT, /* Want read set */
THREAD_FL_WRITE_BIT, /* Want write set */
THREAD_FL_EPOLL_BIT, /* fd is registered with epoll */
THREAD_FL_EPOLL_READ_BIT, /* read is registered */
THREAD_FL_EPOLL_WRITE_BIT, /* write is registered */
};
/* epoll def */
#define THREAD_EPOLL_REALLOC_THRESH 64
/* Thread flags for thread destruction */
#define THREAD_DESTROY_CLOSE_FD 0x01
#define THREAD_DESTROY_FREE_ARG 0x02
typedef struct _thread thread_t;
typedef const thread_t * thread_ref_t;
typedef void (*thread_func_t)(thread_ref_t);
typedef union {
int val;
unsigned uval;
struct {
int fd; /* file descriptor in case of read/write. */
unsigned flags;
} f;
struct {
pid_t pid; /* process id a child thread is wanting. */
int status; /* return status of the process */
} c;
} thread_arg2;
/* Thread itself. */
struct _thread {
unsigned long id;
thread_type_t type; /* thread type */
struct _thread_master *master; /* pointer to the struct thread_master. */
thread_func_t func; /* event function */
void *arg; /* event argument */
timeval_t sands; /* rest of time sands value. */
thread_arg2 u; /* second argument of the event. */
struct _thread_event *event; /* Thread Event back-pointer */
union {
rb_node_t n;
list_head_t e_list;
};
rb_node_t rb_data; /* PID or fd/vrid */
};
/* Thread Event */
typedef struct _thread_event {
thread_t *read;
thread_t *write;
unsigned long flags;
int fd;
rb_node_t n;
} thread_event_t;
/* Master of the threads. */
typedef struct _thread_master {
rb_root_cached_t read;
rb_root_cached_t write;
rb_root_cached_t timer;
rb_root_cached_t child;
list_head_t event;
#ifdef USE_SIGNAL_THREADS
list_head_t signal;
#endif
list_head_t ready;
list_head_t unuse;
thread_t *current_thread;
/* child process related */
rb_root_t child_pid;
/* epoll related */
rb_root_t io_events;
struct epoll_event *epoll_events;
thread_event_t *current_event;
unsigned int epoll_size;
unsigned int epoll_count;
int epoll_fd;
/* timer related */
int timer_fd;
thread_ref_t timer_thread;
/* signal related */
int signal_fd;
#ifdef _WITH_SNMP_
/* snmp related */
thread_ref_t snmp_timer_thread;
int snmp_fdsetsize;
fd_set snmp_fdset;
#endif
/* Local data */
unsigned long alloc;
unsigned long id;
bool shutdown_timer_running;
} thread_master_t;
#ifndef _ONE_PROCESS_DEBUG_
typedef enum {
PROG_TYPE_PARENT,
#ifdef _WITH_VRRP_
PROG_TYPE_VRRP,
#endif
#ifdef _WITH_LVS_
PROG_TYPE_CHECKER,
#endif
#ifdef _WITH_BFD_
PROG_TYPE_BFD,
#endif
} prog_type_t;
#endif
/* MICRO SEC def */
#define BOOTSTRAP_DELAY TIMER_HZ
/* Macros. */
#define THREAD_ARG(X) ((X)->arg)
#define THREAD_VAL(X) ((X)->u.val)
#define THREAD_CHILD_PID(X) ((X)->u.c.pid)
#define THREAD_CHILD_STATUS(X) ((X)->u.c.status)
/* Exit codes. The values comply with the LSB so far as possible,
* and are also documented in the systemd.exec(5) man page. */
enum exit_code {
KEEPALIVED_EXIT_OK = EXIT_SUCCESS,
KEEPALIVED_EXIT_NO_MEMORY = 204, /* EXIT_MEMORY */
KEEPALIVED_EXIT_PROGRAM_ERROR = 70, /* EX_SOFTWARE */
KEEPALIVED_EXIT_FATAL = 1, /* EXIT_FAILURE */
KEEPALIVED_EXIT_CONFIG = 2, /* EXIT_INVALIDARGUMENT */
KEEPALIVED_EXIT_NO_CONFIG = 6, /* EXIT_NOTCONFIGURED */
KEEPALIVED_EXIT_MISSING_PERMISSION = 4, /* EXIT_NOPERMISSION */
} ;
enum chk_exit_code {
KEEPALIVED_CHK_EXIT_OK = EXIT_SUCCESS,
KEEPALIVED_CHK_EXIT_CONFIG = 4, /* Maintain backward compatibility */
KEEPALIVED_CHK_EXIT_CONFIG_TEST,
KEEPALIVED_CHK_EXIT_CONFIG_TEST_SECURITY,
} ;
#define DEFAULT_CHILD_FINDER ((void *)1)
/* global vars exported */
extern thread_master_t *master;
#ifndef _ONE_PROCESS_DEBUG_
extern prog_type_t prog_type; /* Parent/VRRP/Checker process */
#endif
#ifdef _WITH_SNMP_
extern bool snmp_running;
#endif
#ifdef _EPOLL_DEBUG_
extern bool do_epoll_debug;
#endif
#ifdef _EPOLL_THREAD_DUMP_
extern bool do_epoll_thread_dump;
#endif
#ifdef _SCRIPT_DEBUG_
extern bool do_script_debug;
#endif
extern const char *config_opts;
/* Prototypes. */
extern void set_child_finder_name(char const * (*)(pid_t));
extern void save_cmd_line_options(int, char * const *);
extern char * const * get_cmd_line_options(int *);
extern void log_command_line(unsigned);
#ifndef _ONE_PROCESS_DEBUG_
extern unsigned calc_restart_delay(const timeval_t *, unsigned *, const char *);
extern void log_child_died(const char *, pid_t);
extern int report_child_status(int, pid_t, const char *);
#endif
extern thread_master_t *thread_make_master(void);
extern thread_ref_t thread_add_terminate_event(thread_master_t *);
extern thread_ref_t thread_add_parent_terminate_event(thread_master_t *, int);
extern thread_ref_t thread_add_start_terminate_event(thread_master_t *, thread_func_t);
#ifdef THREAD_DUMP
extern void dump_thread_data(const thread_master_t *, FILE *);
#endif
extern void thread_cleanup_master(thread_master_t *, bool);
extern void thread_destroy_master(thread_master_t *);
extern thread_ref_t thread_add_read_sands(thread_master_t *, thread_func_t, void *, int, const timeval_t *, unsigned);
extern thread_ref_t thread_add_read(thread_master_t *, thread_func_t, void *, int, unsigned long, unsigned);
extern void thread_del_read(thread_ref_t);
extern void thread_requeue_read(thread_master_t *, int, const timeval_t *);
extern thread_ref_t thread_add_write(thread_master_t *, thread_func_t, void *, int, unsigned long, unsigned);
extern void thread_del_write(thread_ref_t);
extern void thread_close_fd(thread_ref_t);
extern thread_ref_t thread_add_timer_uval(thread_master_t *, thread_func_t, void *, unsigned, unsigned long);
extern thread_ref_t thread_add_timer(thread_master_t *, thread_func_t, void *, unsigned long);
extern thread_ref_t thread_add_timer_sands(thread_master_t *, thread_func_t, void *, const timeval_t *);
extern void thread_update_arg2(thread_ref_t, const thread_arg2 *);
extern void timer_thread_update_timeout(thread_ref_t, unsigned long);
extern thread_ref_t thread_add_timer_shutdown(thread_master_t *, thread_func_t, void *, unsigned long);
extern thread_ref_t thread_add_child(thread_master_t *, thread_func_t, void *, pid_t, unsigned long);
extern void thread_children_reschedule(thread_master_t *, thread_func_t, unsigned long);
extern thread_ref_t thread_add_event(thread_master_t *, thread_func_t, void *, int);
extern void thread_cancel(thread_ref_t);
extern void thread_cancel_read(thread_master_t *, int);
#ifdef _WITH_SNMP_
extern void snmp_timeout_thread(thread_ref_t);
extern void snmp_epoll_info(thread_master_t *);
extern void snmp_epoll_clear(thread_master_t *);
#endif
extern int process_threads(thread_master_t *);
extern void thread_child_handler(void *, int);
extern void thread_add_base_threads(thread_master_t *, bool);
extern int launch_thread_scheduler(thread_master_t *);
#ifndef _ONE_PROCESS_DEBUG_
extern void register_shutdown_function(void (*)(int));
#endif
extern void register_thread_timeout_handler(void (*)(unsigned), unsigned);
#ifdef THREAD_DUMP
extern const char *get_signal_function_name(void (*)(void *, int));
extern void register_signal_handler_address(const char *, void (*)(void *, int));
extern void register_thread_address(const char *, thread_func_t);
extern void deregister_thread_addresses(void);
extern void register_scheduler_addresses(void);
#endif
#ifdef _VRRP_FD_DEBUG_
extern void set_extra_threads_debug(void (*)(void));
#endif
#endif