1 /* 2 * Copyright (c) 2008-2013 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 /* 22 * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch 23 * which are subject to change in future releases of Mac OS X. Any applications 24 * relying on these interfaces WILL break. 25 */ 26 27 #ifndef __DISPATCH_OBJECT_INTERNAL__ 28 #define __DISPATCH_OBJECT_INTERNAL__ 29 30 #if OS_OBJECT_USE_OBJC 31 #define DISPATCH_DECL_INTERNAL_SUBCLASS(name, super) \ 32 OS_OBJECT_DECL_SUBCLASS(name, super) 33 #define DISPATCH_DECL_INTERNAL(name) \ 34 DISPATCH_DECL_INTERNAL_SUBCLASS(name, dispatch_object) 35 #define DISPATCH_DECL_SUBCLASS_INTERFACE(name, super) \ 36 _OS_OBJECT_DECL_SUBCLASS_INTERFACE(name, super) 37 #else 38 #define DISPATCH_DECL_INTERNAL_SUBCLASS(name, super) DISPATCH_DECL(name) 39 #define DISPATCH_DECL_INTERNAL(name) DISPATCH_DECL(name) 40 #define DISPATCH_DECL_SUBCLASS_INTERFACE(name, super) 41 #endif // OS_OBJECT_USE_OBJC 42 43 #if USE_OBJC 44 #define DISPATCH_CLASS(name) OS_OBJECT_CLASS(dispatch_##name) 45 // ObjC classes and dispatch vtables are co-located via linker order and alias 46 // files rdar://10640168 47 #define DISPATCH_VTABLE_SUBCLASS_INSTANCE(name, super, ...) \ 48 __attribute__((section("__DATA,__objc_data"), used)) \ 49 static const struct { \ 50 DISPATCH_VTABLE_HEADER(super); \ 51 } DISPATCH_CONCAT(_,DISPATCH_CLASS(name##_vtable)) = { \ 52 __VA_ARGS__ \ 53 } 54 #else 55 #define DISPATCH_VTABLE_SUBCLASS_INSTANCE(name, super, ...) \ 56 DISPATCH_CONST_STRUCT_INSTANCE(dispatch_##super##_vtable_s, \ 57 _dispatch_##name##_vtable, \ 58 ._os_obj_xref_dispose = _dispatch_xref_dispose, \ 59 ._os_obj_dispose = _dispatch_dispose, \ 60 __VA_ARGS__) 61 #endif // USE_OBJC 62 63 #define DISPATCH_SUBCLASS_DECL(name, super) \ 64 DISPATCH_DECL_SUBCLASS_INTERFACE(dispatch_##name, super) \ 65 struct dispatch_##name##_s; \ 66 extern DISPATCH_CONST_STRUCT_DECL(dispatch_##name##_vtable_s, \ 67 _dispatch_##name##_vtable, \ 68 { \ 69 _OS_OBJECT_CLASS_HEADER(); \ 70 DISPATCH_VTABLE_HEADER(name); \ 71 }) 72 #define DISPATCH_CLASS_DECL(name) DISPATCH_SUBCLASS_DECL(name, dispatch_object) 73 #define DISPATCH_INTERNAL_SUBCLASS_DECL(name, super) \ 74 DISPATCH_DECL_INTERNAL_SUBCLASS(dispatch_##name, dispatch_##super); \ 75 DISPATCH_DECL_SUBCLASS_INTERFACE(dispatch_##name, dispatch_##super) \ 76 extern DISPATCH_CONST_STRUCT_DECL(dispatch_##super##_vtable_s, \ 77 _dispatch_##name##_vtable) 78 #define DISPATCH_VTABLE_INSTANCE(name, ...) \ 79 DISPATCH_VTABLE_SUBCLASS_INSTANCE(name, name, __VA_ARGS__) 80 #define DISPATCH_VTABLE(name) &_dispatch_##name##_vtable 81 82 #if !TARGET_OS_WIN32 83 #define DISPATCH_VTABLE_HEADER(x) \ 84 unsigned long const do_type; \ 85 const char *const do_kind; \ 86 size_t (*const do_debug)(struct dispatch_##x##_s *, char *, size_t); \ 87 void (*const do_invoke)(struct dispatch_##x##_s *); \ 88 unsigned long (*const do_probe)(struct dispatch_##x##_s *); \ 89 void (*const do_dispose)(struct dispatch_##x##_s *); 90 #else 91 // Cannot be const on Win32 because we initialize at runtime. 92 #define DISPATCH_VTABLE_HEADER(x) \ 93 unsigned long do_type; \ 94 const char *do_kind; \ 95 size_t (*do_debug)(struct dispatch_##x##_s *, char *, size_t); \ 96 void (*do_invoke)(struct dispatch_##x##_s *); \ 97 unsigned long (*do_probe)(struct dispatch_##x##_s *); \ 98 void (*do_dispose)(struct dispatch_##x##_s *); 99 #endif 100 101 #define dx_type(x) (x)->do_vtable->do_type 102 #define dx_metatype(x) ((x)->do_vtable->do_type & _DISPATCH_META_TYPE_MASK) 103 #define dx_kind(x) (x)->do_vtable->do_kind 104 #define dx_debug(x, y, z) (x)->do_vtable->do_debug((x), (y), (z)) 105 #define dx_dispose(x) (x)->do_vtable->do_dispose(x) 106 #define dx_invoke(x) (x)->do_vtable->do_invoke(x) 107 #define dx_probe(x) (x)->do_vtable->do_probe(x) 108 109 #define DISPATCH_STRUCT_HEADER(x) \ 110 _OS_OBJECT_HEADER( \ 111 const struct dispatch_##x##_vtable_s *do_vtable, \ 112 do_ref_cnt, \ 113 do_xref_cnt); \ 114 struct dispatch_##x##_s *volatile do_next; \ 115 struct dispatch_queue_s *do_targetq; \ 116 void *do_ctxt; \ 117 void *do_finalizer; \ 118 unsigned int volatile do_suspend_cnt; 119 120 #define DISPATCH_OBJECT_GLOBAL_REFCNT _OS_OBJECT_GLOBAL_REFCNT 121 // "word and bit" must be a power of two to be safely subtracted 122 #define DISPATCH_OBJECT_SUSPEND_LOCK 1u 123 #define DISPATCH_OBJECT_SUSPEND_INTERVAL 2u 124 #define DISPATCH_OBJECT_SUSPENDED(x) \ 125 ((x)->do_suspend_cnt >= DISPATCH_OBJECT_SUSPEND_INTERVAL) 126 #ifdef __LP64__ 127 // the bottom nibble must not be zero, the rest of the bits should be random 128 // we sign extend the 64-bit version so that a better instruction encoding is 129 // generated on Intel 130 #define DISPATCH_OBJECT_LISTLESS ((void *)0xffffffff89abcdef) 131 #else 132 #define DISPATCH_OBJECT_LISTLESS ((void *)0x89abcdef) 133 #endif 134 135 enum { 136 _DISPATCH_CONTINUATION_TYPE = 0x00000, // meta-type for continuations 137 _DISPATCH_QUEUE_TYPE = 0x10000, // meta-type for queues 138 _DISPATCH_SOURCE_TYPE = 0x20000, // meta-type for sources 139 _DISPATCH_SEMAPHORE_TYPE = 0x30000, // meta-type for semaphores 140 _DISPATCH_NODE_TYPE = 0x40000, // meta-type for data node 141 _DISPATCH_IO_TYPE = 0x50000, // meta-type for io channels 142 _DISPATCH_OPERATION_TYPE = 0x60000, // meta-type for io operations 143 _DISPATCH_DISK_TYPE = 0x70000, // meta-type for io disks 144 _DISPATCH_META_TYPE_MASK = 0xfff0000, // mask for object meta-types 145 _DISPATCH_ATTR_TYPE = 0x10000000, // meta-type for attributes 146 147 DISPATCH_CONTINUATION_TYPE = _DISPATCH_CONTINUATION_TYPE, 148 149 DISPATCH_DATA_TYPE = 1 | _DISPATCH_NODE_TYPE, 150 DISPATCH_MACH_MSG_TYPE = 2 | _DISPATCH_NODE_TYPE, 151 152 DISPATCH_IO_TYPE = _DISPATCH_IO_TYPE, 153 DISPATCH_OPERATION_TYPE = _DISPATCH_OPERATION_TYPE, 154 DISPATCH_DISK_TYPE = _DISPATCH_DISK_TYPE, 155 156 DISPATCH_QUEUE_ATTR_TYPE = _DISPATCH_QUEUE_TYPE |_DISPATCH_ATTR_TYPE, 157 158 DISPATCH_QUEUE_TYPE = 1 | _DISPATCH_QUEUE_TYPE, 159 DISPATCH_QUEUE_ROOT_TYPE = 2 | _DISPATCH_QUEUE_TYPE, 160 DISPATCH_QUEUE_MGR_TYPE = 3 | _DISPATCH_QUEUE_TYPE, 161 DISPATCH_QUEUE_SPECIFIC_TYPE = 4 | _DISPATCH_QUEUE_TYPE, 162 163 DISPATCH_SEMAPHORE_TYPE = 1 | _DISPATCH_SEMAPHORE_TYPE, 164 DISPATCH_GROUP_TYPE = 2 | _DISPATCH_SEMAPHORE_TYPE, 165 166 DISPATCH_SOURCE_KEVENT_TYPE = 1 | _DISPATCH_SOURCE_TYPE, 167 DISPATCH_MACH_CHANNEL_TYPE = 2 | _DISPATCH_SOURCE_TYPE, 168 }; 169 170 DISPATCH_SUBCLASS_DECL(object, object); 171 struct dispatch_object_s { 172 DISPATCH_STRUCT_HEADER(object); 173 }; 174 175 size_t _dispatch_object_debug_attr(dispatch_object_t dou, char* buf, 176 size_t bufsiz); 177 void *_dispatch_alloc(const void *vtable, size_t size); 178 void _dispatch_xref_dispose(dispatch_object_t dou); 179 void _dispatch_dispose(dispatch_object_t dou); 180 #if DISPATCH_COCOA_COMPAT 181 void *_dispatch_autorelease_pool_push(void); 182 void _dispatch_autorelease_pool_pop(void *context); 183 #endif 184 185 #if USE_OBJC 186 #include <objc/runtime.h> 187 188 #define OS_OBJC_CLASS_SYMBOL(name) \ 189 DISPATCH_CONCAT(OBJC_CLASS_$_,name) 190 #define OS_OBJC_CLASS_DECL(name) \ 191 extern void *OS_OBJC_CLASS_SYMBOL(name) 192 #define OS_OBJC_CLASS(name) \ 193 ((Class)&OS_OBJC_CLASS_SYMBOL(name)) 194 #define OS_OBJECT_OBJC_CLASS_DECL(name) \ 195 OS_OBJC_CLASS_DECL(OS_OBJECT_CLASS(name)) 196 #define OS_OBJECT_OBJC_CLASS(name) \ 197 OS_OBJC_CLASS(OS_OBJECT_CLASS(name)) 198 #define DISPATCH_OBJC_CLASS_DECL(name) \ 199 OS_OBJC_CLASS_DECL(DISPATCH_CLASS(name)) 200 #define DISPATCH_OBJC_CLASS(name) \ 201 OS_OBJC_CLASS(DISPATCH_CLASS(name)) 202 203 OS_OBJECT_OBJC_CLASS_DECL(object); 204 DISPATCH_OBJC_CLASS_DECL(object); 205 206 // ObjC toll-free bridging, keep in sync with libdispatch.order file 207 #define DISPATCH_OBJECT_TFB(f, o, ...) \ 208 if (slowpath((uintptr_t)((o)._os_obj->os_obj_isa) & 1) || \ 209 slowpath((Class)((o)._os_obj->os_obj_isa) < \ 210 DISPATCH_OBJC_CLASS(object)) || \ 211 slowpath((Class)((o)._os_obj->os_obj_isa) >= \ 212 OS_OBJECT_OBJC_CLASS(object))) { \ 213 return f((o), ##__VA_ARGS__); \ 214 } 215 216 id _dispatch_objc_alloc(Class cls, size_t size); 217 void _dispatch_objc_retain(dispatch_object_t dou); 218 void _dispatch_objc_release(dispatch_object_t dou); 219 void _dispatch_objc_set_context(dispatch_object_t dou, void *context); 220 void *_dispatch_objc_get_context(dispatch_object_t dou); 221 void _dispatch_objc_set_finalizer_f(dispatch_object_t dou, 222 dispatch_function_t finalizer); 223 void _dispatch_objc_set_target_queue(dispatch_object_t dou, 224 dispatch_queue_t queue); 225 void _dispatch_objc_suspend(dispatch_object_t dou); 226 void _dispatch_objc_resume(dispatch_object_t dou); 227 size_t _dispatch_objc_debug(dispatch_object_t dou, char* buf, size_t bufsiz); 228 229 #if __OBJC2__ 230 @interface NSObject (DISPATCH_CONCAT(_,DISPATCH_CLASS(object))) 231 - (void)_setContext:(void*)context; 232 - (void*)_getContext; 233 - (void)_setFinalizer:(dispatch_function_t)finalizer; 234 - (void)_setTargetQueue:(dispatch_queue_t)queue; 235 - (void)_suspend; 236 - (void)_resume; 237 @end 238 #endif // __OBJC2__ 239 #else // USE_OBJC 240 #define DISPATCH_OBJECT_TFB(f, o, ...) 241 #endif // USE_OBJC 242 243 #pragma mark - 244 #pragma mark _os_object_s 245 246 typedef struct _os_object_class_s { 247 _OS_OBJECT_CLASS_HEADER(); 248 } _os_object_class_s; 249 250 typedef struct _os_object_s { 251 _OS_OBJECT_HEADER( 252 const _os_object_class_s *os_obj_isa, 253 os_obj_ref_cnt, 254 os_obj_xref_cnt); 255 } _os_object_s; 256 257 void _os_object_init(void); 258 unsigned long _os_object_retain_count(_os_object_t obj); 259 bool _os_object_retain_weak(_os_object_t obj); 260 bool _os_object_allows_weak_reference(_os_object_t obj); 261 void _os_object_dispose(_os_object_t obj); 262 void _os_object_xref_dispose(_os_object_t obj); 263 264 #endif // __DISPATCH_OBJECT_INTERNAL__ 265