1 #ifndef __OSX_ASSUMES_H__
2 #define __OSX_ASSUMES_H__
8 #include <Availability.h>
9 #include <TargetConditionals.h>
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()
22 #define __OSX_COMPILETIME_ASSERT__(e) ({ \
23 char __compile_time_assert__[(e) ? 1 : -1]; \
24 (void)__compile_time_assert__; \
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()
32 #define __OSX_COMPILETIME_ASSERT__(e) (e)
35 typedef bool (*osx_redirect_t
)(const char *);
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.
41 typedef bool (*osx_log_callout_t
)(aslmsg asl_message
, void *ctx
, const char *);
44 #define osx_set_crash_message(arg) /* no-op */
46 #include <CrashReporterClient.h>
47 #define osx_set_crash_message(arg) _crc_make_setter(message, (arg))
50 #define osx_assumes(e) ({ \
51 typeof(e) _e = osx_fastpath(e); /* Force evaluation of 'e' */ \
53 if (osx_constant(e)) { \
54 __OSX_COMPILETIME_ASSERT__(e); \
56 _osx_assumes_log((uint64_t)(uintptr_t)_e); \
57 _osx_avoid_tail_call(); \
62 #define osx_assumes_zero(e) ({ \
63 typeof(e) _e = osx_slowpath(e); \
65 if (osx_constant(e)) { \
66 __OSX_COMPILETIME_ASSERT__(!e); \
68 _osx_assumes_log((uint64_t)(uintptr_t)_e); \
69 _osx_avoid_tail_call(); \
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:
79 * if (pipe(tubes) == -1) {
80 * (void)osx_assumes_zero(errno);
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(); \
92 #define osx_assert(e) ({ \
93 typeof(e) _e = osx_fastpath(e); \
95 if (osx_constant(e)) { \
96 __OSX_COMPILETIME_ASSERT__(e); \
99 char *message = _osx_assert_log((uint64_t)(uintptr_t)_e); \
100 osx_set_crash_message(message); \
101 osx_hardware_trap(); \
106 #define osx_assert_zero(e) ({ \
107 typeof(e) _e = osx_slowpath(e); \
109 if (osx_constant(e)) { \
110 __OSX_COMPILETIME_ASSERT__(!e); \
113 char *message = _osx_assert_log((uint64_t)(uintptr_t)_e); \
114 osx_set_crash_message(message); \
115 osx_hardware_trap(); \
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(); \
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.
134 #define osx_assumes_ctx(f, ctx, e) ({ \
135 typeof(e) _e = osx_fastpath(e); \
137 if (osx_constant(e)) { \
138 __OSX_COMPILETIME_ASSERT__(e); \
140 _osx_assumes_log_ctx(f, ctx, (uintptr_t)_e); \
141 _osx_avoid_tail_call(); \
146 #define osx_assumes_zero_ctx(f, ctx, e) ({ \
147 typeof(e) _e = osx_slowpath(e); \
149 if (osx_constant(e)) { \
150 __OSX_COMPILETIME_ASSERT__(!e); \
152 _osx_assumes_log_ctx((f), (ctx), (uintptr_t)_e); \
153 _osx_avoid_tail_call(); \
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(); \
167 #define osx_assert_ctx(f, ctx, e) ({ \
168 typeof(e) _e = osx_fastpath(e); \
170 if (osx_constant(e)) { \
171 __OSX_COMPILETIME_ASSERT__(e); \
174 char *message = _osx_assert_log_ctx((f), (ctx), (uint64_t)(uintptr_t)_e); \
175 osx_set_crash_message(message); \
176 osx_hardware_trap(); \
181 #define osx_assert_zero_ctx(f, ctx, e) ({ \
182 typeof(e) _e = osx_slowpath(e); \
184 if (osx_constant(e)) { \
185 __OSX_COMPILETIME_ASSERT__(!e); \
188 char *message = _osx_assert_log_ctx((f), (ctx), (uint64_t)(uintptr_t)_e); \
189 osx_set_crash_message(message); \
190 osx_hardware_trap(); \
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(); \
205 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_4_3
)
207 _osx_assumes_log(uint64_t code
);
209 __OSX_AVAILABLE_STARTING(__MAC_10_8
, __IPHONE_6_0
)
211 _osx_assert_log(uint64_t code
);
213 __OSX_AVAILABLE_STARTING(__MAC_10_8
, __IPHONE_6_0
)
215 _osx_assumes_log_ctx(osx_log_callout_t callout
, void *ctx
, uint64_t code
);
217 __OSX_AVAILABLE_STARTING(__MAC_10_8
, __IPHONE_6_0
)
219 _osx_assert_log_ctx(osx_log_callout_t callout
, void *ctx
, uint64_t code
);
221 __OSX_AVAILABLE_STARTING(__MAC_10_8
, __IPHONE_6_0
)
223 _osx_avoid_tail_call(void);
227 #endif /* __OSX_ASSUMES_H__ */