]>
Commit | Line | Data |
---|---|---|
58ef912c MM |
1 | /* |
2 | * BIRD Library | |
3 | * | |
206f59df | 4 | * (c) 1998--2004 Martin Mares <mj@ucw.cz> |
58ef912c MM |
5 | * |
6 | * Can be freely distributed and used under the terms of the GNU GPL. | |
7 | */ | |
8 | ||
9 | #ifndef _BIRD_BIRDLIB_H_ | |
10 | #define _BIRD_BIRDLIB_H_ | |
11 | ||
7152e5ef | 12 | #include "lib/alloca.h" |
cb530392 | 13 | |
58ef912c MM |
14 | /* Ugly structure offset handling macros */ |
15 | ||
b845ea09 OZ |
16 | struct align_probe { char x; long int y; }; |
17 | ||
54d70d3e | 18 | #define OFFSETOF(s, i) ((size_t) &((s *)0)->i) |
58ef912c | 19 | #define SKIP_BACK(s, i, p) ((s *)((char *)p - OFFSETOF(s, i))) |
7fdd338c | 20 | #define BIRD_ALIGN(s, a) (((s)+a-1)&~(a-1)) |
b845ea09 | 21 | #define CPU_STRUCT_ALIGN (sizeof(struct align_probe)) |
18c8241a | 22 | |
c4c63eec MM |
23 | /* Utility macros */ |
24 | ||
41f8bf57 OZ |
25 | #define MIN_(a,b) (((a)<(b))?(a):(b)) |
26 | #define MAX_(a,b) (((a)>(b))?(a):(b)) | |
0e175f9f OZ |
27 | |
28 | #ifndef PARSER | |
1ec52253 OZ |
29 | #undef MIN |
30 | #undef MAX | |
41f8bf57 OZ |
31 | #define MIN(a,b) MIN_(a,b) |
32 | #define MAX(a,b) MAX_(a,b) | |
93e868c7 OZ |
33 | #endif |
34 | ||
5126380b | 35 | #define U64(c) UINT64_C(c) |
47f18ac3 | 36 | #define ABS(a) ((a)>=0 ? (a) : -(a)) |
8d9eef17 | 37 | #define DELTA(a,b) (((a)>=(b))?(a)-(b):(b)-(a)) |
77506349 | 38 | #define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) |
77234bbb | 39 | #define BYTES(n) ((((uint) (n)) + 7) / 8) |
f4a60a9b | 40 | #define CALL(fn, args...) ({ if (fn) fn(args); }) |
524d2538 | 41 | #define ADVANCE(w, r, l) ({ r -= (l); w += (l); }) |
cf3527e2 | 42 | |
5e173e9f JMM |
43 | static inline int uint_cmp(uint i1, uint i2) |
44 | { return (int)(i1 > i2) - (int)(i1 < i2); } | |
45 | ||
46 | static inline int u64_cmp(u64 i1, u64 i2) | |
47 | { return (int)(i1 > i2) - (int)(i1 < i2); } | |
48 | ||
4e639744 OZ |
49 | |
50 | /* Bitfield macros */ | |
51 | ||
52 | /* b is u32 array (or ptr), l is size of it in bits (multiple of 32), p is 0..(l-1) */ | |
70945cb6 OZ |
53 | #define BIT32_VAL(p) (((u32) 1) << ((p) % 32)) |
54 | #define BIT32_TEST(b,p) ((b)[(p)/32] & BIT32_VAL(p)) | |
55 | #define BIT32_SET(b,p) ((b)[(p)/32] |= BIT32_VAL(p)) | |
56 | #define BIT32_CLR(b,p) ((b)[(p)/32] &= ~BIT32_VAL(p)) | |
57 | #define BIT32_ZERO(b,l) memset((b), 0, (l)/8) | |
58 | ||
5a50a989 OZ |
59 | /* The same, but counting bits from MSB */ |
60 | #define BIT32R_VAL(p) ((((u32) 1) << 31) >> ((p) % 32)) | |
61 | #define BIT32R_TEST(b,p) ((b)[(p)/32] & BIT32R_VAL(p)) | |
62 | #define BIT32R_SET(b,p) ((b)[(p)/32] |= BIT32R_VAL(p)) | |
63 | #define BIT32R_CLR(b,p) ((b)[(p)/32] &= ~BIT32R_VAL(p)) | |
64 | #define BIT32R_ZERO(b,l) memset((b), 0, (l)/8) | |
65 | ||
61340248 MM |
66 | #ifndef NULL |
67 | #define NULL ((void *) 0) | |
68 | #endif | |
69 | ||
5da8f82f | 70 | /* Macros for gcc attributes */ |
18c8241a MM |
71 | |
72 | #define NORET __attribute__((noreturn)) | |
206f59df | 73 | #define UNUSED __attribute__((unused)) |
937e75d8 | 74 | #define PACKED __attribute__((packed)) |
bf9486bf | 75 | #define NONNULL(...) __attribute__((nonnull((__VA_ARGS__)))) |
58ef912c | 76 | |
3782454e MM |
77 | #ifndef HAVE_THREAD_LOCAL |
78 | #define _Thread_local | |
6479e403 JMM |
79 | #endif |
80 | ||
0e175f9f OZ |
81 | /* Microsecond time */ |
82 | ||
83 | typedef s64 btime; | |
574b2324 | 84 | //typedef s64 bird_clock_t; |
0e175f9f | 85 | |
ee528fbd OZ |
86 | #define S_ * (btime) 1000000 |
87 | #define MS_ * (btime) 1000 | |
88 | #define US_ * (btime) 1 | |
0e175f9f OZ |
89 | #define TO_S /1000000 |
90 | #define TO_MS /1000 | |
91 | #define TO_US /1 | |
92 | ||
93 | #ifndef PARSER | |
41f8bf57 OZ |
94 | #define S S_ |
95 | #define MS MS_ | |
96 | #define US US_ | |
ee528fbd | 97 | #define NS /1000 |
0e175f9f OZ |
98 | #endif |
99 | ||
574b2324 OZ |
100 | #define TIME_INFINITY ((s64) 0x7fffffffffffffff) |
101 | ||
0e175f9f | 102 | |
1123e707 OZ |
103 | /* Rate limiting */ |
104 | ||
105 | struct tbf { | |
574b2324 OZ |
106 | btime timestamp; /* Last update */ |
107 | u64 count; /* Available micro-tokens */ | |
1123e707 | 108 | u16 burst; /* Max number of tokens */ |
574b2324 OZ |
109 | u16 rate; /* Rate of replenishment (tokens / sec) */ |
110 | u32 drop; /* Number of failed request since last successful */ | |
1123e707 OZ |
111 | }; |
112 | ||
113 | /* Default TBF values for rate limiting log messages */ | |
114 | #define TBF_DEFAULT_LOG_LIMITS { .rate = 1, .burst = 5 } | |
115 | ||
574b2324 | 116 | int tbf_limit(struct tbf *f); |
1123e707 OZ |
117 | |
118 | ||
c40e05a0 MM |
119 | /* Logging and dying */ |
120 | ||
0e175f9f OZ |
121 | typedef struct buffer { |
122 | byte *start; | |
123 | byte *pos; | |
124 | byte *end; | |
125 | } buffer; | |
126 | ||
127 | #define STACK_BUFFER_INIT(buf,size) \ | |
128 | do { \ | |
129 | buf.start = alloca(size); \ | |
130 | buf.pos = buf.start; \ | |
131 | buf.end = buf.start + size; \ | |
132 | } while(0) | |
133 | ||
134 | #define LOG_BUFFER_INIT(buf) \ | |
135 | STACK_BUFFER_INIT(buf, LOG_BUFFER_SIZE) | |
136 | ||
137 | #define LOG_BUFFER_SIZE 1024 | |
138 | ||
e98bc2ea | 139 | #define log log_msg |
0e175f9f | 140 | void log_commit(int class, buffer *buf); |
e598853e PT |
141 | void log_msg(const char *msg, ...); |
142 | void log_rl(struct tbf *rl, const char *msg, ...); | |
143 | void die(const char *msg, ...) NORET; | |
144 | void bug(const char *msg, ...) NORET; | |
c40e05a0 MM |
145 | |
146 | #define L_DEBUG "\001" /* Debugging messages */ | |
98e87c86 MM |
147 | #define L_TRACE "\002" /* Protocol tracing */ |
148 | #define L_INFO "\003" /* Informational messages */ | |
149 | #define L_REMOTE "\004" /* Remote protocol errors */ | |
27e993fb MM |
150 | #define L_WARN "\005" /* Local warnings */ |
151 | #define L_ERR "\006" /* Local errors */ | |
152 | #define L_AUTH "\007" /* Authorization failed etc. */ | |
153 | #define L_FATAL "\010" /* Fatal errors */ | |
154 | #define L_BUG "\011" /* BIRD bugs */ | |
18c8241a | 155 | |
9b0a0ba9 | 156 | void debug(const char *msg, ...); /* Printf to debug output */ |
c40e05a0 MM |
157 | |
158 | /* Debugging */ | |
159 | ||
3cbfcafe | 160 | #if defined(LOCAL_DEBUG) || defined(GLOBAL_DEBUG) |
5222c46c | 161 | #define DBG(x, y...) debug(x, ##y) |
c40e05a0 | 162 | #else |
e68dd11c | 163 | #define DBG(x, y...) do { } while(0) |
c40e05a0 MM |
164 | #endif |
165 | ||
8029ae52 MM |
166 | #define ASSERT_DIE(x) do { if (!(x)) bug("Assertion '%s' failed at %s:%d", #x, __FILE__, __LINE__); } while(0) |
167 | ||
a0d0a71a MM |
168 | #define EXPENSIVE_CHECK(x) /* intentionally left blank */ |
169 | ||
98e87c86 | 170 | #ifdef DEBUGGING |
8029ae52 MM |
171 | #define ASSERT(x) ASSERT_DIE(x) |
172 | #define ASSUME(x) ASSERT_DIE(x) | |
a0d0a71a MM |
173 | #ifdef ENABLE_EXPENSIVE_CHECKS |
174 | #undef EXPENSIVE_CHECK | |
175 | #define EXPENSIVE_CHECK(x) ASSERT_DIE(x) | |
176 | #endif | |
98e87c86 | 177 | #else |
2e507a74 | 178 | #define ASSERT(x) do { if (!(x)) log(L_BUG "Assertion '%s' failed at %s:%d", #x, __FILE__, __LINE__); } while(0) |
8029ae52 | 179 | #define ASSUME(x) /* intentionally left blank */ |
98e87c86 MM |
180 | #endif |
181 | ||
a0d0a71a | 182 | |
71365879 MM |
183 | #ifdef DEBUGGING |
184 | asm( | |
185 | ".pushsection \".debug_gdb_scripts\", \"MS\",@progbits,1\n" | |
186 | ".byte 1\n" /* Python */ | |
187 | ".asciz \"bird-gdb.py\"\n" | |
188 | ".popsection\n" | |
189 | ); | |
190 | #endif | |
191 | ||
f6519414 MM |
192 | /* Pseudorandom numbers */ |
193 | ||
194 | u32 random_u32(void); | |
195 | ||
58ef912c | 196 | #endif |