]> git.saurik.com Git - apple/libc.git/blob - gen/assumes.h
Libc-825.26.tar.gz
[apple/libc.git] / gen / assumes.h
1 #ifndef __OSX_ASSUMES_H__
2 #define __OSX_ASSUMES_H__
3
4 #include <sys/cdefs.h>
5
6 __BEGIN_DECLS
7
8 #include <Availability.h>
9 #include <TargetConditionals.h>
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include <stdarg.h>
13 #include <stdbool.h>
14 #include <asl.h>
15
16 #if __GNUC__
17 #define osx_fastpath(x) ((typeof(x))__builtin_expect((long)(x), ~0l))
18 #define osx_slowpath(x) ((typeof(x))__builtin_expect((long)(x), 0l))
19 #define osx_constant(x) __builtin_constant_p((x))
20 #define osx_hardware_trap() __builtin_trap()
21
22 #define __OSX_COMPILETIME_ASSERT__(e) ({ \
23 char __compile_time_assert__[(e) ? 1 : -1]; \
24 (void)__compile_time_assert__; \
25 })
26 #else
27 #define osx_fastpath(x) (x)
28 #define osx_slowpath(x) (x)
29 #define osx_constant(x) ((long)0)
30 #define osx_hardware_trap() abort()
31
32 #define __OSX_COMPILETIME_ASSERT__(e) (e)
33 #endif /* __GNUC__ */
34
35 typedef bool (*osx_redirect_t)(const char *);
36
37 /* The asl_message argument is an aslmsg that, when given to asl_log(), will
38 * direct the message to the MessageTracer diagnostic messages store rather than
39 * the default system log store.
40 */
41 typedef bool (*osx_log_callout_t)(aslmsg asl_message, void *ctx, const char *);
42
43 #if TARGET_OS_IPHONE
44 #define osx_set_crash_message(arg) /* no-op */
45 #else
46 #include <CrashReporterClient.h>
47 #define osx_set_crash_message(arg) _crc_make_setter(message, (arg))
48 #endif
49
50 #define osx_assumes(e) ({ \
51 typeof(e) _e = osx_fastpath(e); /* Force evaluation of 'e' */ \
52 if (!_e) { \
53 if (osx_constant(e)) { \
54 __OSX_COMPILETIME_ASSERT__(e); \
55 } \
56 _osx_assumes_log((uint64_t)(uintptr_t)_e); \
57 _osx_avoid_tail_call(); \
58 } \
59 _e; \
60 })
61
62 #define osx_assumes_zero(e) ({ \
63 typeof(e) _e = osx_slowpath(e); \
64 if (_e) { \
65 if (osx_constant(e)) { \
66 __OSX_COMPILETIME_ASSERT__(!e); \
67 } \
68 _osx_assumes_log((uint64_t)(uintptr_t)_e); \
69 _osx_avoid_tail_call(); \
70 } \
71 _e; \
72 })
73
74 /* This variant is for use with old-style POSIX APIs that return -1 on failure
75 * and set errno. If the return code is -1, the value logged will be as though
76 * osx_assumes_zero(errno) was used. It encapsulates the following pattern:
77 *
78 * int tubes[2];
79 * if (pipe(tubes) == -1) {
80 * (void)osx_assumes_zero(errno);
81 * }
82 */
83 #define posix_assumes_zero(e) ({ \
84 typeof(e) _e = osx_slowpath(e); \
85 if (_e == (typeof(e))-1) { \
86 _osx_assumes_log((uint64_t)(uintptr_t)errno); \
87 _osx_avoid_tail_call(); \
88 } \
89 _e; \
90 })
91
92 #define osx_assert(e) ({ \
93 typeof(e) _e = osx_fastpath(e); \
94 if (!_e) { \
95 if (osx_constant(e)) { \
96 __OSX_COMPILETIME_ASSERT__(e); \
97 } \
98 \
99 char *message = _osx_assert_log((uint64_t)(uintptr_t)_e); \
100 osx_set_crash_message(message); \
101 osx_hardware_trap(); \
102 free(message); \
103 } \
104 })
105
106 #define osx_assert_zero(e) ({ \
107 typeof(e) _e = osx_slowpath(e); \
108 if (_e) { \
109 if (osx_constant(e)) { \
110 __OSX_COMPILETIME_ASSERT__(!e); \
111 } \
112 \
113 char *message = _osx_assert_log((uint64_t)(uintptr_t)_e); \
114 osx_set_crash_message(message); \
115 osx_hardware_trap(); \
116 free(message); \
117 } \
118 })
119
120 #define posix_assert_zero(e) ({ \
121 typeof(e) _e = osx_slowpath(e); \
122 if (_e == (typeof(e))-1) { \
123 char *message = _osx_assert_log((uint64_t)(uintptr_t)errno); \
124 osx_set_crash_message(message); \
125 osx_hardware_trap(); \
126 free(message); \
127 } \
128 })
129
130 /* These are for defining your own assumes()-like wrapper calls so that you can
131 * log additional information, such as the about-PID, sender, etc. They're
132 * generally not useful for direct inclusion in your code.
133 */
134 #define osx_assumes_ctx(f, ctx, e) ({ \
135 typeof(e) _e = osx_fastpath(e); \
136 if (!_e) { \
137 if (osx_constant(e)) { \
138 __OSX_COMPILETIME_ASSERT__(e); \
139 } \
140 _osx_assumes_log_ctx(f, ctx, (uintptr_t)_e); \
141 _osx_avoid_tail_call(); \
142 } \
143 _e; \
144 })
145
146 #define osx_assumes_zero_ctx(f, ctx, e) ({ \
147 typeof(e) _e = osx_slowpath(e); \
148 if (_e) { \
149 if (osx_constant(e)) { \
150 __OSX_COMPILETIME_ASSERT__(!e); \
151 } \
152 _osx_assumes_log_ctx((f), (ctx), (uintptr_t)_e); \
153 _osx_avoid_tail_call(); \
154 } \
155 _e; \
156 })
157
158 #define posix_assumes_zero_ctx(f, ctx, e) ({ \
159 typeof(e) _e = osx_slowpath(e); \
160 if (_e == (typeof(e))-1) { \
161 _osx_assumes_log_ctx((f), (ctx), (uintptr_t)errno); \
162 _osx_avoid_tail_call(); \
163 } \
164 _e; \
165 })
166
167 #define osx_assert_ctx(f, ctx, e) ({ \
168 typeof(e) _e = osx_fastpath(e); \
169 if (!_e) { \
170 if (osx_constant(e)) { \
171 __OSX_COMPILETIME_ASSERT__(e); \
172 } \
173 \
174 char *message = _osx_assert_log_ctx((f), (ctx), (uint64_t)(uintptr_t)_e); \
175 osx_set_crash_message(message); \
176 osx_hardware_trap(); \
177 free(message); \
178 } \
179 })
180
181 #define osx_assert_zero_ctx(f, ctx, e) ({ \
182 typeof(e) _e = osx_slowpath(e); \
183 if (_e) { \
184 if (osx_constant(e)) { \
185 __OSX_COMPILETIME_ASSERT__(!e); \
186 } \
187 \
188 char *message = _osx_assert_log_ctx((f), (ctx), (uint64_t)(uintptr_t)_e); \
189 osx_set_crash_message(message); \
190 osx_hardware_trap(); \
191 free(message); \
192 } \
193 })
194
195 #define posix_assert_zero_ctx(f, ctx, e) ({ \
196 typeof(e) _e = osx_slowpath(e); \
197 if (_e == (typeof(e))-1) { \
198 char *message = _osx_assert_log_ctx((f), (ctx), (uint64_t)(uintptr_t)errno); \
199 osx_set_crash_message(message); \
200 osx_hardware_trap(); \
201 free(message); \
202 } \
203 })
204
205 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3)
206 extern void
207 _osx_assumes_log(uint64_t code);
208
209 __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0)
210 extern char *
211 _osx_assert_log(uint64_t code);
212
213 __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0)
214 extern void
215 _osx_assumes_log_ctx(osx_log_callout_t callout, void *ctx, uint64_t code);
216
217 __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0)
218 extern char *
219 _osx_assert_log_ctx(osx_log_callout_t callout, void *ctx, uint64_t code);
220
221 __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0)
222 extern void
223 _osx_avoid_tail_call(void);
224
225 __END_DECLS
226
227 #endif /* __OSX_ASSUMES_H__ */