size_t _dispatch_source_debug(dispatch_source_t ds, char* buf, size_t bufsiz) { size_t offset = 0; offset += snprintf(&buf[offset], bufsiz - offset, "%s[%p] = { ", dx_kind(ds), ds); offset += dispatch_object_debug_attr(as_do(ds), &buf[offset], bufsiz - offset); offset += dispatch_source_debug_attr(ds, &buf[offset], bufsiz - offset); return offset; }
size_t _dispatch_semaphore_debug(dispatch_object_t dou, char *buf, size_t bufsiz) { dispatch_semaphore_t dsema = dou._dsema; size_t offset = 0; offset += snprintf(&buf[offset], bufsiz - offset, "%s[%p] = { ", dx_kind(dsema), dsema); offset += _dispatch_object_debug_attr(dsema, &buf[offset], bufsiz - offset); #if USE_MACH_SEM offset += snprintf(&buf[offset], bufsiz - offset, "port = 0x%u, ", dsema->dsema_port); #endif offset += snprintf(&buf[offset], bufsiz - offset, "value = %ld, orig = %ld }", dsema->dsema_value, dsema->dsema_orig); return offset; }
static inline dispatch_introspection_queue_function_s _dispatch_introspection_continuation_get_info(dispatch_queue_t dq, dispatch_continuation_t dc, unsigned long *type) { void *ctxt = dc->dc_ctxt; dispatch_function_t func = dc->dc_func; pthread_t waiter = NULL; bool apply = false; long flags = (long)dc->do_vtable; if (flags & DISPATCH_OBJ_SYNC_SLOW_BIT) { waiter = pthread_from_mach_thread_np((mach_port_t)dc->dc_data); if (flags & DISPATCH_OBJ_BARRIER_BIT) { dc = dc->dc_ctxt; dq = dc->dc_data; } ctxt = dc->dc_ctxt; func = dc->dc_func; } if (func == _dispatch_sync_recurse_invoke) { dc = dc->dc_ctxt; dq = dc->dc_data; ctxt = dc->dc_ctxt; func = dc->dc_func; } else if (func == _dispatch_async_redirect_invoke) { dq = dc->dc_data; dc = dc->dc_other; ctxt = dc->dc_ctxt; func = dc->dc_func; flags = (long)dc->do_vtable; } else if (func == _dispatch_mach_barrier_invoke) { dq = dq->do_targetq; ctxt = dc->dc_data; func = dc->dc_other; } else if (func == _dispatch_apply_invoke || func == _dispatch_apply_redirect_invoke) { dispatch_apply_t da = ctxt; if (da->da_todo) { dc = da->da_dc; if (func == _dispatch_apply_redirect_invoke) { dq = dc->dc_data; } ctxt = dc->dc_ctxt; func = dc->dc_func; apply = true; } } if (func == _dispatch_call_block_and_release) { *type = dispatch_introspection_queue_item_type_block; func = _dispatch_Block_invoke(ctxt); } else { *type = dispatch_introspection_queue_item_type_function; } dispatch_introspection_queue_function_s diqf= { .continuation = dc, .target_queue = dq, .context = ctxt, .function = func, .group = flags & DISPATCH_OBJ_GROUP_BIT ? dc->dc_data : NULL, .waiter = waiter, .barrier = flags & DISPATCH_OBJ_BARRIER_BIT, .sync = flags & DISPATCH_OBJ_SYNC_SLOW_BIT, .apply = apply, }; return diqf; } static inline dispatch_introspection_object_s _dispatch_introspection_object_get_info(dispatch_object_t dou) { dispatch_introspection_object_s dio = { .object = dou._dc, .target_queue = dou._do->do_targetq, .type = (void*)dou._do->do_vtable, .kind = dx_kind(dou._do), }; return dio; } DISPATCH_USED inline dispatch_introspection_queue_s dispatch_introspection_queue_get_info(dispatch_queue_t dq) { bool global = (dq->do_xref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) || (dq->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT); uint16_t width = dq->dq_width; if (width > 1 && width != DISPATCH_QUEUE_WIDTH_MAX) width /= 2; dispatch_introspection_queue_s diq = { .queue = dq, .target_queue = dq->do_targetq, .label = dq->dq_label, .serialnum = dq->dq_serialnum, .width = width, .suspend_count = dq->do_suspend_cnt / 2, .enqueued = (dq->do_suspend_cnt & 1) && !global, .barrier = (dq->dq_running & 1) && !global, .draining = (dq->dq_items_head == (void*)~0ul) || (!dq->dq_items_head && dq->dq_items_tail), .global = global, .main = (dq == &_dispatch_main_q), }; return diq; } static inline dispatch_introspection_source_s _dispatch_introspection_source_get_info(dispatch_source_t ds) { dispatch_source_refs_t dr = ds->ds_refs; dispatch_continuation_t dc = dr->ds_handler[DS_EVENT_HANDLER]; void *ctxt = NULL; dispatch_function_t handler = NULL; bool hdlr_is_block = false; if (dc) { ctxt = dc->dc_ctxt; handler = dc->dc_func; hdlr_is_block = ((long)dc->do_vtable & DISPATCH_OBJ_BLOCK_RELEASE_BIT); } bool after = (handler == _dispatch_after_timer_callback); if (after && !(ds->ds_atomic_flags & DSF_CANCELED)) { dc = ctxt; ctxt = dc->dc_ctxt; handler = dc->dc_func; hdlr_is_block = (handler == _dispatch_call_block_and_release); if (hdlr_is_block) { handler = _dispatch_Block_invoke(ctxt); } } dispatch_introspection_source_s dis = { .source = ds, .target_queue = ds->do_targetq, .type = ds->ds_dkev ? (unsigned long)ds->ds_dkev->dk_kevent.filter : 0, .handle = ds->ds_dkev ? (unsigned long)ds->ds_dkev->dk_kevent.ident : 0, .context = ctxt, .handler = handler, .suspend_count = ds->do_suspend_cnt / 2, .enqueued = (ds->do_suspend_cnt & 1), .handler_is_block = hdlr_is_block, .timer = ds->ds_is_timer, .after = after, }; return dis; } static inline dispatch_introspection_queue_thread_s _dispatch_introspection_thread_get_info(dispatch_introspection_thread_t dit) { dispatch_introspection_queue_thread_s diqt = { .object = (void*)dit, .thread = dit->thread, }; if (dit->queue && *dit->queue) { diqt.queue = dispatch_introspection_queue_get_info(*dit->queue); } return diqt; } DISPATCH_USED inline dispatch_introspection_queue_item_s dispatch_introspection_queue_item_get_info(dispatch_queue_t dq, dispatch_continuation_t dc) { dispatch_introspection_queue_item_s diqi; if (DISPATCH_OBJ_IS_VTABLE(dc)) { dispatch_object_t dou = (dispatch_object_t)dc; unsigned long type = dx_type(dou._do); unsigned long metatype = type & _DISPATCH_META_TYPE_MASK; if (metatype == _DISPATCH_QUEUE_TYPE && type != DISPATCH_QUEUE_SPECIFIC_TYPE) { diqi.type = dispatch_introspection_queue_item_type_queue; diqi.queue = dispatch_introspection_queue_get_info(dou._dq); } else if (metatype == _DISPATCH_SOURCE_TYPE && type != DISPATCH_MACH_CHANNEL_TYPE) { diqi.type = dispatch_introspection_queue_item_type_source; diqi.source = _dispatch_introspection_source_get_info(dou._ds); } else { diqi.type = dispatch_introspection_queue_item_type_object; diqi.object = _dispatch_introspection_object_get_info(dou._do); } } else { diqi.function = _dispatch_introspection_continuation_get_info(dq, dc, &diqi.type); } return diqi; }