Tizen 2.1 base
[platform/upstream/gcd.git] / dispatch-1.0 / src / queue_internal.h
1 /*
2  * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
3  *
4  * @APPLE_APACHE_LICENSE_HEADER_START@
5  * 
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
9  * 
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  * 
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.
17  * 
18  * @APPLE_APACHE_LICENSE_HEADER_END@
19  */
20
21 /*
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.
25  */
26
27 #ifndef __DISPATCH_QUEUE_INTERNAL__
28 #define __DISPATCH_QUEUE_INTERNAL__
29
30 #ifndef __DISPATCH_INDIRECT__
31 #error "Please #include <dispatch/dispatch.h> instead of this file directly."
32 #include <dispatch/base.h> // for HeaderDoc
33 #endif
34
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;        \
42         void *                                          dc_ctxt
43
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)
49
50 struct dispatch_continuation_s {
51         DISPATCH_CONTINUATION_HEADER(dispatch_continuation_s);
52         dispatch_group_t        dc_group;
53         void *                          dc_data[3];
54 };
55
56 typedef struct dispatch_continuation_s *dispatch_continuation_t;
57
58
59 struct dispatch_queue_vtable_s {
60         DISPATCH_VTABLE_HEADER(dispatch_queue_s);
61 };
62
63 #define DISPATCH_QUEUE_MIN_LABEL_SIZE   64
64
65 #ifndef DISPATCH_NO_LEGACY
66 #define DISPATCH_QUEUE_HEADER \
67         uint32_t dq_running; \
68         uint32_t dq_width; \
69         struct dispatch_object_s *dq_items_tail; \
70         struct dispatch_object_s *volatile dq_items_head; \
71         unsigned long dq_serialnum; \
72         void *dq_finalizer_ctxt; \
73         dispatch_queue_finalizer_function_t dq_finalizer_func
74 #else
75 #define DISPATCH_QUEUE_HEADER \
76         uint32_t dq_running; \
77         uint32_t dq_width; \
78         struct dispatch_object_s *dq_items_tail; \
79         struct dispatch_object_s *volatile dq_items_head; \
80         unsigned long dq_serialnum; \
81         void *dq_finalizer_ctxt;
82 #endif
83
84 struct dispatch_queue_s {
85         DISPATCH_STRUCT_HEADER(dispatch_queue_s, dispatch_queue_vtable_s);
86         DISPATCH_QUEUE_HEADER;
87         char dq_label[DISPATCH_QUEUE_MIN_LABEL_SIZE];   // must be last
88 };
89
90 extern struct dispatch_queue_s _dispatch_mgr_q;
91
92 #define DISPATCH_ROOT_QUEUE_COUNT (DISPATCH_QUEUE_PRIORITY_COUNT * 2)
93 extern struct dispatch_queue_s _dispatch_root_queues[];
94
95 void _dispatch_queue_init(dispatch_queue_t dq);
96 void _dispatch_queue_drain(dispatch_queue_t dq);
97 void _dispatch_queue_dispose(dispatch_queue_t dq);
98 void _dispatch_queue_push_list_slow(dispatch_queue_t dq, struct dispatch_object_s *obj);
99 void _dispatch_queue_serial_drain_till_empty(dispatch_queue_t dq);
100 void _dispatch_force_cache_cleanup(void);
101
102 __attribute__((always_inline))
103 static inline void
104 _dispatch_queue_push_list(dispatch_queue_t dq, dispatch_object_t _head, dispatch_object_t _tail)
105 {
106         struct dispatch_object_s *prev, *head = _head._do, *tail = _tail._do;
107
108         tail->do_next = NULL;
109         prev = fastpath(dispatch_atomic_xchg(&dq->dq_items_tail, tail));
110         if (prev) {
111                 // if we crash here with a value less than 0x1000, then we are at a known bug in client code
112                 // for example, see _dispatch_queue_dispose or _dispatch_atfork_child
113                 prev->do_next = head;
114         } else {
115                 _dispatch_queue_push_list_slow(dq, head);
116         }
117 }
118
119 #define _dispatch_queue_push(x, y) _dispatch_queue_push_list((x), (y), (y))
120
121 #define DISPATCH_QUEUE_PRIORITY_COUNT 3
122
123 #if DISPATCH_DEBUG
124 void dispatch_debug_queue(dispatch_queue_t dq, const char* str);
125 #else
126 static inline void dispatch_debug_queue(dispatch_queue_t dq __attribute__((unused)), const char* str __attribute__((unused))) {}
127 #endif
128
129 size_t dispatch_queue_debug(dispatch_queue_t dq, char* buf, size_t bufsiz);
130 size_t dispatch_queue_debug_attr(dispatch_queue_t dq, char* buf, size_t bufsiz);
131
132 static inline dispatch_queue_t
133 _dispatch_queue_get_current(void)
134 {
135         return _dispatch_thread_getspecific(dispatch_queue_key);
136 }
137
138 __private_extern__ malloc_zone_t *_dispatch_ccache_zone;
139 dispatch_continuation_t _dispatch_continuation_alloc_from_heap(void);
140
141 static inline dispatch_continuation_t
142 _dispatch_continuation_alloc_cacheonly(void)
143 {
144         dispatch_continuation_t dc = fastpath(_dispatch_thread_getspecific(dispatch_cache_key));
145         if (dc) {
146                 _dispatch_thread_setspecific(dispatch_cache_key, dc->do_next);
147         }
148         return dc;
149 }
150
151 #endif