2 * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
22 * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
23 * which are subject to change in future releases of Mac OS X. Any applications
24 * relying on these interfaces WILL break.
27 #ifndef __DISPATCH_QUEUE_INTERNAL__
28 #define __DISPATCH_QUEUE_INTERNAL__
30 #ifndef __DISPATCH_INDIRECT__
31 #error "Please #include <dispatch/dispatch.h> instead of this file directly."
32 #include <dispatch/base.h> // for HeaderDoc
35 // If dc_vtable is less than 127, then the object is a continuation.
36 // Otherwise, the object has a private layout and memory management rules. The
37 // first two words must align with normal objects.
38 #define DISPATCH_CONTINUATION_HEADER(x) \
39 const void * do_vtable; \
40 struct x *volatile do_next; \
41 dispatch_function_t dc_func; \
44 #define DISPATCH_OBJ_ASYNC_BIT 0x1
45 #define DISPATCH_OBJ_BARRIER_BIT 0x2
46 #define DISPATCH_OBJ_GROUP_BIT 0x4
47 // vtables are pointers far away from the low page in memory
48 #define DISPATCH_OBJ_IS_VTABLE(x) ((unsigned long)(x)->do_vtable > 127ul)
50 struct dispatch_continuation_s
{
51 DISPATCH_CONTINUATION_HEADER(dispatch_continuation_s
);
52 dispatch_group_t dc_group
;
56 typedef struct dispatch_continuation_s
*dispatch_continuation_t
;
59 struct dispatch_queue_vtable_s
{
60 DISPATCH_VTABLE_HEADER(dispatch_queue_s
);
63 #define DISPATCH_QUEUE_MIN_LABEL_SIZE 64
65 #define DISPATCH_QUEUE_HEADER \
66 uint32_t dq_running; \
68 struct dispatch_object_s *dq_items_tail; \
69 struct dispatch_object_s *volatile dq_items_head; \
70 unsigned long dq_serialnum; \
71 void *dq_finalizer_ctxt; \
72 dispatch_queue_finalizer_function_t dq_finalizer_func
74 struct dispatch_queue_s
{
75 DISPATCH_STRUCT_HEADER(dispatch_queue_s
, dispatch_queue_vtable_s
);
76 DISPATCH_QUEUE_HEADER
;
77 char dq_label
[DISPATCH_QUEUE_MIN_LABEL_SIZE
]; // must be last
80 extern struct dispatch_queue_s _dispatch_mgr_q
;
82 void _dispatch_queue_init(dispatch_queue_t dq
);
83 void _dispatch_queue_drain(dispatch_queue_t dq
);
84 void _dispatch_queue_dispose(dispatch_queue_t dq
);
86 __attribute__((always_inline
))
88 _dispatch_queue_push_list(dispatch_queue_t dq
, dispatch_object_t _head
, dispatch_object_t _tail
)
90 struct dispatch_object_s
*prev
, *head
= _head
._do
, *tail
= _tail
._do
;
93 prev
= fastpath(dispatch_atomic_xchg(&dq
->dq_items_tail
, tail
));
95 // if we crash here with a value less than 0x1000, then we are at a known bug in client code
96 // for example, see _dispatch_queue_dispose or _dispatch_atfork_child
99 dq
->dq_items_head
= head
;
100 _dispatch_wakeup(dq
);
104 #define _dispatch_queue_push(x, y) _dispatch_queue_push_list((x), (y), (y))
106 #define DISPATCH_QUEUE_PRIORITY_COUNT 3
109 void dispatch_debug_queue(dispatch_queue_t dq
, const char* str
);
111 static inline void dispatch_debug_queue(dispatch_queue_t dq
__attribute__((unused
)), const char* str
__attribute__((unused
))) {}
114 size_t dispatch_queue_debug(dispatch_queue_t dq
, char* buf
, size_t bufsiz
);
115 size_t dispatch_queue_debug_attr(dispatch_queue_t dq
, char* buf
, size_t bufsiz
);
117 static inline dispatch_queue_t
118 _dispatch_queue_get_current(void)
120 return _dispatch_thread_getspecific(dispatch_queue_key
);
123 __private_extern__ malloc_zone_t
*_dispatch_ccache_zone
;
124 dispatch_continuation_t
_dispatch_continuation_alloc_from_heap(void);
126 static inline dispatch_continuation_t
127 _dispatch_continuation_alloc_cacheonly(void)
129 dispatch_continuation_t dc
= fastpath(_dispatch_thread_getspecific(dispatch_cache_key
));
131 _dispatch_thread_setspecific(dispatch_cache_key
, dc
->do_next
);