]> git.saurik.com Git - apple/libdispatch.git/commitdiff
libdispatch-339.90.1.tar.gz os-x-1092 v339.90.1
authorApple <opensource@apple.com>
Tue, 11 Mar 2014 19:54:31 +0000 (19:54 +0000)
committerApple <opensource@apple.com>
Tue, 11 Mar 2014 19:54:31 +0000 (19:54 +0000)
private/introspection_private.h
src/introspection.c
src/introspection_internal.h
src/queue.c
src/queue_internal.h
src/shims/tsd.h
src/source.c
xcodeconfig/libdispatch.interposable

index 727d9715a77559c665029c594577eac49ad28e52..dd18beebc21ccceeb1ad17cde0224ff082055b32 100644 (file)
@@ -38,9 +38,9 @@
  * loaded by running a process with the environment variable
  * DYLD_LIBRARY_PATH=/usr/lib/system/introspection
  *
- * NOTE: these functions are _not_ exported from the shared library, they are
- * only intended to be called from a debugger context while the rest of the
- * process is suspended.
+ * 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
@@ -68,7 +68,13 @@ 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
@@ -79,6 +85,43 @@ typedef struct dispatch_object_s *dispatch_object_t;
  * @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.
  *
@@ -467,6 +510,27 @@ typedef void (*dispatch_introspection_hook_queue_item_enqueue_t)(
 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
  *
@@ -479,7 +543,8 @@ typedef struct dispatch_introspection_hooks_s {
        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;
-       void *_reserved[6];
+       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;
 
@@ -638,7 +703,8 @@ dispatch_introspection_queue_item_get_info(dispatch_queue_t queue,
  *
  * @discussion
  * Installing hook functions must take place from a debugger context (while the
- * rest of the process is suspended).
+ * 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).
@@ -650,7 +716,8 @@ dispatch_introspection_queue_item_get_info(dispatch_queue_t queue,
  * hooks on output.
  */
 
-extern void
+__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0)
+DISPATCH_EXPORT void
 dispatch_introspection_hooks_install(dispatch_introspection_hooks_t hooks);
 
 /*!
@@ -722,6 +789,37 @@ 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
index 5338f259acbe909fe475665ba72ede33f4b727f9..d1dd04db590e8cac66f0db4f07d7dad55ea387a3 100644 (file)
@@ -85,7 +85,7 @@ _dispatch_introspection_init(void)
 const struct dispatch_introspection_versions_s
 dispatch_introspection_versions = {
        .introspection_version = 1,
-       .hooks_version = 1,
+       .hooks_version = 2,
        .hooks_size = sizeof(dispatch_introspection_hooks_s),
        .queue_item_version = 1,
        .queue_item_size = sizeof(dispatch_introspection_queue_item_s),
@@ -390,6 +390,7 @@ dispatch_introspection_hooks_s _dispatch_introspection_hook_callouts_enabled = {
        .queue_dispose = DISPATCH_INTROSPECTION_NO_HOOK,
        .queue_item_enqueue = DISPATCH_INTROSPECTION_NO_HOOK,
        .queue_item_dequeue = DISPATCH_INTROSPECTION_NO_HOOK,
+       .queue_item_complete = DISPATCH_INTROSPECTION_NO_HOOK,
 };
 
 #define DISPATCH_INTROSPECTION_HOOKS_COUNT (( \
@@ -419,6 +420,7 @@ DISPATCH_INTROSPECTION_INTERPOSABLE_HOOK(queue_create);
 DISPATCH_INTROSPECTION_INTERPOSABLE_HOOK(queue_destroy);
 DISPATCH_INTROSPECTION_INTERPOSABLE_HOOK(queue_item_enqueue);
 DISPATCH_INTROSPECTION_INTERPOSABLE_HOOK(queue_item_dequeue);
+DISPATCH_INTROSPECTION_INTERPOSABLE_HOOK(queue_item_complete);
 DISPATCH_INTROSPECTION_INTERPOSABLE_HOOK(queue_callout_begin);
 DISPATCH_INTROSPECTION_INTERPOSABLE_HOOK(queue_callout_end);
 
@@ -564,7 +566,7 @@ _dispatch_introspection_queue_item_dequeue_hook(dispatch_queue_t dq,
 {
        dispatch_introspection_queue_item_s diqi;
        diqi = dispatch_introspection_queue_item_get_info(dq, dou._dc);
-       dispatch_introspection_hook_callout_queue_item_enqueue(dq, &diqi);
+       dispatch_introspection_hook_callout_queue_item_dequeue(dq, &diqi);
 }
 
 void
@@ -578,6 +580,30 @@ _dispatch_introspection_queue_item_dequeue(dispatch_queue_t dq,
        }
 }
 
+DISPATCH_NOINLINE
+void
+dispatch_introspection_hook_callout_queue_item_complete(
+               dispatch_continuation_t object)
+{
+       DISPATCH_INTROSPECTION_HOOK_CALLOUT(queue_item_complete, object);
+}
+
+DISPATCH_NOINLINE
+static void
+_dispatch_introspection_queue_item_complete_hook(dispatch_object_t dou)
+{
+       dispatch_introspection_hook_callout_queue_item_complete(dou._dc);
+}
+
+void
+_dispatch_introspection_queue_item_complete(dispatch_object_t dou)
+{
+       DISPATCH_INTROSPECTION_INTERPOSABLE_HOOK_CALLOUT(queue_item_complete, dou);
+       if (DISPATCH_INTROSPECTION_HOOK_ENABLED(queue_item_complete)) {
+               _dispatch_introspection_queue_item_complete_hook(dou);
+       }
+}
+
 void
 _dispatch_introspection_callout_entry(void *ctxt, dispatch_function_t f) {
        dispatch_queue_t dq = _dispatch_queue_get_current();
index 89a9360c01363076028c1b602149933e9d5ecaad..7b015aa0e07a2c8a1908b74b50ba983da381ab8b 100644 (file)
@@ -42,6 +42,7 @@ void _dispatch_introspection_queue_item_enqueue(dispatch_queue_t dq,
                dispatch_object_t dou);
 void _dispatch_introspection_queue_item_dequeue(dispatch_queue_t dq,
                dispatch_object_t dou);
+void _dispatch_introspection_queue_item_complete(dispatch_object_t dou);
 void _dispatch_introspection_callout_entry(void *ctxt, dispatch_function_t f);
 void _dispatch_introspection_callout_return(void *ctxt, dispatch_function_t f);
 
@@ -104,6 +105,11 @@ static inline void
 _dispatch_introspection_queue_pop(dispatch_queue_t dq DISPATCH_UNUSED,
                dispatch_object_t dou DISPATCH_UNUSED) {}
 
+DISPATCH_ALWAYS_INLINE
+static inline void
+_dispatch_introspection_queue_item_complete(
+               dispatch_object_t dou DISPATCH_UNUSED) {}
+
 DISPATCH_ALWAYS_INLINE
 static inline void
 _dispatch_introspection_callout_entry(void *ctxt DISPATCH_UNUSED,
index 05687622322164316e4f0fd1bd0ad53b9d5a701f..0c05b0bea2773499561f8945c308d7074a648383 100644 (file)
@@ -1345,15 +1345,17 @@ _dispatch_continuation_redirect(dispatch_queue_t dq, dispatch_object_t dou)
 {
        dispatch_continuation_t dc = dou._dc;
 
-       _dispatch_trace_continuation_pop(dq, dou);
        (void)dispatch_atomic_add2o(dq, dq_running, 2, acquire);
        if (!DISPATCH_OBJ_IS_VTABLE(dc) &&
                        (long)dc->do_vtable & DISPATCH_OBJ_SYNC_SLOW_BIT) {
+               _dispatch_trace_continuation_pop(dq, dou);
                _dispatch_thread_semaphore_signal(
                                (_dispatch_thread_semaphore_t)dc->dc_other);
+               _dispatch_introspection_queue_item_complete(dou);
        } else {
                _dispatch_async_f_redirect(dq, dc);
        }
+       _dispatch_perfmon_workitem_inc();
 }
 
 DISPATCH_ALWAYS_INLINE_NDEBUG
@@ -1389,6 +1391,7 @@ _dispatch_continuation_pop(dispatch_object_t dou)
                dispatch_group_leave(dg);
                _dispatch_release(dg);
        }
+        _dispatch_introspection_queue_item_complete(dou);
        if (slowpath(dc1)) {
                _dispatch_continuation_free_to_cache_limit(dc1);
        }
@@ -1700,6 +1703,7 @@ _dispatch_barrier_sync_f_pop(dispatch_queue_t dq, dispatch_object_t dou,
                // returns
                (void)dispatch_atomic_add2o(dq, dq_running, 2, relaxed);
        }
+       _dispatch_introspection_queue_item_complete(dou);
        return sema ? sema : MACH_PORT_DEAD;
 }
 
@@ -1715,7 +1719,7 @@ _dispatch_barrier_sync_f_slow_invoke(void *ctxt)
 #if DISPATCH_COCOA_COMPAT
        if (slowpath(dq->dq_is_thread_bound)) {
                // The queue is bound to a non-dispatch thread (e.g. main thread)
-               dc->dc_func(dc->dc_ctxt);
+               _dispatch_client_callout(dc->dc_ctxt, dc->dc_func);
                dispatch_atomic_store2o(dc, dc_func, NULL, release);
                _dispatch_thread_semaphore_signal(sema); // release
                return;
@@ -1985,7 +1989,8 @@ _dispatch_sync_f2(dispatch_queue_t dq, void *ctxt, dispatch_function_t func)
                return _dispatch_sync_f_slow(dq, ctxt, func, false);
        }
        uint32_t running = dispatch_atomic_add2o(dq, dq_running, 2, relaxed);
-       if (slowpath(running & 1)) {
+       // re-check suspension after barrier check <rdar://problem/15242126>
+       if (slowpath(running & 1) || slowpath(DISPATCH_OBJECT_SUSPENDED(dq))) {
                running = dispatch_atomic_sub2o(dq, dq_running, 2, relaxed);
                return _dispatch_sync_f_slow(dq, ctxt, func, running == 0);
        }
index 4f42d24fafc53a123eb65f054bc942c6d0c694eb..5f6476a53c20e7811bf3b2272b1b70ad79d9f9f9 100644 (file)
@@ -270,6 +270,7 @@ _dispatch_queue_class_invoke(dispatch_object_t dou,
                if (sema) {
                        _dispatch_thread_semaphore_signal(sema);
                } else if (tq) {
+                       _dispatch_introspection_queue_item_complete(dq);
                        return _dispatch_queue_push(tq, dq);
                }
        }
@@ -281,6 +282,7 @@ _dispatch_queue_class_invoke(dispatch_object_t dou,
                        _dispatch_wakeup(dq); // verify that the queue is idle
                }
        }
+       _dispatch_introspection_queue_item_complete(dq);
        _dispatch_release(dq); // added when the queue is put on the list
 }
 
index 2a0ab2290e961d4172584f9ad7027c23bca67ea2..c7e387c17113f8e43759cd91126bcdd4192c013a 100644 (file)
@@ -36,6 +36,9 @@
 #if USE_APPLE_TSD_OPTIMIZATIONS && HAVE_PTHREAD_KEY_INIT_NP && \
        !defined(DISPATCH_USE_DIRECT_TSD)
 #define DISPATCH_USE_DIRECT_TSD 1
+#if __has_include(<os/tsd.h>)
+#include <os/tsd.h>
+#endif
 #endif
 
 #if DISPATCH_USE_DIRECT_TSD
@@ -128,3 +131,20 @@ DISPATCH_TSD_INLINE DISPATCH_CONST
 static inline unsigned int
 _dispatch_cpu_number(void)
 {
+#if TARGET_IPHONE_SIMULATOR && IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 1090
+       return 0;
+#elif __has_include(<os/tsd.h>)
+       return _os_cpu_number();
+#elif defined(__x86_64__) || defined(__i386__)
+       struct { uintptr_t p1, p2; } p;
+       __asm__("sidt %[p]" : [p] "=&m" (p));
+       return (unsigned int)(p.p1 & 0xfff);
+#else
+       // Not yet implemented.
+       return 0;
+#endif
+}
+
+#undef DISPATCH_TSD_INLINE
+
+#endif
index 067c5baf9da8af0d2780671f4f247d842672387b..c6aaae36f252b6538a530fc6987dfd866a9ac0a2 100644 (file)
@@ -3678,6 +3678,7 @@ _dispatch_mach_msg_invoke(dispatch_mach_msg_t dmsg)
        _dispatch_client_callout4(dr->dm_handler_ctxt, reason, dmsg, err,
                        dr->dm_handler_func);
        _dispatch_thread_setspecific(dispatch_queue_key, (dispatch_queue_t)dm);
+       _dispatch_introspection_queue_item_complete(dmsg);
        dispatch_release(dmsg);
 }
 
index f3377617b3658226860c584f37c71d3cbebbbbf2..52a1264688211b8b502b9aaa6f7a442d6e5730f3 100644 (file)
@@ -24,5 +24,6 @@ _dispatch_introspection_hook_queue_create
 _dispatch_introspection_hook_queue_destroy
 _dispatch_introspection_hook_queue_item_enqueue
 _dispatch_introspection_hook_queue_item_dequeue
+_dispatch_introspection_hook_queue_item_complete
 _dispatch_introspection_hook_queue_callout_begin
 _dispatch_introspection_hook_queue_callout_end