]> git.saurik.com Git - apple/xnu.git/blame - libkern/os/base.h
xnu-6153.61.1.tar.gz
[apple/xnu.git] / libkern / os / base.h
CommitLineData
39037602 1/*
cb323159 2 * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
39037602
A
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20
21#ifndef __OS_BASE__
22#define __OS_BASE__
23
24#include <sys/cdefs.h>
25
26#ifndef __has_builtin
27#define __has_builtin(x) 0
28#endif
29#ifndef __has_include
30#define __has_include(x) 0
31#endif
32#ifndef __has_feature
33#define __has_feature(x) 0
34#endif
35#ifndef __has_attribute
36#define __has_attribute(x) 0
37#endif
38#ifndef __has_extension
39#define __has_extension(x) 0
40#endif
41
42#undef OS_INLINE // <sys/_types/_os_inline.h>
43#if __GNUC__
44#define OS_NORETURN __attribute__((__noreturn__))
45#define OS_NOTHROW __attribute__((__nothrow__))
46#define OS_NONNULL1 __attribute__((__nonnull__(1)))
47#define OS_NONNULL2 __attribute__((__nonnull__(2)))
48#define OS_NONNULL3 __attribute__((__nonnull__(3)))
49#define OS_NONNULL4 __attribute__((__nonnull__(4)))
50#define OS_NONNULL5 __attribute__((__nonnull__(5)))
51#define OS_NONNULL6 __attribute__((__nonnull__(6)))
52#define OS_NONNULL7 __attribute__((__nonnull__(7)))
53#define OS_NONNULL8 __attribute__((__nonnull__(8)))
54#define OS_NONNULL9 __attribute__((__nonnull__(9)))
55#define OS_NONNULL10 __attribute__((__nonnull__(10)))
56#define OS_NONNULL11 __attribute__((__nonnull__(11)))
57#define OS_NONNULL12 __attribute__((__nonnull__(12)))
58#define OS_NONNULL13 __attribute__((__nonnull__(13)))
59#define OS_NONNULL14 __attribute__((__nonnull__(14)))
60#define OS_NONNULL15 __attribute__((__nonnull__(15)))
61#define OS_NONNULL_ALL __attribute__((__nonnull__))
62#define OS_SENTINEL __attribute__((__sentinel__))
63#define OS_PURE __attribute__((__pure__))
64#define OS_CONST __attribute__((__const__))
65#define OS_WARN_RESULT __attribute__((__warn_unused_result__))
66#define OS_MALLOC __attribute__((__malloc__))
67#define OS_USED __attribute__((__used__))
68#define OS_UNUSED __attribute__((__unused__))
69#define OS_COLD __attribute__((__cold__))
70#define OS_WEAK __attribute__((__weak__))
71#define OS_WEAK_IMPORT __attribute__((__weak_import__))
72#define OS_NOINLINE __attribute__((__noinline__))
73#define OS_ALWAYS_INLINE __attribute__((__always_inline__))
74#define OS_TRANSPARENT_UNION __attribute__((__transparent_union__))
75#define OS_ALIGNED(n) __attribute__((__aligned__((n))))
0a7de745 76#define OS_FORMAT_PRINTF(x, y) __attribute__((__format__(printf,x,y)))
39037602
A
77#define OS_EXPORT extern __attribute__((__visibility__("default")))
78#define OS_INLINE static __inline__
79#define OS_EXPECT(x, v) __builtin_expect((x), (v))
80#else
81#define OS_NORETURN
82#define OS_NOTHROW
83#define OS_NONNULL1
84#define OS_NONNULL2
85#define OS_NONNULL3
86#define OS_NONNULL4
87#define OS_NONNULL5
88#define OS_NONNULL6
89#define OS_NONNULL7
90#define OS_NONNULL8
91#define OS_NONNULL9
92#define OS_NONNULL10
93#define OS_NONNULL11
94#define OS_NONNULL12
95#define OS_NONNULL13
96#define OS_NONNULL14
97#define OS_NONNULL15
98#define OS_NONNULL_ALL
99#define OS_SENTINEL
100#define OS_PURE
101#define OS_CONST
102#define OS_WARN_RESULT
103#define OS_MALLOC
104#define OS_USED
105#define OS_UNUSED
106#define OS_COLD
107#define OS_WEAK
108#define OS_WEAK_IMPORT
109#define OS_NOINLINE
110#define OS_ALWAYS_INLINE
111#define OS_TRANSPARENT_UNION
112#define OS_ALIGNED(n)
0a7de745 113#define OS_FORMAT_PRINTF(x, y)
39037602
A
114#define OS_EXPORT extern
115#define OS_INLINE static inline
116#define OS_EXPECT(x, v) (x)
117#endif
118
119#if __has_attribute(noescape)
120#define OS_NOESCAPE __attribute__((__noescape__))
121#else
122#define OS_NOESCAPE
123#endif
124
cb323159
A
125#if defined(__cplusplus) && defined(__clang__)
126#define OS_FALLTHROUGH [[clang::fallthrough]]
127#else
128#define OS_FALLTHROUGH
129#endif
130
39037602
A
131#if __has_feature(assume_nonnull)
132#define OS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
133#define OS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
134#else
135#define OS_ASSUME_NONNULL_BEGIN
136#define OS_ASSUME_NONNULL_END
137#endif
138
139#if __has_builtin(__builtin_assume)
140#define OS_COMPILER_CAN_ASSUME(expr) __builtin_assume(expr)
141#else
142#define OS_COMPILER_CAN_ASSUME(expr) ((void)(expr))
143#endif
144
145#if __has_extension(attribute_overloadable)
146#define OS_OVERLOADABLE __attribute__((__overloadable__))
147#else
148#define OS_OVERLOADABLE
149#endif
150
cb323159
A
151#if __has_attribute(enum_extensibility)
152#define __OS_ENUM_ATTR __attribute__((enum_extensibility(open)))
153#define __OS_ENUM_ATTR_CLOSED __attribute__((enum_extensibility(closed)))
154#else
155#define __OS_ENUM_ATTR
156#define __OS_ENUM_ATTR_CLOSED
157#endif // __has_attribute(enum_extensibility)
158
159#if __has_attribute(flag_enum)
160/*!
161 * Compile with -Wflag-enum and -Wassign-enum to enforce at definition and
162 * assignment, respectively, i.e. -Wflag-enum prevents you from creating new
163 * enumeration values from illegal values within the enum definition, and
164 * -Wassign-enum prevents you from assigning illegal values to a variable of the
165 * enum type.
166 */
167#define __OS_OPTIONS_ATTR __attribute__((flag_enum))
168#else
169#define __OS_OPTIONS_ATTR
170#endif // __has_attribute(flag_enum)
171
172#if __has_feature(objc_fixed_enum) || __has_extension(cxx_fixed_enum) || \
173 __has_extension(cxx_strong_enums)
39037602 174#define OS_ENUM(_name, _type, ...) \
0a7de745 175 typedef enum : _type { __VA_ARGS__ } _name##_t
cb323159
A
176#define OS_CLOSED_ENUM(_name, _type, ...) \
177 typedef enum : _type { __VA_ARGS__ } \
178 __OS_ENUM_ATTR_CLOSED _name##_t
179#define OS_OPTIONS(_name, _type, ...) \
180 typedef enum : _type { __VA_ARGS__ } \
181 __OS_ENUM_ATTR __OS_OPTIONS_ATTR _name##_t
182#define OS_CLOSED_OPTIONS(_name, _type, ...) \
183 typedef enum : _type { __VA_ARGS__ } \
184 __OS_ENUM_ATTR_CLOSED __OS_OPTIONS_ATTR _name##_t
39037602 185#else
cb323159
A
186/*!
187 * There is unfortunately no good way in plain C to have both fixed-type enums
188 * and enforcement for clang's enum_extensibility extensions. The primary goal
189 * of these macros is to allow you to define an enum and specify its width in a
190 * single statement, and for plain C that is accomplished by defining an
191 * anonymous enum and then separately typedef'ing the requested type name to the
192 * requested underlying integer type. So the type emitted actually has no
193 * relationship at all to the enum, and therefore while the compiler could
194 * enforce enum extensibility if you used the enum type, it cannot do so if you
195 * use the "_t" type resulting from this expression.
196 *
197 * But we still define a named enum type and decorate it appropriately for you,
198 * so if you really want the enum extensibility enforcement, you can use the
199 * enum type yourself, i.e. when compiling with a C compiler:
200 *
201 * OS_CLOSED_ENUM(my_type, uint64_t,
202 * FOO,
203 * BAR,
204 * BAZ,
205 * );
206 *
207 * my_type_t mt = 98; // legal
208 * enum my_type emt = 98; // illegal
209 *
210 * But be aware that the underlying enum type's width is subject only to the C
211 * language's guarantees -- namely that it will be compatible with int, char,
212 * and unsigned char. It is not safe to rely on the size of this type.
213 *
214 * When compiling in ObjC or C++, both of the above assignments are illegal.
215 */
216#define __OS_ENUM_C_FALLBACK(_name, _type, ...) \
217 typedef _type _name##_t; enum _name { __VA_ARGS__ }
218
39037602 219#define OS_ENUM(_name, _type, ...) \
cb323159
A
220 typedef _type _name##_t; enum { __VA_ARGS__ }
221#define OS_CLOSED_ENUM(_name, _type, ...) \
222 __OS_ENUM_C_FALLBACK(_name, _type, ## __VA_ARGS__) \
223 __OS_ENUM_ATTR_CLOSED
224#define OS_OPTIONS(_name, _type, ...) \
225 __OS_ENUM_C_FALLBACK(_name, _type, ## __VA_ARGS__) \
226 __OS_ENUM_ATTR __OS_OPTIONS_ATTR
227#define OS_CLOSED_OPTIONS(_name, _type, ...) \
228 __OS_ENUM_C_FALLBACK(_name, _type, ## __VA_ARGS__) \
229 __OS_ENUM_ATTR_CLOSED __OS_OPTIONS_ATTR
230#endif // __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums)
39037602
A
231
232#if __has_feature(attribute_availability_swift)
233// equivalent to __SWIFT_UNAVAILABLE from Availability.h
234#define OS_SWIFT_UNAVAILABLE(_msg) \
0a7de745 235 __attribute__((__availability__(swift, unavailable, message=_msg)))
39037602
A
236#else
237#define OS_SWIFT_UNAVAILABLE(_msg)
238#endif
239
240#if __has_attribute(swift_private)
241# define OS_REFINED_FOR_SWIFT __attribute__((__swift_private__))
242#else
243# define OS_REFINED_FOR_SWIFT
244#endif
245
246#if __has_attribute(swift_name)
247# define OS_SWIFT_NAME(_name) __attribute__((__swift_name__(#_name)))
248#else
249# define OS_SWIFT_NAME(_name)
250#endif
251
252#define __OS_STRINGIFY(s) #s
253#define OS_STRINGIFY(s) __OS_STRINGIFY(s)
254#define __OS_CONCAT(x, y) x ## y
255#define OS_CONCAT(x, y) __OS_CONCAT(x, y)
256
257#ifdef __GNUC__
258#define os_prevent_tail_call_optimization() __asm__("")
259#define os_is_compile_time_constant(expr) __builtin_constant_p(expr)
cb323159 260#ifndef KERNEL
39037602 261#define os_compiler_barrier() __asm__ __volatile__("" ::: "memory")
cb323159 262#endif
39037602
A
263#else
264#define os_prevent_tail_call_optimization() do { } while (0)
265#define os_is_compile_time_constant(expr) 0
cb323159 266#ifndef KERNEL
39037602
A
267#define os_compiler_barrier() do { } while (0)
268#endif
cb323159 269#endif
39037602
A
270
271#if __has_attribute(not_tail_called)
272#define OS_NOT_TAIL_CALLED __attribute__((__not_tail_called__))
273#else
274#define OS_NOT_TAIL_CALLED
275#endif
276
cb323159
A
277/*
278 * LIBKERN_ALWAYS_DESTROY attribute can be applied to global variables with
279 * destructors. It specifies that and object should have its exit-time
280 * destructor run. This attribute is the default unless clang was invoked with
281 * -fno-c++-static-destructors.
282 */
283#if __has_attribute(always_destroy)
284#define LIBKERN_ALWAYS_DESTROY __attribute__((always_destroy))
285#else
286#define LIBKERN_ALWAYS_DESTROY
287#endif
288
39037602
A
289typedef void (*os_function_t)(void *_Nullable);
290
291#ifdef __BLOCKS__
292/*!
293 * @typedef os_block_t
294 *
295 * @abstract
296 * Generic type for a block taking no arguments and returning no value.
297 *
298 * @discussion
299 * When not building with Objective-C ARC, a block object allocated on or
300 * copied to the heap must be released with a -[release] message or the
301 * Block_release() function.
302 *
303 * The declaration of a block literal allocates storage on the stack.
304 * Therefore, this is an invalid construct:
305 * <code>
306 * os_block_t block;
307 * if (x) {
308 * block = ^{ printf("true\n"); };
309 * } else {
310 * block = ^{ printf("false\n"); };
311 * }
312 * block(); // unsafe!!!
313 * </code>
314 *
315 * What is happening behind the scenes:
316 * <code>
317 * if (x) {
318 * struct Block __tmp_1 = ...; // setup details
319 * block = &__tmp_1;
320 * } else {
321 * struct Block __tmp_2 = ...; // setup details
322 * block = &__tmp_2;
323 * }
324 * </code>
325 *
326 * As the example demonstrates, the address of a stack variable is escaping the
327 * scope in which it is allocated. That is a classic C bug.
328 *
329 * Instead, the block literal must be copied to the heap with the Block_copy()
330 * function or by sending it a -[copy] message.
331 */
332typedef void (^os_block_t)(void);
333#endif
334
335#endif // __OS_BASE__