[libdispatch-changes] [155] trunk/src

source_changes at macosforge.org source_changes at macosforge.org
Sat Nov 14 15:54:01 PST 2009


Revision: 155
          http://trac.macosforge.org/projects/libdispatch/changeset/155
Author:   kvv at apple.com
Date:     2009-11-14 15:53:59 -0800 (Sat, 14 Nov 2009)
Log Message:
-----------
10.6.2: Fix a performance regression in the dispatch_queue_pust_list fast path.
<rdar://problem/7217227>

Modified Paths:
--------------
    trunk/src/queue.c
    trunk/src/queue_internal.h

Modified: trunk/src/queue.c
===================================================================
--- trunk/src/queue.c	2009-11-14 21:24:14 UTC (rev 154)
+++ trunk/src/queue.c	2009-11-14 23:53:59 UTC (rev 155)
@@ -620,6 +620,22 @@
 	_dispatch_dispose(dq);
 }
 
+DISPATCH_NOINLINE 
+void
+_dispatch_queue_push_list_slow(dispatch_queue_t dq, struct dispatch_object_s *obj)
+{
+	// The queue must be retained before dq_items_head is written in order
+	// to ensure that the reference is still valid when _dispatch_wakeup is
+	// called. Otherwise, if preempted between the assignment to
+	// dq_items_head and _dispatch_wakeup, the blocks submitted to the
+	// queue may release the last reference to the queue when invoked by
+	// _dispatch_queue_drain. <rdar://problem/6932776>
+	_dispatch_retain(dq);
+	dq->dq_items_head = obj;
+	_dispatch_wakeup(dq);
+	_dispatch_release(dq);
+}
+
 DISPATCH_NOINLINE
 static void
 _dispatch_barrier_async_f_slow(dispatch_queue_t dq, void *context, dispatch_function_t func)

Modified: trunk/src/queue_internal.h
===================================================================
--- trunk/src/queue_internal.h	2009-11-14 21:24:14 UTC (rev 154)
+++ trunk/src/queue_internal.h	2009-11-14 23:53:59 UTC (rev 155)
@@ -95,6 +95,7 @@
 void _dispatch_queue_init(dispatch_queue_t dq);
 void _dispatch_queue_drain(dispatch_queue_t dq);
 void _dispatch_queue_dispose(dispatch_queue_t dq);
+void _dispatch_queue_push_list_slow(dispatch_queue_t dq, struct dispatch_object_s *obj);
 void _dispatch_queue_serial_drain_till_empty(dispatch_queue_t dq);
 void _dispatch_force_cache_cleanup(void);
 
@@ -105,17 +106,14 @@
 	struct dispatch_object_s *prev, *head = _head._do, *tail = _tail._do;
 
 	tail->do_next = NULL;
-	_dispatch_retain(dq);
 	prev = fastpath(dispatch_atomic_xchg(&dq->dq_items_tail, tail));
 	if (prev) {
 		// if we crash here with a value less than 0x1000, then we are at a known bug in client code
 		// for example, see _dispatch_queue_dispose or _dispatch_atfork_child
 		prev->do_next = head;
 	} else {
-		dq->dq_items_head = head;
-		_dispatch_wakeup(dq);
+		_dispatch_queue_push_list_slow(dq, head);
 	}
-	_dispatch_release(dq);
 }
 
 #define _dispatch_queue_push(x, y) _dispatch_queue_push_list((x), (y), (y))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/libdispatch-changes/attachments/20091114/0f8e5a46/attachment.html>


More information about the libdispatch-changes mailing list