blob: 6da752ce60f2aa813128f63c2d1d3f7f89586e59 [file] [log] [blame]
Willy Tarreaud13a9282018-11-25 18:36:15 +01001/*
2 * include/common/initcall.h
3 *
4 * Initcall management.
5 *
6 * Copyright (C) 2018 Willy Tarreau - w@1wt.eu
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29#ifndef _COMMON_INIT_H
30#define _COMMON_INIT_H
31
32/* List of known init stages. If others are added, please declare their
33 * section at the end of the file below.
34 */
Willy Tarreau7b5654f2019-03-29 21:30:17 +010035
36/* The principle of the initcalls is to create optional sections in the target
37 * program which are made of arrays of structures containing a function pointer
38 * and 3 argument pointers. Then at boot time, these sections are scanned in a
39 * well defined order to call in turn each of these functions with their
40 * arguments. This allows to declare register callbacks in C files without
41 * having to export lots of things nor to cross-reference functions. There are
42 * several initialization stages defined so that certain guarantees are offered
43 * (for example list heads might or might not be initialized, pools might or
44 * might not have been created yet).
45 *
46 * On some very old platforms there is no convenient way to retrieve the start
47 * or stop pointer for these sections so there is no reliable way to enumerate
48 * the callbacks. When this is the case, as detected when USE_OBSOLETE_LINKER
49 * is set, instead of using sections we exclusively use constructors whose name
50 * is based on the current line number in the file to guarantee uniqueness.
51 * When called, these constructors then add their callback to their respective
52 * list. It works as well but slightly inflates the executable's size since
53 * code has to be emitted just to register each of these callbacks.
54 */
55
Olivier Houchard9efa7b82019-02-13 16:22:17 +010056/*
57 * Please keep those names short enough, they are used to generate section
58 * names, Mac OS X accepts section names up to 16 characters, and we prefix
59 * them with i_, so stage name can't be more than 14 characters.
60 */
Willy Tarreaud13a9282018-11-25 18:36:15 +010061enum init_stage {
62 STG_PREPARE = 0, // preset variables, tables, list heads
63 STG_LOCK, // pre-initialize locks
64 STG_ALLOC, // allocate required structures
65 STG_POOL, // create pools
66 STG_REGISTER, // register static lists (keywords etc)
67 STG_INIT, // subsystems normal initialization
68 STG_SIZE // size of the stages array, must be last
69};
70
71/* This is the descriptor for an initcall */
72struct initcall {
73 void (*const fct)(void *arg1, void *arg2, void *arg3);
74 void *arg1;
75 void *arg2;
76 void *arg3;
Willy Tarreau7b5654f2019-03-29 21:30:17 +010077#if defined(USE_OBSOLETE_LINKER)
78 void *next;
79#endif
Willy Tarreaud13a9282018-11-25 18:36:15 +010080};
81
Willy Tarreau7b5654f2019-03-29 21:30:17 +010082
83#if !defined(USE_OBSOLETE_LINKER)
84
Olivier Houchard9efa7b82019-02-13 16:22:17 +010085#ifdef __APPLE__
86#define HA_SECTION(s) __section__("__DATA, i_" # s)
87#else
88#define HA_SECTION(s) __section__("init_" # s)
89#endif
90
Willy Tarreaud13a9282018-11-25 18:36:15 +010091/* Declare a static variable in the init section dedicated to stage <stg>,
92 * with an element referencing function <function> and arguments <a1..a3>.
93 * <linenum> is needed to deduplicate entries created from a same file. The
94 * trick with (stg<STG_SIZE) consists in verifying that stg if a valid enum
95 * value from the initcall set, and to emit a warning or error if it is not.
96 * The function's type is cast so that it is technically possible to call a
97 * function taking other argument types, provided they are all the same size
98 * as a pointer (args are cast to (void*)). Do not use this macro directly,
99 * use INITCALL{0..3}() instead.
100 */
Olivier Houchard526dc952019-04-10 16:21:32 +0200101#define __GLOBL1(sym) __asm__(".globl " #sym)
102#define __GLOBL(sym) __GLOBL1(sym)
Willy Tarreaud13a9282018-11-25 18:36:15 +0100103#define __DECLARE_INITCALL(stg, linenum, function, a1, a2, a3) \
Olivier Houchard526dc952019-04-10 16:21:32 +0200104 __GLOBL(__start_init_##stg ); \
105 __GLOBL(__stop_init_##stg ); \
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100106 static const struct initcall *__initcb_##linenum \
Olivier Houchard9efa7b82019-02-13 16:22:17 +0100107 __attribute__((__used__,HA_SECTION(stg))) = \
Willy Tarreaud13a9282018-11-25 18:36:15 +0100108 (stg < STG_SIZE) ? &(const struct initcall) { \
109 .fct = (void (*)(void *,void *,void *))function, \
110 .arg1 = (void *)(a1), \
111 .arg2 = (void *)(a2), \
112 .arg3 = (void *)(a3), \
113 } : NULL
114
Olivier Houchard526dc952019-04-10 16:21:32 +0200115
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100116#else // USE_OBSOLETE_LINKER
117
118/* Declare a static constructor function to register a static descriptor for
119 * stage <stg>, with an element referencing function <function> and arguments
120 * <a1..a3>. <linenum> is needed to deduplicate entries created from a same
121 * file. The trick with (stg<STG_SIZE) consists in verifying that stg if a
122 * valid enum value from the initcall set, and to emit a warning or error if
123 * it is not.
124 * The function's type is cast so that it is technically possible to call a
125 * function taking other argument types, provided they are all the same size
126 * as a pointer (args are cast to (void*)). Do not use this macro directly,
127 * use INITCALL{0..3}() instead.
128 */
129#define __DECLARE_INITCALL(stg, linenum, function, a1, a2, a3) \
130__attribute__((constructor)) static void __initcb_##linenum() \
131{ \
132 static struct initcall entry = { \
133 .fct = (void (*)(void *,void *,void *))function, \
134 .arg1 = (void *)(a1), \
135 .arg2 = (void *)(a2), \
136 .arg3 = (void *)(a3), \
137 }; \
138 if (stg < STG_SIZE) { \
139 entry.next = __initstg[stg]; \
140 __initstg[stg] = &entry; \
141 }; \
142}
143
144#endif // USE_OBSOLETE_LINKER
145
Willy Tarreaud13a9282018-11-25 18:36:15 +0100146/* This is used to resolve <linenum> to an integer before calling
147 * __DECLARE_INITCALL(). Do not use this macro directly, use INITCALL{0..3}()
148 * instead.
149 */
150#define _DECLARE_INITCALL(...) \
151 __DECLARE_INITCALL(__VA_ARGS__)
152
153/* This requires that function <function> is called with pointer argument
154 * <argument> during init stage <stage> which must be one of init_stage.
155 */
156#define INITCALL0(stage, function) \
157 _DECLARE_INITCALL(stage, __LINE__, function, 0, 0, 0)
158
159/* This requires that function <function> is called with pointer argument
160 * <argument> during init stage <stage> which must be one of init_stage.
161 */
162#define INITCALL1(stage, function, arg1) \
163 _DECLARE_INITCALL(stage, __LINE__, function, arg1, 0, 0)
164
165/* This requires that function <function> is called with pointer arguments
166 * <arg1..2> during init stage <stage> which must be one of init_stage.
167 */
168#define INITCALL2(stage, function, arg1, arg2) \
169 _DECLARE_INITCALL(stage, __LINE__, function, arg1, arg2, 0)
170
171/* This requires that function <function> is called with pointer arguments
172 * <arg1..3> during init stage <stage> which must be one of init_stage.
173 */
174#define INITCALL3(stage, function, arg1, arg2, arg3) \
175 _DECLARE_INITCALL(stage, __LINE__, function, arg1, arg2, arg3)
176
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100177#if !defined(USE_OBSOLETE_LINKER)
Willy Tarreaud13a9282018-11-25 18:36:15 +0100178/* Iterate pointer p (of type initcall**) over all registered calls at
179 * stage <stg>.
180 */
181#define FOREACH_INITCALL(p,stg) \
182 for ((p) = &(__start_init_##stg); (p) < &(__stop_init_##stg); (p)++)
183
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100184#else // USE_OBSOLETE_LINKER
185
186#define FOREACH_INITCALL(p,stg) \
187 for ((p) = __initstg[stg]; (p); (p) = (p)->next)
188#endif // USE_OBSOLETE_LINKER
189
190
191#if !defined(USE_OBSOLETE_LINKER)
Willy Tarreaud13a9282018-11-25 18:36:15 +0100192/* Declare a section for stage <stg>. The start and stop pointers are set by
193 * the linker itself, which is why they're declared extern here. The weak
194 * attribute is used so that we declare them ourselves if the section is
195 * empty. The corresponding sections must contain exclusively pointers to
196 * make sure each location may safely be visited by incrementing a pointer.
197 */
Olivier Houchard9efa7b82019-02-13 16:22:17 +0100198#ifdef __APPLE__
199#define DECLARE_INIT_SECTION(stg) \
200 extern __attribute__((__weak__)) const struct initcall *__start_init_##stg __asm("section$start$__DATA$i_" # stg); \
201 extern __attribute__((__weak__)) const struct initcall *__stop_init_##stg __asm("section$end$__DATA$i_" # stg)
202
203#else
Willy Tarreaud13a9282018-11-25 18:36:15 +0100204#define DECLARE_INIT_SECTION(stg) \
205 extern __attribute__((__weak__)) const struct initcall *__start_init_##stg; \
206 extern __attribute__((__weak__)) const struct initcall *__stop_init_##stg
Olivier Houchard9efa7b82019-02-13 16:22:17 +0100207#endif
Willy Tarreaud13a9282018-11-25 18:36:15 +0100208
209/* Declare all initcall sections here */
210DECLARE_INIT_SECTION(STG_PREPARE);
211DECLARE_INIT_SECTION(STG_LOCK);
212DECLARE_INIT_SECTION(STG_ALLOC);
213DECLARE_INIT_SECTION(STG_POOL);
214DECLARE_INIT_SECTION(STG_REGISTER);
215DECLARE_INIT_SECTION(STG_INIT);
216
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100217// for use in the main haproxy.c file
218#define DECLARE_INIT_STAGES asm("")
219
Willy Tarreaud13a9282018-11-25 18:36:15 +0100220/* not needed anymore */
221#undef DECLARE_INIT_SECTION
222
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100223#else // USE_OBSOLETE_LINKER
224
225extern struct initcall *__initstg[STG_SIZE];
226
227// for use in the main haproxy.c file
228#define DECLARE_INIT_STAGES struct initcall *__initstg[STG_SIZE]
229
230#endif // USE_OBSOLETE_LINKER
231
232#if !defined(USE_OBSOLETE_LINKER)
Willy Tarreaud13a9282018-11-25 18:36:15 +0100233/* Run the initcalls for stage <stg>. The test on <stg> is only there to
234 * ensure it is a valid initcall stage.
235 */
236#define RUN_INITCALLS(stg) \
237 do { \
238 const struct initcall **ptr; \
239 if (stg >= STG_SIZE) \
240 break; \
241 FOREACH_INITCALL(ptr, stg) \
242 (*ptr)->fct((*ptr)->arg1, (*ptr)->arg2, (*ptr)->arg3); \
243 } while (0)
244
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100245#else // USE_OBSOLETE_LINKER
246
247/* Run the initcalls for stage <stg>. The test on <stg> is only there to
248 * ensure it is a valid initcall stage.
249 */
250#define RUN_INITCALLS(stg) \
251 do { \
252 const struct initcall *ptr; \
253 if (stg >= STG_SIZE) \
254 break; \
255 FOREACH_INITCALL(ptr, stg) \
256 (ptr)->fct((ptr)->arg1, (ptr)->arg2, (ptr)->arg3); \
257 } while (0)
258
259#endif // USE_OBSOLETE_LINKER
260
Willy Tarreaud13a9282018-11-25 18:36:15 +0100261#endif /* _COMMON_INIT_H */
262
263/*
264 * Local variables:
265 * c-indent-level: 8
266 * c-basic-offset: 8
267 * End:
268 */