blob: 9e7059262dae01ef7ecb13a80b874306026affe7 [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 */
Olivier Houchard9efa7b82019-02-13 16:22:17 +010035/*
36 * Please keep those names short enough, they are used to generate section
37 * names, Mac OS X accepts section names up to 16 characters, and we prefix
38 * them with i_, so stage name can't be more than 14 characters.
39 */
Willy Tarreaud13a9282018-11-25 18:36:15 +010040enum init_stage {
41 STG_PREPARE = 0, // preset variables, tables, list heads
42 STG_LOCK, // pre-initialize locks
43 STG_ALLOC, // allocate required structures
44 STG_POOL, // create pools
45 STG_REGISTER, // register static lists (keywords etc)
46 STG_INIT, // subsystems normal initialization
47 STG_SIZE // size of the stages array, must be last
48};
49
50/* This is the descriptor for an initcall */
51struct initcall {
52 void (*const fct)(void *arg1, void *arg2, void *arg3);
53 void *arg1;
54 void *arg2;
55 void *arg3;
56};
57
Olivier Houchard9efa7b82019-02-13 16:22:17 +010058#ifdef __APPLE__
59#define HA_SECTION(s) __section__("__DATA, i_" # s)
60#else
61#define HA_SECTION(s) __section__("init_" # s)
62#endif
63
Willy Tarreaud13a9282018-11-25 18:36:15 +010064/* Declare a static variable in the init section dedicated to stage <stg>,
65 * with an element referencing function <function> and arguments <a1..a3>.
66 * <linenum> is needed to deduplicate entries created from a same file. The
67 * trick with (stg<STG_SIZE) consists in verifying that stg if a valid enum
68 * value from the initcall set, and to emit a warning or error if it is not.
69 * The function's type is cast so that it is technically possible to call a
70 * function taking other argument types, provided they are all the same size
71 * as a pointer (args are cast to (void*)). Do not use this macro directly,
72 * use INITCALL{0..3}() instead.
73 */
74#define __DECLARE_INITCALL(stg, linenum, function, a1, a2, a3) \
75 static const struct initcall *__initcb_##linenum \
Olivier Houchard9efa7b82019-02-13 16:22:17 +010076 __attribute__((__used__,HA_SECTION(stg))) = \
Willy Tarreaud13a9282018-11-25 18:36:15 +010077 (stg < STG_SIZE) ? &(const struct initcall) { \
78 .fct = (void (*)(void *,void *,void *))function, \
79 .arg1 = (void *)(a1), \
80 .arg2 = (void *)(a2), \
81 .arg3 = (void *)(a3), \
82 } : NULL
83
84/* This is used to resolve <linenum> to an integer before calling
85 * __DECLARE_INITCALL(). Do not use this macro directly, use INITCALL{0..3}()
86 * instead.
87 */
88#define _DECLARE_INITCALL(...) \
89 __DECLARE_INITCALL(__VA_ARGS__)
90
91/* This requires that function <function> is called with pointer argument
92 * <argument> during init stage <stage> which must be one of init_stage.
93 */
94#define INITCALL0(stage, function) \
95 _DECLARE_INITCALL(stage, __LINE__, function, 0, 0, 0)
96
97/* This requires that function <function> is called with pointer argument
98 * <argument> during init stage <stage> which must be one of init_stage.
99 */
100#define INITCALL1(stage, function, arg1) \
101 _DECLARE_INITCALL(stage, __LINE__, function, arg1, 0, 0)
102
103/* This requires that function <function> is called with pointer arguments
104 * <arg1..2> during init stage <stage> which must be one of init_stage.
105 */
106#define INITCALL2(stage, function, arg1, arg2) \
107 _DECLARE_INITCALL(stage, __LINE__, function, arg1, arg2, 0)
108
109/* This requires that function <function> is called with pointer arguments
110 * <arg1..3> during init stage <stage> which must be one of init_stage.
111 */
112#define INITCALL3(stage, function, arg1, arg2, arg3) \
113 _DECLARE_INITCALL(stage, __LINE__, function, arg1, arg2, arg3)
114
115/* Iterate pointer p (of type initcall**) over all registered calls at
116 * stage <stg>.
117 */
118#define FOREACH_INITCALL(p,stg) \
119 for ((p) = &(__start_init_##stg); (p) < &(__stop_init_##stg); (p)++)
120
121/* Declare a section for stage <stg>. The start and stop pointers are set by
122 * the linker itself, which is why they're declared extern here. The weak
123 * attribute is used so that we declare them ourselves if the section is
124 * empty. The corresponding sections must contain exclusively pointers to
125 * make sure each location may safely be visited by incrementing a pointer.
126 */
Olivier Houchard9efa7b82019-02-13 16:22:17 +0100127#ifdef __APPLE__
128#define DECLARE_INIT_SECTION(stg) \
129 extern __attribute__((__weak__)) const struct initcall *__start_init_##stg __asm("section$start$__DATA$i_" # stg); \
130 extern __attribute__((__weak__)) const struct initcall *__stop_init_##stg __asm("section$end$__DATA$i_" # stg)
131
132#else
Willy Tarreaud13a9282018-11-25 18:36:15 +0100133#define DECLARE_INIT_SECTION(stg) \
134 extern __attribute__((__weak__)) const struct initcall *__start_init_##stg; \
135 extern __attribute__((__weak__)) const struct initcall *__stop_init_##stg
Olivier Houchard9efa7b82019-02-13 16:22:17 +0100136#endif
Willy Tarreaud13a9282018-11-25 18:36:15 +0100137
138/* Declare all initcall sections here */
139DECLARE_INIT_SECTION(STG_PREPARE);
140DECLARE_INIT_SECTION(STG_LOCK);
141DECLARE_INIT_SECTION(STG_ALLOC);
142DECLARE_INIT_SECTION(STG_POOL);
143DECLARE_INIT_SECTION(STG_REGISTER);
144DECLARE_INIT_SECTION(STG_INIT);
145
146/* not needed anymore */
147#undef DECLARE_INIT_SECTION
148
149/* Run the initcalls for stage <stg>. The test on <stg> is only there to
150 * ensure it is a valid initcall stage.
151 */
152#define RUN_INITCALLS(stg) \
153 do { \
154 const struct initcall **ptr; \
155 if (stg >= STG_SIZE) \
156 break; \
157 FOREACH_INITCALL(ptr, stg) \
158 (*ptr)->fct((*ptr)->arg1, (*ptr)->arg2, (*ptr)->arg3); \
159 } while (0)
160
161#endif /* _COMMON_INIT_H */
162
163/*
164 * Local variables:
165 * c-indent-level: 8
166 * c-basic-offset: 8
167 * End:
168 */