lldb bt 堆栈信息
GCD源码存在于dyld
几种类型的队列
首先测试打印几种常用的queue
- (void)queueTestPrint {
dispatch_queue_t serial = dispatch_queue_create("ifl_queue_serial",
DISPATCH_QUEUE_SERIAL);
dispatch_queue_t conque = dispatch_queue_create("ifl_queue_concurrent",
DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_queue_t globQueue = dispatch_get_global_queue(0, 0);
NSLog(@"\n%@\n%@\n%@\n%@",serial,conque,mainQueue,globQueue);
}
测试结果
<OS_dispatch_queue_serial: ifl_queue_serial>
<OS_dispatch_queue_concurrent: ifl_queue_concurrent>
<OS_dispatch_queue_main: com.apple.main-thread>
<OS_dispatch_queue_global: com.apple.root.default-qos>
乍一看,貌似可以分为4种, 且看 - 暂且不表
串行队列 - ifl_queue_serial
并行队列 - ifl_queue_concurrent
主队列 - com.apple.main-thread
全局队列 - com.apple.root.default-qos
主队列 - com.apple.main-thread
-
主队列溯源 - dispatch_get_main_queue()
-
dispatch_queue_main_t dispatch_get_main_queue(void) { return DISPATCH_GLOBAL_OBJECT(dispatch_queue_main_t, _dispatch_main_q); } -
DISPATCH_GLOBAL_OBJECT(dispatch_queue_main_t, _dispatch_main_q) #define DISPATCH_GLOBAL_OBJECT(type, object) ((type)&(object)) -
解析宏 DISPATCH_GLOBAL_OBJECT,重点放在_dispatch_main_q上 -
struct dispatch_queue_static_s _dispatch_main_q = { DISPATCH_GLOBAL_OBJECT_HEADER(queue_main), #if !DISPATCH_USE_RESOLVERS .do_targetq = _dispatch_get_default_queue(true), #endif .dq_state = DISPATCH_QUEUE_STATE_INIT_VALUE(1) | DISPATCH_QUEUE_ROLE_BASE_ANON, .dq_label = "com.apple.main-thread", .dq_atomic_flags = DQF_THREAD_BOUND | DQF_WIDTH(1), .dq_serialnum = 1, }; -
#define DISPATCH_GLOBAL_OBJECT_HEADER(name) \ .do_vtable = DISPATCH_VTABLE(name), \ .do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT, \ .do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT -
#define DISPATCH_VTABLE(name) DISPATCH_OBJC_CLASS(name) -
#define DISPATCH_OBJC_CLASS(name) (&DISPATCH_CLASS_SYMBOL(name)) -
#define DISPATCH_CLASS_SYMBOL(name) _dispatch_##name##_vtable 解析宏 DISPATCH_CLASS_SYMBOL 为 前缀部分(_dispatch_) + name部分(queue_main) + 后缀部分(vtable)根据层层宏嵌套,解析出
_dispatch_main_q结构 -
struct dispatch_queue_static_s _dispatch_main_q = { .do_vtable = _dispatch_queue_main_vtable, .do_ref_cnt = INT_MAX, .do_xref_cnt = INT_MAX #if !DISPATCH_USE_RESOLVERS .do_targetq = _dispatch_get_default_queue(true), #endif .dq_state = DISPATCH_QUEUE_STATE_INIT_VALUE(1) | DISPATCH_QUEUE_ROLE_BASE_ANON, .dq_label = "com.apple.main-thread", .dq_atomic_flags = DQF_THREAD_BOUND | DQF_WIDTH(1), .dq_serialnum = 1, };解析类型
dispatch_queue_static_s -
typedef struct dispatch_queue_static_s *dispatch_queue_main_t 10_1 struct dispatch_queue_static_s { struct dispatch_lane_s _as_dl[0]; DISPATCH_LANE_CLASS_HEADER(lane); } DISPATCH_CACHELINE_ALIGN; 10_2 #define DISPATCH_LANE_CLASS_HEADER(x) \ struct dispatch_queue_s _as_dq[0]; \ DISPATCH_QUEUE_CLASS_HEADER(x, \ struct dispatch_object_s *volatile dq_items_tail); \ dispatch_unfair_lock_s dq_sidelock; \ struct dispatch_object_s *volatile dq_items_head; \ uint32_t dq_side_suspend_cnt 10_3 struct dispatch_queue_s { DISPATCH_QUEUE_CLASS_HEADER(queue, void *__dq_opaque1); /* 32bit hole on LP64 */ } DISPATCH_ATOMIC64_ALIGN; 10_4 #define DISPATCH_QUEUE_CLASS_HEADER(x, __pointer_sized_field__) \ _DISPATCH_QUEUE_CLASS_HEADER(x, __pointer_sized_field__); \ /* LP64 global queue cacheline boundary */ \ unsigned long dq_serialnum; \ const char *dq_label; \ DISPATCH_UNION_LE(uint32_t volatile dq_atomic_flags, \ const uint16_t dq_width, \ const uint16_t __dq_opaque2 \ ); \ dispatch_priority_t dq_priority; \ union { \ struct dispatch_queue_specific_head_s *dq_specific_head; \ struct dispatch_source_refs_s *ds_refs; \ struct dispatch_timer_source_refs_s *ds_timer_refs; \ struct dispatch_mach_recv_refs_s *dm_recv_refs; \ struct dispatch_channel_callbacks_s const *dch_callbacks; \ }; \ int volatile dq_sref_cnt 10_5 #define _DISPATCH_QUEUE_CLASS_HEADER(x, __pointer_sized_field__) \ DISPATCH_OBJECT_HEADER(x); \ __pointer_sized_field__; \ DISPATCH_UNION_LE(uint64_t volatile dq_state, \ dispatch_lock dq_state_lock, \ uint32_t dq_state_bits \ ) 10_6 #define DISPATCH_OBJECT_HEADER(x) \ struct dispatch_object_s _as_do[0]; \ _DISPATCH_OBJECT_HEADER(x) 10_7 #define _DISPATCH_OBJECT_HEADER(x) \ struct _os_object_s _as_os_obj[0]; \ OS_OBJECT_STRUCT_HEADER(dispatch_##x); \ struct dispatch_##x##_s *volatile do_next; \ struct dispatch_queue_s *do_targetq; \ void *do_ctxt; \ union { \ dispatch_function_t DISPATCH_FUNCTION_POINTER do_finalizer; \ void *do_introspection_ctxt; \ } typedef void (*dispatch_function_t)(void * _Nullable); #if __has_feature(ptrauth_calls) //判断编译器是否支持指针身份验证功能 [使用Apple A12或更高版本A系列处理器的设备(如iPhone XS、iPhone XS Max和 iPhone XR或更新的设备)支持arm64e架构] #define DISPATCH_FUNCTION_POINTER \ __ptrauth(ptrauth_key_process_dependent_code, true, \ ptrauth_string_discriminator("dispatch.handler")) #else #define DISPATCH_FUNCTION_POINTER (空的宏定义 - 也就是占位为空) 10_8 #define OS_OBJECT_STRUCT_HEADER(x) \ _OS_OBJECT_HEADER(\ const struct x##_vtable_s *__ptrauth_objc_isa_pointer do_vtable, \ do_ref_cnt, \ do_xref_cnt) 10_9 #define _OS_OBJECT_HEADER(isa, ref_cnt, xref_cnt) \ isa; /* must be pointer-sized and use __ptrauth_objc_isa_pointer */ \ int volatile ref_cnt; \ int volatile xref_cnt -
from 10 描述的源码宏逻辑层层拆解 根据10_8 and 10_9 拆解得到 11_1 #define OS_OBJECT_STRUCT_HEADER(x) \ const struct x##_vtable_s *__ptrauth_objc_isa_pointer do_vtable; \ int volatile do_ref_cnt; \ int volatile do_xref_cnt) 从10_8 向上追踪 宏参数 x,发现 10_1-> dispatch_queue_static_s DISPATCH_LANE_CLASS_HEADER(dispatch_lane) x ------- lane 10_3-> DISPATCH_QUEUE_CLASS_HEADER(dispatch_queue, void *__dq_opaque1) x ------- queue 11_2 - 分析 继续11_1 得到 11_3 #define OS_OBJECT_STRUCT_HEADER(dispatch_lane) \ const struct dispatch_lane_vtable_s \ *__ptrauth_objc_isa_pointer do_vtable; \ int volatile do_ref_cnt; \ int volatile do_xref_cnt) #define OS_OBJECT_STRUCT_HEADER(dispatch_queue) \ const struct dispatch_queue_vtable_s \ *__ptrauth_objc_isa_pointer do_vtable; \ int volatile do_ref_cnt; \ int volatile do_xref_cnt) 11_4 拆解10_7 //#define _DISPATCH_OBJECT_HEADER(x) \ x: lane / queue #define _DISPATCH_OBJECT_HEADER(lane) \ struct _os_object_s _as_os_obj[0]; \ const struct dispatch_lane_vtable_s \ *__ptrauth_objc_isa_pointer do_vtable; \ int volatile do_ref_cnt; \ int volatile do_xref_cnt) \ struct dispatch_lane_s *volatile do_next; \ struct dispatch_queue_s *do_targetq; \ void *do_ctxt; \ union { \ void *do_finalizer; \ void *do_introspection_ctxt; \ } 11_5 拆解10_6 #define DISPATCH_OBJECT_HEADER(x) \ x: lane / queue struct dispatch_object_s _as_do[0]; \ struct _os_object_s _as_os_obj[0]; \ const struct dispatch_lane_vtable_s \ *__ptrauth_objc_isa_pointer do_vtable; \ int volatile do_ref_cnt; \ int volatile do_xref_cnt) \ struct dispatch_lane_s *volatile do_next; \ struct dispatch_queue_s *do_targetq; \ void *do_ctxt; \ union { \ void *do_finalizer; \ void *do_introspection_ctxt; \ } 11_6 拆解10_5 x: lane / queue #define _DISPATCH_QUEUE_CLASS_HEADER(x,__pointer_sized_field__)\ struct dispatch_object_s _as_do[0]; \ struct _os_object_s _as_os_obj[0]; \ const struct dispatch_lane_vtable_s \ *__ptrauth_objc_isa_pointer do_vtable; \ int volatile do_ref_cnt; \ int volatile do_xref_cnt) \ struct dispatch_lane_s *volatile do_next; \ struct dispatch_queue_s *do_targetq; \ void *do_ctxt; \ union { \ void *do_finalizer; \ void *do_introspection_ctxt; \ } \ __pointer_sized_field__; \ DISPATCH_UNION_LE(uint64_t volatile dq_state, \ dispatch_lock dq_state_lock, \ uint32_t dq_state_bits \ ) 11_7 拆解10_4 x: lane / queue #define DISPATCH_QUEUE_CLASS_HEADER(x, __pointer_sized_field__) \ struct dispatch_object_s _as_do[0]; \ struct _os_object_s _as_os_obj[0]; \ const struct dispatch_lane_vtable_s \ *__ptrauth_objc_isa_pointer do_vtable; \ int volatile do_ref_cnt; \ int volatile do_xref_cnt) \ struct dispatch_lane_s *volatile do_next; \ struct dispatch_queue_s *do_targetq; \ void *do_ctxt; \ union { \ void *do_finalizer; \ void *do_introspection_ctxt; \ } \ __pointer_sized_field__; \ DISPATCH_UNION_LE(uint64_t volatile dq_state, \ dispatch_lock dq_state_lock, \ uint32_t dq_state_bits \ ) /* LP64 global queue cacheline boundary */ \ unsigned long dq_serialnum; \ const char *dq_label; \ DISPATCH_UNION_LE(uint32_t volatile dq_atomic_flags, \ const uint16_t dq_width, \ const uint16_t __dq_opaque2 \ ); \ dispatch_priority_t dq_priority; \ union { \ struct dispatch_queue_specific_head_s *dq_specific_head; \ struct dispatch_source_refs_s *ds_refs; \ struct dispatch_timer_source_refs_s *ds_timer_refs; \ struct dispatch_mach_recv_refs_s *dm_recv_refs; \ struct dispatch_channel_callbacks_s const *dch_callbacks; \ }; \ int volatile dq_sref_cnt 11_8 拆解10_3 struct dispatch_queue_s { struct dispatch_object_s _as_do[0]; \ struct _os_object_s _as_os_obj[0]; \ const struct dispatch_queue_vtable_s \ *__ptrauth_objc_isa_pointer do_vtable; \ int volatile do_ref_cnt; \ int volatile do_xref_cnt) \ struct dispatch_queue_s *volatile do_next; \ struct dispatch_queue_s *do_targetq; \ void *do_ctxt; \ union { \ void *do_finalizer; \ void *do_introspection_ctxt; \ } \ void *__dq_opaque1; \ DISPATCH_UNION_LE(uint64_t volatile dq_state, \ dispatch_lock dq_state_lock, \ uint32_t dq_state_bits \ ) /* LP64 global queue cacheline boundary */ \ unsigned long dq_serialnum; \ const char *dq_label; \ DISPATCH_UNION_LE(uint32_t volatile dq_atomic_flags, \ const uint16_t dq_width, \ const uint16_t __dq_opaque2 \ ); \ dispatch_priority_t dq_priority; \ union { \ struct dispatch_queue_specific_head_s *dq_specific_head; \ struct dispatch_source_refs_s *ds_refs; \ struct dispatch_timer_source_refs_s *ds_timer_refs; \ struct dispatch_mach_recv_refs_s *dm_recv_refs; \ struct dispatch_channel_callbacks_s const *dch_callbacks; \ }; \ int volatile dq_sref_cnt; } DISPATCH_ATOMIC64_ALIGN; 11_9 拆解 10_2 10_1 struct dispatch_queue_static_s { struct dispatch_lane_s _as_dl[0]; \ struct dispatch_queue_s _as_dq[0]; \ struct dispatch_object_s _as_do[0]; \ struct _os_object_s _as_os_obj[0]; \ const struct dispatch_lane_vtable_s \ *__ptrauth_objc_isa_pointer do_vtable; \ int volatile do_ref_cnt; \ int volatile do_xref_cnt) \ struct dispatch_lane_s *volatile do_next; \ struct dispatch_queue_s *do_targetq; \ void *do_ctxt; \ union { \ void *do_finalizer; \ void *do_introspection_ctxt; \ } \ struct dispatch_object_s *volatile dq_items_tail; \ DISPATCH_UNION_LE(uint64_t volatile dq_state, \ dispatch_lock dq_state_lock, \ uint32_t dq_state_bits \ ) /* LP64 global queue cacheline boundary */ \ unsigned long dq_serialnum; \ const char *dq_label; \ DISPATCH_UNION_LE(uint32_t volatile dq_atomic_flags, \ const uint16_t dq_width, \ const uint16_t __dq_opaque2 \ ); \ dispatch_priority_t dq_priority; \ union { \ struct dispatch_queue_specific_head_s *dq_specific_head; \ struct dispatch_source_refs_s *ds_refs; \ struct dispatch_timer_source_refs_s *ds_timer_refs; \ struct dispatch_mach_recv_refs_s *dm_recv_refs; \ struct dispatch_channel_callbacks_s const *dch_callbacks; \ }; \ int volatile dq_sref_cnt; dispatch_unfair_lock_s dq_sidelock; \ struct dispatch_object_s *volatile dq_items_head; \ uint32_t dq_side_suspend_cnt; } DISPATCH_CACHELINE_ALIGN;
最终通过解析宏 得到
dispatch_queue_static_s完整类型结构 -
-
DQF_WIDTH
#define DQF_WIDTH(n) ((dispatch_queue_flags_t)(uint16_t)(n))
DQF_WIDTH(1) -
0x00000001(32位 16进制形式) -
DQF_THREAD_BOUND
对于
_dispatch_main_q结构中出现的DQF_THREAD_BOUND甚是耿耿于怀源码中查找,出现在
DISPATCH_OPTIONS(dispatch_queue_flags, uint32_t, ....)结构里#define DISPATCH_OPTIONS(name, type, ...) \ typedef enum : type { __VA_ARGS__ } __DISPATCH_OPTIONS_ATTR \ __DISPATCH_ENUM_ATTR name##_tVA_ARGS 表示可变参数的宏,用来替换 ...代表的可变参数
解析
DISPATCH_OPTIONS(name, type, ...)得到typedef uint32_t dispatch_queue_flags_t enum : dispatch_queue_flags_t { DQF_NONE = 0x00000000, DQF_AUTORELEASE_ALWAYS = 0x00010000, DQF_AUTORELEASE_NEVER = 0x00020000, DQF_THREAD_BOUND = 0x00040000, // queue is bound to a thread DQF_BARRIER_BIT = 0x00080000, // queue is a barrier on its target DQF_TARGETED = 0x00100000, // queue is targeted by another object DQF_LABEL_NEEDS_FREE = 0x00200000, // queue label was strdup()ed DQF_MUTABLE = 0x00400000, DQF_RELEASED = 0x00800000, // xref_cnt == -1 DSF_STRICT = 0x04000000, DSF_WLH_CHANGED = 0x08000000, DSF_CANCELED = 0x10000000, DSF_CANCEL_WAITER = 0x20000000, DSF_NEEDS_EVENT = 0x40000000, DSF_DELETED = 0x80000000, }DQF_THREAD_BOUND- 标识为 0x00040000,表示队列绑定到一个线程DQF_THREAD_BOUND | DQF_WIDTH(1) 就是 0x00040000 | 0x00000001 = 0x00040001_dispatch_main_q.
dq_atomic_flags= 0x00040001, 高16位标识flag, 低16位标识 DQF_WIDTH, 至于 DQF_WIDTH什么含义,且往继续看分析过程,暂不表 -
dispatch_queue_flags_t
dispatch_queue_flags_t 通过拆解宏得到,分析源码过程中,经常会碰到令人厌烦的宏, 不做到耐心有细,分析思路就此中断,文章到此也就结束了
如果搞不清楚一个研究对象的
基本数据类型,后面 堆积起来的所有理解就不踏实,分析思路是离散化的,面对抽象的底层代码,终不得其正解-
DQF_NONE = 0x00000000
-
DQF_AUTORELEASE_ALWAYS = 0x00010000
-
DQF_AUTORELEASE_NEVER = 0x00020000
32位16进制结构, 16~17 两位表示 (第一位从0开始) autorelease标识(0-none, 1-always autorelease, 2-never autorelease) dispatch_queue_flags_t & _DQF_AUTORELEASE_MASK(0x00030000) 得到标识 -
DQF_THREAD_BOUND= 0x00040000队列绑定到一个线程 -
DQF_BARRIER_BIT 第19位, // queue is a barrier on its target
-
DQF_TARGETED 第20位, // queue is targeted by another object
-
DQF_LABEL_NEEDS_FREE 第21位, // queue label was strdup()ed
DQF_BARRIER_BIT DQF_TARGETED DQF_LABEL_NEEDS_FREE 具体含义暂不表 -
DSF_STRICT // 第26位
一旦设定,严格遵守语义,handlers(处理程序)不能随便更改已激活的状态机状态 -
DSF_WLH_CHANGED // 第27位
只能作为调试分析标识用 -
DSF_CANCELED // 第28位
要求取消,发出请求 -
DSF_CANCEL_WAITER // 第29位
至少有一个 dispatch_source_cancel_and_wait() 等待取消完成,此之前一定 已经设置了标识 DSF_CANCELED -
DSF_NEEDS_EVENT // 第30位
状态机需要特定的事件才能唤醒,此标识可以防止一些乱七八糟的虚假wakeups 可能解除状态机阻塞的事件传递 DISPATCH_WAKEUP_EVENT, 消除 DSF_NEEDS_EVENT 影响 -
DSF_DELETED // 第31位
标识不再允许注册新的unote,之前已经注册的unotes失活,但是之前已经注册过的 unotes可能还处在正交付最后一个事件的过程中, 直到结束
-
全局队列 - com.apple.root.default-qos
- 全局队列溯源 - dispatch_get_global_queue(intptr_t identifier, uintptr_t flags)
-
dispatch_queue_global_t dispatch_get_global_queue(intptr_t priority, uintptr_t flags) { dispatch_assert(countof(_dispatch_root_queues) == DISPATCH_ROOT_QUEUE_COUNT); \ if (flags & ~(unsigned long)DISPATCH_QUEUE_OVERCOMMIT) { return DISPATCH_BAD_INPUT; } dispatch_qos_t qos = _dispatch_qos_from_queue_priority(priority); #if !HAVE_PTHREAD_WORKQUEUE_QOS if (qos == QOS_CLASS_MAINTENANCE) { qos = DISPATCH_QOS_BACKGROUND; } else if (qos == QOS_CLASS_USER_INTERACTIVE) { qos = DISPATCH_QOS_USER_INITIATED; } #endif if (qos == DISPATCH_QOS_UNSPECIFIED) { return DISPATCH_BAD_INPUT; } return _dispatch_get_root_queue(qos, flags & DISPATCH_QUEUE_OVERCOMMIT); } -
static inline dispatch_queue_global_t _dispatch_get_root_queue(dispatch_qos_t qos, bool overcommit) { if (unlikely(qos < DISPATCH_QOS_MIN || qos > DISPATCH_QOS_MAX)) { DISPATCH_CLIENT_CRASH(qos, "Corrupted priority"); } return &_dispatch_root_queues[2 * (qos - 1) + overcommit]; } -
struct dispatch_queue_global_s _dispatch_root_queues[] = { #define _DISPATCH_ROOT_QUEUE_IDX(n, flags) \ ((flags & DISPATCH_PRIORITY_FLAG_OVERCOMMIT) ? \ DISPATCH_ROOT_QUEUE_IDX_##n##_QOS_OVERCOMMIT : \ DISPATCH_ROOT_QUEUE_IDX_##n##_QOS) #define _DISPATCH_ROOT_QUEUE_ENTRY(n, flags, ...) \ [_DISPATCH_ROOT_QUEUE_IDX(n, flags)] = { \ DISPATCH_GLOBAL_OBJECT_HEADER(queue_global), \ .dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \ .do_ctxt = _dispatch_root_queue_ctxt(_DISPATCH_ROOT_QUEUE_IDX(n, flags)), \ .dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \ .dq_priority = flags | ((flags & DISPATCH_PRIORITY_FLAG_FALLBACK) ? \ _dispatch_priority_make_fallback(DISPATCH_QOS_##n) : \ _dispatch_priority_make(DISPATCH_QOS_##n, 0)), \ __VA_ARGS__ \ } _DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, 0, .dq_label = "com.apple.root.maintenance-qos", .dq_serialnum = 4, ), _DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.maintenance-qos.overcommit", .dq_serialnum = 5, ), _DISPATCH_ROOT_QUEUE_ENTRY(BACKGROUND, 0, .dq_label = "com.apple.root.background-qos", .dq_serialnum = 6, ), _DISPATCH_ROOT_QUEUE_ENTRY(BACKGROUND, DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.background-qos.overcommit", .dq_serialnum = 7, ), _DISPATCH_ROOT_QUEUE_ENTRY(UTILITY, 0, .dq_label = "com.apple.root.utility-qos", .dq_serialnum = 8, ), _DISPATCH_ROOT_QUEUE_ENTRY(UTILITY, DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.utility-qos.overcommit", .dq_serialnum = 9, ), _DISPATCH_ROOT_QUEUE_ENTRY(DEFAULT, DISPATCH_PRIORITY_FLAG_FALLBACK, .dq_label = "com.apple.root.default-qos", .dq_serialnum = 10, ), _DISPATCH_ROOT_QUEUE_ENTRY(DEFAULT, DISPATCH_PRIORITY_FLAG_FALLBACK | DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.default-qos.overcommit", .dq_serialnum = 11, ), _DISPATCH_ROOT_QUEUE_ENTRY(USER_INITIATED, 0, .dq_label = "com.apple.root.user-initiated-qos", .dq_serialnum = 12, ), _DISPATCH_ROOT_QUEUE_ENTRY(USER_INITIATED, DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.user-initiated-qos.overcommit", .dq_serialnum = 13, ), _DISPATCH_ROOT_QUEUE_ENTRY(USER_INTERACTIVE, 0, .dq_label = "com.apple.root.user-interactive-qos", .dq_serialnum = 14, ), _DISPATCH_ROOT_QUEUE_ENTRY(USER_INTERACTIVE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.user-interactive-qos.overcommit", .dq_serialnum = 15, ), }; -
_dispatch_root_queues结构中又出现了宏 _DISPATCH_ROOT_QUEUE_IDX _DISPATCH_ROOT_QUEUE_ENTRY DISPATCH_GLOBAL_OBJECT_HEADER .... -
#define DISPATCH_GLOBAL_OBJECT_HEADER(name) \ .do_vtable = DISPATCH_VTABLE(name), \ .do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT, \ .do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT #define DISPATCH_VTABLE(name) DISPATCH_OBJC_CLASS(name) #define DISPATCH_OBJC_CLASS(name) (&DISPATCH_CLASS_SYMBOL(name)) #define DISPATCH_CLASS_SYMBOL(name) _dispatch_##name##_vtable 解析宏 DISPATCH_CLASS_SYMBOL 为 前缀部分(_dispatch_) + name部分(queue_global) + 后缀部分(vtable) 解析其中一个 _DISPATCH_ROOT_QUEUE_ENTRY 结构 _DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.maintenance-qos.overcommit", .dq_serialnum = 5, ), #define _DISPATCH_ROOT_QUEUE_IDX(MAINTENANCE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT) \ ((DISPATCH_PRIORITY_FLAG_OVERCOMMIT & DISPATCH_PRIORITY_FLAG_OVERCOMMIT) ? \ DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT : \ DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS) #define _DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT, ...) \ [_DISPATCH_ROOT_QUEUE_IDX(MAINTENANCE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT)] = { \ .do_vtable = _dispatch_queue_global_vtable, .do_ref_cnt = INT_MAX, .do_xref_cnt = INT_MAX .dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \ .do_ctxt = _dispatch_root_queue_ctxt(_DISPATCH_ROOT_QUEUE_IDX( MAINTENANCE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT)), \ .dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \ .dq_priority = DISPATCH_PRIORITY_FLAG_OVERCOMMIT | (( DISPATCH_PRIORITY_FLAG_OVERCOMMIT & DISPATCH_PRIORITY_FLAG_FALLBACK) ? \ _dispatch_priority_make_fallback(DISPATCH_QOS_MAINTENANCE) : \ _dispatch_priority_make(DISPATCH_QOS_MAINTENANCE, 0)), \ .dq_label = "com.apple.root.maintenance-qos.overcommit", \ .dq_serialnum = 5, \ } 解析 _DISPATCH_ROOT_QUEUE_IDX(MAINTENANCE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT) 得到一个entry结构 [DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT] = { \ .do_vtable = _dispatch_queue_global_vtable, .do_ref_cnt = INT_MAX, .do_xref_cnt = INT_MAX .dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \ .do_ctxt = _dispatch_root_queue_ctxt( DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT), \ .dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \ .dq_priority = DISPATCH_PRIORITY_FLAG_OVERCOMMIT | (_dispatch_priority_make(DISPATCH_QOS_MAINTENANCE, 0), \ .dq_label = "com.apple.root.maintenance-qos.overcommit", \ .dq_serialnum = 5, \ } #define _dispatch_priority_make(qos, relpri) \ (qos ? ((((qos) << DISPATCH_PRIORITY_QOS_SHIFT) & DISPATCH_PRIORITY_QOS_MASK) | \ ((dispatch_priority_t)(relpri - 1) & DISPATCH_PRIORITY_RELPRI_MASK)) : 0) #define _dispatch_priority_make(DISPATCH_QOS_MAINTENANCE, 0) \ (DISPATCH_QOS_MAINTENANCE ? ((((DISPATCH_QOS_MAINTENANCE) << DISPATCH_PRIORITY_QOS_SHIFT) & DISPATCH_PRIORITY_QOS_MASK) | \ ((dispatch_priority_t)(0 - 1) & DISPATCH_PRIORITY_RELPRI_MASK)) : 0) #define _dispatch_priority_make(DISPATCH_QOS_MAINTENANCE, 0) \ (DISPATCH_QOS_MAINTENANCE ? (((1 << 8) & 0x00000f00) | \ ((dispatch_priority_t)(0 - 1) & DISPATCH_PRIORITY_RELPRI_MASK)) : 0) #define _dispatch_priority_make(DISPATCH_QOS_MAINTENANCE, 0) \ (DISPATCH_QOS_MAINTENANCE ? (0x00000100 | \ ((dispatch_priority_t)(0 - 1) & 0x000000ff)) : 0) #define _dispatch_priority_make(DISPATCH_QOS_MAINTENANCE, 0) \ (DISPATCH_QOS_MAINTENANCE ? 0x000001ff : 0) _dispatch_priority_make 解出结果 --- 0x000001ff [DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT] = { \ .do_vtable = _dispatch_queue_global_vtable, .do_ref_cnt = INT_MAX, .do_xref_cnt = INT_MAX .dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \ .do_ctxt = _dispatch_root_queue_ctxt( DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT), \ .dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \ .dq_priority = DISPATCH_PRIORITY_FLAG_OVERCOMMIT | 0x000001ff, \ .dq_label = "com.apple.root.maintenance-qos.overcommit", \ .dq_serialnum = 5, \ } [DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT] = { \ .do_vtable = _dispatch_queue_global_vtable, .do_ref_cnt = INT_MAX, .do_xref_cnt = INT_MAX .dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \ .do_ctxt = _dispatch_root_queue_ctxt( DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT), \ .dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \ .dq_priority = 0x800001ff, \ .dq_label = "com.apple.root.maintenance-qos.overcommit", \ .dq_serialnum = 5, \ }
串行队列
- 队列溯源 - ifl_queue_serial -
-
根据源码中的宏解析 dispatch_lane_t typedef struct dispatch_lane_s *dispatch_queue_serial_t; typedef struct dispatch_lane_s *dispatch_queue_concurrent_t; typedef struct dispatch_lane_s { struct dispatch_queue_s _as_dq[0]; \ struct dispatch_object_s _as_do[0]; \ struct _os_object_s _as_os_obj[0]; \ const struct dispatch_lane_vtable_s \ *__ptrauth_objc_isa_pointer do_vtable; \ int volatile do_ref_cnt; \ int volatile do_xref_cnt) \ struct dispatch_lane_s *volatile do_next; \ struct dispatch_queue_s *do_targetq; \ void *do_ctxt; \ union { \ void *do_finalizer; \ void *do_introspection_ctxt; \ } \ struct dispatch_object_s *volatile dq_items_tail; \ DISPATCH_UNION_LE(uint64_t volatile dq_state, \ dispatch_lock dq_state_lock, \ uint32_t dq_state_bits \ ) /* LP64 global queue cacheline boundary */ \ unsigned long dq_serialnum; \ const char *dq_label; \ DISPATCH_UNION_LE(uint32_t volatile dq_atomic_flags, \ const uint16_t dq_width, \ const uint16_t __dq_opaque2 \ ); \ dispatch_priority_t dq_priority; \ union { \ struct dispatch_queue_specific_head_s *dq_specific_head; \ struct dispatch_source_refs_s *ds_refs; \ struct dispatch_timer_source_refs_s *ds_timer_refs; \ struct dispatch_mach_recv_refs_s *dm_recv_refs; \ struct dispatch_channel_callbacks_s const *dch_callbacks; \ }; \ int volatile dq_sref_cnt; dispatch_unfair_lock_s dq_sidelock; \ struct dispatch_object_s *volatile dq_items_head; \ uint32_t dq_side_suspend_cnt } DISPATCH_ATOMIC64_ALIGN *dispatch_lane_t; typedef struct dispatch_queue_s *dispatch_queue_t; struct dispatch_queue_s { struct dispatch_object_s _as_do[0]; \ struct _os_object_s _as_os_obj[0]; \ const struct dispatch_queue_vtable_s \ *__ptrauth_objc_isa_pointer do_vtable; \ int volatile do_ref_cnt; \ int volatile do_xref_cnt) \ struct dispatch_queue_s *volatile do_next; \ struct dispatch_queue_s *do_targetq; \ void *do_ctxt; \ union { \ void *do_finalizer; \ void *do_introspection_ctxt; \ } \ void *__dq_opaque1; \ DISPATCH_UNION_LE(uint64_t volatile dq_state, \ dispatch_lock dq_state_lock, \ uint32_t dq_state_bits \ ) /* LP64 global queue cacheline boundary */ \ unsigned long dq_serialnum; \ const char *dq_label; \ DISPATCH_UNION_LE(uint32_t volatile dq_atomic_flags, \ const uint16_t dq_width, \ const uint16_t __dq_opaque2 \ ); \ dispatch_priority_t dq_priority; \ union { \ struct dispatch_queue_specific_head_s *dq_specific_head; \ struct dispatch_source_refs_s *ds_refs; \ struct dispatch_timer_source_refs_s *ds_timer_refs; \ struct dispatch_mach_recv_refs_s *dm_recv_refs; \ struct dispatch_channel_callbacks_s const *dch_callbacks; \ }; \ int volatile dq_sref_cnt; } DISPATCH_ATOMIC64_ALIGN; typedef union { struct _os_object_s *_os_obj; struct dispatch_object_s *_do; struct dispatch_queue_s *_dq; struct dispatch_queue_attr_s *_dqa; struct dispatch_group_s *_dg; struct dispatch_source_s *_ds; struct dispatch_channel_s *_dch; struct dispatch_mach_s *_dm; struct dispatch_mach_msg_s *_dmsg; struct dispatch_semaphore_s *_dsema; struct dispatch_data_s *_ddata; struct dispatch_io_s *_dchannel; } dispatch_object_t DISPATCH_TRANSPARENT_UNION; typedef struct dispatch_continuation_s { DISPATCH_CONTINUATION_HEADER(continuation); } *dispatch_continuation_t; typedef struct dispatch_continuation_s { union { \ const void *__ptrauth_objc_isa_pointer do_vtable; \ uintptr_t dc_flags; \ }; \ union { \ pthread_priority_t dc_priority; \ int dc_cache_cnt; \ uintptr_t dc_pad; \ }; \ struct voucher_s *dc_voucher; \ struct dispatch_continuation_s *volatile do_next; \ dispatch_function_t dc_func; \ void *dc_ctxt; \ void *dc_data; \ void *dc_other } *dispatch_continuation_t; -
dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr) _dispatch_lane_create_with_target(label, attr, DISPATCH_TARGET_QUEUE_DEFAULT, true) static dispatch_queue_t _dispatch_lane_create_with_target(const char *label, dispatch_queue_attr_t dqa, dispatch_queue_t tq, bool legacy) { /* typedef struct dispatch_queue_attr_info_s { dispatch_qos_t dqai_qos : 8; int dqai_relpri : 8; uint16_t dqai_overcommit:2; uint16_t dqai_autorelease_frequency:2; uint16_t dqai_concurrent:1; uint16_t dqai_inactive:1; } dispatch_queue_attr_info_t; */ dispatch_queue_attr_info_t dqai = _dispatch_queue_attr_to_info(dqa); \ // // Step 1: Normalize arguments (qos, overcommit, tq) // \ // dqai_qos -- typedef uint32_t dispatch_qos_t dispatch_qos_t qos = dqai.dqai_qos; // #if !HAVE_PTHREAD_WORKQUEUE_QOS if (qos == DISPATCH_QOS_USER_INTERACTIVE) { dqai.dqai_qos = qos = DISPATCH_QOS_USER_INITIATED; } if (qos == DISPATCH_QOS_MAINTENANCE) { dqai.dqai_qos = qos = DISPATCH_QOS_BACKGROUND; } #endif // !HAVE_PTHREAD_WORKQUEUE_QOS \ _dispatch_queue_attr_overcommit_t overcommit = dqai.dqai_overcommit; if (overcommit != _dispatch_queue_attr_overcommit_unspecified && tq) { if (tq->do_targetq) { DISPATCH_CLIENT_CRASH(tq, "Cannot specify both overcommit and " "a non-global target queue"); } } \ if (tq && dx_type(tq) == DISPATCH_QUEUE_GLOBAL_ROOT_TYPE) { // Handle discrepancies between attr and target queue, attributes win if (overcommit == _dispatch_queue_attr_overcommit_unspecified) { if (tq->dq_priority & DISPATCH_PRIORITY_FLAG_OVERCOMMIT) { overcommit = _dispatch_queue_attr_overcommit_enabled; } else { overcommit = _dispatch_queue_attr_overcommit_disabled; } } if (qos == DISPATCH_QOS_UNSPECIFIED) { qos = _dispatch_priority_qos(tq->dq_priority); } tq = NULL; } else if (tq && !tq->do_targetq) { // target is a pthread or runloop root queue, setting QoS or overcommit // is disallowed if (overcommit != _dispatch_queue_attr_overcommit_unspecified) { DISPATCH_CLIENT_CRASH(tq, "Cannot specify an overcommit attribute " "and use this kind of target queue"); } } else { if (overcommit == _dispatch_queue_attr_overcommit_unspecified) { // Serial queues default to overcommit! overcommit = dqai.dqai_concurrent ? _dispatch_queue_attr_overcommit_disabled : _dispatch_queue_attr_overcommit_enabled; } } if (!tq) { tq = _dispatch_get_root_queue( qos == DISPATCH_QOS_UNSPECIFIED ? DISPATCH_QOS_DEFAULT : qos, overcommit == _dispatch_queue_attr_overcommit_enabled)->_as_dq; if (unlikely(!tq)) { DISPATCH_CLIENT_CRASH(qos, "Invalid queue attribute"); } } \ // // Step 2: Initialize the queue // \ if (legacy) { // if any of these attributes is specified, use non legacy classes if (dqai.dqai_inactive || dqai.dqai_autorelease_frequency) { legacy = false; } } \ const void *vtable; dispatch_queue_flags_t dqf = legacy ? DQF_MUTABLE : 0; if (dqai.dqai_concurrent) { vtable = DISPATCH_VTABLE(queue_concurrent); } else { vtable = DISPATCH_VTABLE(queue_serial); } switch (dqai.dqai_autorelease_frequency) { case DISPATCH_AUTORELEASE_FREQUENCY_NEVER: dqf |= DQF_AUTORELEASE_NEVER; break; case DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM: dqf |= DQF_AUTORELEASE_ALWAYS; break; } if (label) { const char *tmp = _dispatch_strdup_if_mutable(label); if (tmp != label) { dqf |= DQF_LABEL_NEEDS_FREE; label = tmp; } } \ dispatch_lane_t dq = _dispatch_object_alloc(vtable, sizeof(struct dispatch_lane_s)); _dispatch_queue_init(dq, dqf, dqai.dqai_concurrent ? DISPATCH_QUEUE_WIDTH_MAX : 1, DISPATCH_QUEUE_ROLE_INNER | (dqai.dqai_inactive ? DISPATCH_QUEUE_INACTIVE : 0)); \ dq->dq_label = label; dq->dq_priority = _dispatch_priority_make((dispatch_qos_t)dqai.dqai_qos, dqai.dqai_relpri); if (overcommit == _dispatch_queue_attr_overcommit_enabled) { dq->dq_priority |= DISPATCH_PRIORITY_FLAG_OVERCOMMIT; } if (!dqai.dqai_inactive) { _dispatch_queue_priority_inherit_from_target(dq, tq); _dispatch_lane_inherit_wlh_from_target(dq, tq); } _dispatch_retain(tq); dq->do_targetq = tq; _dispatch_object_debug(dq, "%s", __func__); return _dispatch_trace_queue_create(dq)._dq; }