/* * Copyright (c) 2012-2013 Apple Inc. All rights reserved. * * @APPLE_APACHE_LICENSE_HEADER_START@ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * @APPLE_APACHE_LICENSE_HEADER_END@ */ /* * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch * which are subject to change in future releases of Mac OS X. Any applications * relying on these interfaces WILL break. */ #ifndef __DISPATCH_INTROSPECTION_PRIVATE__ #define __DISPATCH_INTROSPECTION_PRIVATE__ /*! * @header * * @abstract * Introspection SPI for libdispatch. * * @discussion * This SPI is only available in the introspection version of the library, * loaded by running a process with the environment variable * DYLD_LIBRARY_PATH=/usr/lib/system/introspection * * NOTE: most of these functions are _not_ exported from the shared library, * the unexported functions are intended to only be called from a debugger * context while the rest of the process is suspended. */ #ifndef __BEGIN_DECLS #if defined(__cplusplus) #define __BEGIN_DECLS extern "C" { #define __END_DECLS } #else #define __BEGIN_DECLS #define __END_DECLS #endif #endif __BEGIN_DECLS #ifndef __DISPATCH_INDIRECT__ /* * Typedefs of opaque types, for direct inclusion of header in lldb expressions */ typedef __typeof__(sizeof(int)) size_t; typedef struct _opaque_pthread_t *pthread_t; typedef void (*dispatch_function_t)(void *); typedef struct Block_layout *dispatch_block_t; typedef struct dispatch_continuation_s *dispatch_continuation_t; typedef struct dispatch_queue_s *dispatch_queue_t; typedef struct dispatch_source_s *dispatch_source_t; typedef struct dispatch_group_s *dispatch_group_t; typedef struct dispatch_object_s *dispatch_object_t; #ifndef __OSX_AVAILABLE_STARTING #define __OSX_AVAILABLE_STARTING(x,y) #endif #ifndef DISPATCH_EXPORT #define DISPATCH_EXPORT extern #endif #endif // __DISPATCH_INDIRECT__ /*! * @typedef dispatch_introspection_versions_s * * @abstract * A structure of version and size information of introspection structures. * * @field introspection_version * Version of overall dispatch_introspection SPI. * * @field hooks_version * Version of dispatch_introspection_hooks_s structure. * Version 2 adds the queue_item_complete member. * * @field hooks_size * Size of dispatch_introspection_hooks_s structure. * * @field queue_item_version * Version of dispatch_introspection_queue_item_s structure. * * @field queue_item_size * Size of dispatch_introspection_queue_item_s structure. * * @field queue_block_version * Version of dispatch_introspection_queue_block_s structure. * * @field queue_block_size * Size of dispatch_introspection_queue_block_s structure. * * @field queue_function_version * Version of dispatch_introspection_queue_function_s structure. * * @field queue_function_size * Size of dispatch_introspection_queue_function_s structure. * * @field queue_thread_version * Version of dispatch_introspection_queue_thread_s structure. * * @field queue_thread_size * Size of dispatch_introspection_queue_thread_s structure. * * @field object_version * Version of dispatch_introspection_object_s structure. * * @field object_size * Size of dispatch_introspection_object_s structure. * * @field queue_version * Version of dispatch_introspection_queue_s structure. * * @field queue_size * Size of dispatch_introspection_queue_s structure. * * @field source_version * Version of dispatch_introspection_source_s structure. * * @field source_size * Size of dispatch_introspection_source_s structure. */ __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0) DISPATCH_EXPORT const struct dispatch_introspection_versions_s { unsigned long introspection_version; unsigned long hooks_version; size_t hooks_size; unsigned long queue_item_version; size_t queue_item_size; unsigned long queue_block_version; size_t queue_block_size; unsigned long queue_function_version; size_t queue_function_size; unsigned long queue_thread_version; size_t queue_thread_size; unsigned long object_version; size_t object_size; unsigned long queue_version; size_t queue_size; unsigned long source_version; size_t source_size; } dispatch_introspection_versions; /*! * @typedef dispatch_introspection_queue_block_s * * @abstract * A structure of introspection information for a block item enqueued on a * dispatch queue. * * @field continuation * Pointer to enqueued item. * * @field target_queue * Target queue of item (may be different to the queue the item is currently * enqueued on). * * @field block * Block for enqueued item. * * @field block_invoke * Function pointer of block for enqueued item. * * @field group * Group containing enqueued item (may be NULL). * * @field waiter * Thread waiting for completion of enqueued item (NULL if sync == 0). * * @field barrier * Item is a barrier on the queue (all items on serial queues are barriers). * * @field sync * Item was enqueued by a dispatch_sync/dispatch_barrier_sync. * * @field apply * Item is part of a dispatch_apply. */ typedef struct dispatch_introspection_queue_block_s { dispatch_continuation_t continuation; dispatch_queue_t target_queue; dispatch_block_t block; dispatch_function_t block_invoke; dispatch_group_t group; pthread_t waiter; unsigned long barrier:1, sync:1, apply:1; } dispatch_introspection_queue_block_s; typedef dispatch_introspection_queue_block_s *dispatch_introspection_queue_block_t; /*! * @typedef dispatch_introspection_queue_function_s * * @abstract * A structure of introspection information for a function & context pointer * item enqueued on a dispatch queue. * * @field continuation * Pointer to enqueued item. * * @field target_queue * Target queue of item (may be different to the queue the item is currently * enqueued on). * * @field context * Context in enqueued item. * * @field block_invoke * Function pointer in enqueued item. * * @field group * Group containing enqueued item (may be NULL). * * @field waiter * Thread waiting for completion of enqueued item (NULL if sync == 0). * * @field barrier * Item is a barrier on the queue (all items on serial queues are barriers). * * @field sync * Item was enqueued by a dispatch_sync_f/dispatch_barrier_sync_f. * * @field apply * Item is part of a dispatch_apply_f. */ typedef struct dispatch_introspection_queue_function_s { dispatch_continuation_t continuation; dispatch_queue_t target_queue; void *context; dispatch_function_t function; dispatch_group_t group; pthread_t waiter; unsigned long barrier:1, sync:1, apply:1; } dispatch_introspection_queue_function_s; typedef dispatch_introspection_queue_function_s *dispatch_introspection_queue_function_t; /*! * @typedef dispatch_introspection_object_s * * @abstract * A structure of introspection information for a generic dispatch object. * * @field object * Pointer to object. * * @field target_queue * Target queue of object (may be different to the queue the object is * currently enqueued on). * * @field type * Object class pointer. * * @field kind * String describing the object type. */ typedef struct dispatch_introspection_object_s { dispatch_continuation_t object; dispatch_queue_t target_queue; void *type; const char *kind; } dispatch_introspection_object_s; typedef dispatch_introspection_object_s *dispatch_introspection_object_t; /*! * @typedef dispatch_introspection_queue_s * * @abstract * A structure of introspection information for a dispatch queue. * * @field queue * Pointer to queue object. * * @field target_queue * Target queue of queue (may be different to the queue the queue is currently * enqueued on). NULL indicates queue is a root queue. * * @field label * Pointer to queue label. * * @field serialnum * Queue serial number (unique per process). * * @field width * Queue width (1: serial queue, UINT_MAX: concurrent queue). * * @field suspend_count * Number of times the queue has been suspended. * * @field enqueued * Queue is enqueued on another queue. * * @field barrier * Queue is executing a barrier item. * * @field draining * Queue is being drained (cannot get queue items). * * @field global * Queue is a global queue. * * @field main * Queue is the main queue. */ typedef struct dispatch_introspection_queue_s { dispatch_queue_t queue; dispatch_queue_t target_queue; const char *label; unsigned long serialnum; unsigned int width; unsigned int suspend_count; unsigned long enqueued:1, barrier:1, draining:1, global:1, main:1; } dispatch_introspection_queue_s; typedef dispatch_introspection_queue_s *dispatch_introspection_queue_t; /*! * @typedef dispatch_introspection_source_s * * @abstract * A structure of introspection information for a dispatch source. * * @field source * Pointer to source object. * * @field target_queue * Target queue of source (may be different to the queue the source is currently * enqueued on). * * @field type * Source type (kevent filter) * * @field handle * Source handle (monitored entity). * * @field context * Context pointer passed to source handler. Pointer to handler block if * handler_is_block == 1. * * @field handler * Source handler function. Function pointer of handler block if * handler_is_block == 1. * * @field suspend_count * Number of times the source has been suspended. * * @field enqueued * Source is enqueued on a queue. * * @field handler_is_block * Source handler is a block. * * @field timer * Source is a timer. * * @field after * Source is a dispatch_after timer. */ typedef struct dispatch_introspection_source_s { dispatch_source_t source; dispatch_queue_t target_queue; unsigned long type; unsigned long handle; void *context; dispatch_function_t handler; unsigned int suspend_count; unsigned long enqueued:1, handler_is_block:1, timer:1, after:1; } dispatch_introspection_source_s; typedef dispatch_introspection_source_s *dispatch_introspection_source_t; /*! * @typedef dispatch_introspection_queue_thread_s * * @abstract * A structure of introspection information about a thread executing items for * a dispatch queue. * * @field object * Pointer to thread object. * * @field thread * Thread executing items for a queue. * * @field queue * Queue introspection information. The queue.queue field is NULL if this thread * is not currently executing items for a queue. */ typedef struct dispatch_introspection_queue_thread_s { dispatch_continuation_t object; pthread_t thread; dispatch_introspection_queue_s queue; } dispatch_introspection_queue_thread_s; typedef dispatch_introspection_queue_thread_s *dispatch_introspection_queue_thread_t; /*! * @enum dispatch_introspection_queue_item_type * * @abstract * Types of items enqueued on a dispatch queue. */ enum dispatch_introspection_queue_item_type { dispatch_introspection_queue_item_type_none = 0x0, dispatch_introspection_queue_item_type_block = 0x11, dispatch_introspection_queue_item_type_function = 0x12, dispatch_introspection_queue_item_type_object = 0x100, dispatch_introspection_queue_item_type_queue = 0x101, dispatch_introspection_queue_item_type_source = 0102, }; /*! * @typedef dispatch_introspection_queue_item_s * * @abstract * A structure of introspection information about an item enqueued on a * dispatch queue. * * @field type * Indicates which of the union members applies to this item. */ typedef struct dispatch_introspection_queue_item_s { unsigned long type; // dispatch_introspection_queue_item_type union { dispatch_introspection_queue_block_s block; dispatch_introspection_queue_function_s function; dispatch_introspection_object_s object; dispatch_introspection_queue_s queue; dispatch_introspection_source_s source; }; } dispatch_introspection_queue_item_s; typedef dispatch_introspection_queue_item_s *dispatch_introspection_queue_item_t; /*! * @typedef dispatch_introspection_hook_queue_create_t * * @abstract * A function pointer called when a dispatch queue is created. * * @param queue_info * Pointer to queue introspection structure. */ typedef void (*dispatch_introspection_hook_queue_create_t)( dispatch_introspection_queue_t queue_info); /*! * @typedef dispatch_introspection_hook_queue_dispose_t * * @abstract * A function pointer called when a dispatch queue is destroyed. * * @param queue_info * Pointer to queue introspection structure. */ typedef void (*dispatch_introspection_hook_queue_dispose_t)( dispatch_introspection_queue_t queue_info); /*! * @typedef dispatch_introspection_hook_queue_item_enqueue_t * * @abstract * A function pointer called when an item is enqueued onto a dispatch queue. * * @param queue * Pointer to queue. * * @param item * Pointer to item introspection structure. */ typedef void (*dispatch_introspection_hook_queue_item_enqueue_t)( dispatch_queue_t queue, dispatch_introspection_queue_item_t item); /*! * @typedef dispatch_introspection_hook_queue_item_dequeue_t * * @abstract * A function pointer called when an item is dequeued from a dispatch queue. * * @param queue * Pointer to queue. * * @param item * Pointer to item introspection structure. */ typedef void (*dispatch_introspection_hook_queue_item_dequeue_t)( dispatch_queue_t queue, dispatch_introspection_queue_item_t item); /*! * @typedef dispatch_introspection_hook_queue_item_complete_t * * @abstract * A function pointer called when an item previously dequeued from a dispatch * queue has completed processing. * * @discussion * The object pointer value passed to this function pointer must be treated as a * value only. It is intended solely for matching up with an earlier call to a * dequeue hook function pointer by comparing to the first member of the * dispatch_introspection_queue_item_t structure. It must NOT be dereferenced * or e.g. passed to dispatch_introspection_queue_item_get_info(), the memory * that was backing it may have been reused at the time this hook is called. * * @param object * Opaque dentifier for completed item. Must NOT be dereferenced. */ typedef void (*dispatch_introspection_hook_queue_item_complete_t)( dispatch_continuation_t object); /*! * @typedef dispatch_introspection_hooks_s * * @abstract * A structure of function pointer hoooks into libdispatch. */ typedef struct dispatch_introspection_hooks_s { dispatch_introspection_hook_queue_create_t queue_create; dispatch_introspection_hook_queue_dispose_t queue_dispose; dispatch_introspection_hook_queue_item_enqueue_t queue_item_enqueue; dispatch_introspection_hook_queue_item_dequeue_t queue_item_dequeue; dispatch_introspection_hook_queue_item_complete_t queue_item_complete; void *_reserved[5]; } dispatch_introspection_hooks_s; typedef dispatch_introspection_hooks_s *dispatch_introspection_hooks_t; /*! * @function dispatch_introspection_get_queues * * @abstract * Retrieve introspection information about all dispatch queues in the process, * in batches of specified size. * * @discussion * Retrieving queue information and iterating through the list of all queues * must take place from a debugger context (while the rest of the process is * suspended). * * @param start * Starting point for this batch of queue information, as returned by a previous * call to _dispatch_introspection_get_queues(). * Pass NULL to retrieve the initial batch. * * @param count * Number of queues to introspect. * * @param queues * Array to fill with queue information. If less than 'count' queues are left * in this batch, the end of valid entries in the array will be indicated * by an entry with NULL queue member. * * @result * Queue to pass to another call to _dispatch_introspection_get_queues() to * retrieve information about the next batch of queues. May be NULL if there * are no more queues to iterate over. */ extern dispatch_queue_t dispatch_introspection_get_queues(dispatch_queue_t start, size_t count, dispatch_introspection_queue_t queues); /*! * @function dispatch_introspection_get_queue_threads * * @abstract * Retrieve introspection information about all threads in the process executing * items for dispatch queues, in batches of specified size. * * @discussion * Retrieving thread information and iterating through the list of all queue * threads must take place from a debugger context (while the rest of the * process is suspended). * * @param start * Starting point for this batch of thread information, as returned by a * previous call to _dispatch_introspection_get_queue_threads(). * Pass NULL to retrieve the initial batch. * * @param count * Number of queue threads to introspect. * * @param threads * Array to fill with queue thread information. If less than 'count' threads are * left in this batch, the end of valid entries in the array will be indicated * by an entry with NULL object member. * * @result * Object to pass to another call to _dispatch_introspection_get_queues() to * retrieve information about the next batch of queues. May be NULL if there * are no more queues to iterate over. */ extern dispatch_continuation_t dispatch_introspection_get_queue_threads(dispatch_continuation_t start, size_t count, dispatch_introspection_queue_thread_t threads); /*! * @function dispatch_introspection_queue_get_items * * @abstract * Retrieve introspection information about all items enqueued on a queue, in * batches of specified size. * * @discussion * Retrieving queue item information and iterating through a queue must take * place from a debugger context (while the rest of the process is suspended). * * @param queue * Queue to introspect. * * @param start * Starting point for this batch of queue item information, as returned by a * previous call to _dispatch_introspection_queue_get_items(). * Pass NULL to retrieve the initial batch. * * @param count * Number of items to introspect. * * @param items * Array to fill with queue item information. If less than 'count' queues are * left in this batch, the end of valid entries in the array will be indicated * by an entry with type dispatch_introspection_queue_item_type_none. * * @result * Item to pass to another call to _dispatch_introspection_queue_get_items() to * retrieve information about the next batch of queue items. May be NULL if * there are no more items to iterate over. */ extern dispatch_continuation_t dispatch_introspection_queue_get_items(dispatch_queue_t queue, dispatch_continuation_t start, size_t count, dispatch_introspection_queue_item_t items); /*! * @function dispatch_introspection_queue_get_info * * @abstract * Retrieve introspection information about a specified dispatch queue. * * @discussion * Retrieving queue information must take place from a debugger context (while * the rest of the process is suspended). * * @param queue * Queue to introspect. * * @result * Queue information struct. */ extern dispatch_introspection_queue_s dispatch_introspection_queue_get_info(dispatch_queue_t queue); /*! * @function dispatch_introspection_queue_item_get_info * * @abstract * Retrieve introspection information about a specified dispatch queue item. * * @discussion * Retrieving queue item information must take place from a debugger context * (while the rest of the process is suspended). * * @param queue * Queue to introspect. * * @param item * Item to introspect. * * @result * Queue item information struct. */ extern dispatch_introspection_queue_item_s dispatch_introspection_queue_item_get_info(dispatch_queue_t queue, dispatch_continuation_t item); /*! * @function dispatch_introspection_hooks_install * * @abstract * Install hook functions into libdispatch. * * @discussion * Installing hook functions must take place from a debugger context (while the * rest of the process is suspended) or early enough in the process lifecycle * that the process is still single-threaded. * * The caller is responsible for implementing chaining to the hooks that were * previously installed (if any). * * @param hooks * Pointer to structure of hook function pointers. Any of the structure members * may be NULL to indicate that the hook in question should not be installed. * The structure is copied on input and filled with the previously installed * hooks on output. */ __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0) DISPATCH_EXPORT void dispatch_introspection_hooks_install(dispatch_introspection_hooks_t hooks); /*! * @function dispatch_introspection_hook_callouts_enable * * @abstract * Enable hook callout functions in libdispatch that a debugger can break on * and get introspection arguments even if there are no hook functions * installed via dispatch_introspection_hooks_install(). * * @discussion * Enabling hook callout functions must take place from a debugger context * (while the rest of the process is suspended). * * @param enable * Pointer to dispatch_introspection_hooks_s structure. For every structure * member with (any) non-NULL value, the corresponding hook callout will be * enabled; for every NULL member the hook callout will be disabled (if there * is no hook function installed). * As a convenience, the 'enable' pointer may itself be NULL to indicate that * all hook callouts should be enabled. */ extern void dispatch_introspection_hook_callouts_enable( dispatch_introspection_hooks_t enable); /*! * @function dispatch_introspection_hook_callout_queue_create * * @abstract * Callout to queue creation hook that a debugger can break on. */ extern void dispatch_introspection_hook_callout_queue_create( dispatch_introspection_queue_t queue_info); /*! * @function dispatch_introspection_hook_callout_queue_dispose * * @abstract * Callout to queue destruction hook that a debugger can break on. */ extern void dispatch_introspection_hook_callout_queue_dispose( dispatch_introspection_queue_t queue_info); /*! * @function dispatch_introspection_hook_callout_queue_item_enqueue * * @abstract * Callout to queue enqueue hook that a debugger can break on. */ extern void dispatch_introspection_hook_callout_queue_item_enqueue( dispatch_queue_t queue, dispatch_introspection_queue_item_t item); /*! * @function dispatch_introspection_hook_callout_queue_item_dequeue * * @abstract * Callout to queue dequeue hook that a debugger can break on. */ extern void dispatch_introspection_hook_callout_queue_item_dequeue( dispatch_queue_t queue, dispatch_introspection_queue_item_t item); /*! * @function dispatch_introspection_hook_callout_queue_item_complete * * @abstract * Callout to queue item complete hook that a debugger can break on. */ extern void dispatch_introspection_hook_callout_queue_item_complete( dispatch_continuation_t object); /*! * @function dispatch_introspection_hook_queue_item_complete * * @abstract * Interposable hook function called when an item previously dequeued from a * dispatch queue has completed processing. * * @discussion * The object pointer value passed to this function must be treated as a value * only. It is intended solely for matching up with an earlier call to a * dequeue hook function and must NOT be dereferenced. * * @param item * Opaque dentifier for completed item. Must NOT be dereferenced. */ DISPATCH_EXPORT void dispatch_introspection_hook_queue_item_complete(dispatch_object_t item); __END_DECLS #endif