[libdispatch-dev] libdispatch's thread model

Daniel A. Steffen dsteffen at apple.com
Wed Jan 27 08:43:09 PST 2010


On Jan 27, 2010, at 8:01 AM, Mario Schwalbe wrote:

> Hi,
> 
> On 27.01.2010 16:41, Mario Schwalbe wrote:
>> I know that Apple's non-posix extension to pthread isn't available.
>> Nevertheless, it should be possible to at least use a bounded number of
>> worker threads less than MAX_THREAD_COUNT (255). What about dynamically
>> setting MAX_THREAD_COUNT (or a similar variable) to the number of
>> processors  instead?
> 
> As it turns out, the patch is rather simple:
> 
> Index: queue.c
> ===================================================================
> --- queue.c	(Revision 181)
> +++ queue.c	(Arbeitskopie)
> @@ -1188,6 +1188,8 @@
> 			if (r != ENOTSUP) {
> 				(void)dispatch_assume_zero(r);
> 			}
> +#else  /* HAVE_PTHREAD_WORKQUEUES */
> +		_dispatch_root_queue_contexts[i].dgq_thread_pool_size = _dispatch_hw_config.cc_max_active;
> #endif /* HAVE_PTHREAD_WORKQUEUES */
> #if USE_MACH_SEM
> 			// override the default FIFO behavior for the pool semaphores
> 
> There's similar code in _dispatch_root_queues_init() for the implementation
> using pthread workqueues, but disabled. Why?

that code is in fact not intended for the pthread workqueue implementation (which never looks at dgq_thread_pool_size) but for the pthread-pool implementation, it was mistakenly included inside the #if HAVE_PTHREAD_WORKQUEUES, it should be moved out, c.f. below

The reason it is disabled is explained by the comment... the kernel workqueue mechanism has the ability to create new worker threads when all existing threads for a workqueue are blocked, the pthread-pool implementation does not, so a non-overcommitting queue with a limited pool size can result in deadlocks for client code that expects to be able to submit many concurrently executing interdependent workitems that block.


diff --git i/src/queue.c w/src/queue.c
index dd18edf..33537ba 100644
--- i/src/queue.c
+++ w/src/queue.c
@@ -1171,18 +1171,17 @@ _dispatch_root_queues_init(void *context __attribute__((unused)))
 #endif
 
 	for (i = 0; i < DISPATCH_ROOT_QUEUE_COUNT; i++) {
-#if HAVE_PTHREAD_WORKQUEUES
-		r = pthread_workqueue_attr_setqueuepriority_np(&pwq_attr, _dispatch_rootq2wq_pri(i));
-		(void)dispatch_assume_zero(r);
-		r = pthread_workqueue_attr_setovercommit_np(&pwq_attr, i & 1);
-		(void)dispatch_assume_zero(r);
 // some software hangs if the non-overcommitting queues do not overcommit when threads block
 #if 0
 		if (!(i & 1)) {
 			dispatch_root_queue_contexts[i].dgq_thread_pool_size = _dispatch_hw_config.cc_max_active;
 		}
 #endif
-
+#if HAVE_PTHREAD_WORKQUEUES
+		r = pthread_workqueue_attr_setqueuepriority_np(&pwq_attr, _dispatch_rootq2wq_pri(i));
+		(void)dispatch_assume_zero(r);
+		r = pthread_workqueue_attr_setovercommit_np(&pwq_attr, i & 1);
+		(void)dispatch_assume_zero(r);
 		r = 0;
 		if (disable_wq || (r = pthread_workqueue_create_np(&_dispatch_root_queue_contexts[i].dgq_kworkqueue, &pwq_attr))) {
 			if (r != ENOTSUP) {




More information about the libdispatch-dev mailing list