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