]> git.saurik.com Git - apple/libdispatch.git/blob - src/introspection_internal.h
libdispatch-703.30.5.tar.gz
[apple/libdispatch.git] / src / introspection_internal.h
1 /*
2 * Copyright (c) 2010-2013 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_INTROSPECTION_INTERNAL__
28 #define __DISPATCH_INTROSPECTION_INTERNAL__
29
30 #if DISPATCH_INTROSPECTION
31
32 #define DISPATCH_INTROSPECTION_QUEUE_HEADER \
33 TAILQ_ENTRY(dispatch_queue_s) diq_list; \
34 dispatch_unfair_lock_s diq_order_top_head_lock; \
35 dispatch_unfair_lock_s diq_order_bottom_head_lock; \
36 TAILQ_HEAD(, dispatch_queue_order_entry_s) diq_order_top_head; \
37 TAILQ_HEAD(, dispatch_queue_order_entry_s) diq_order_bottom_head
38 #define DISPATCH_INTROSPECTION_QUEUE_HEADER_SIZE \
39 sizeof(struct { DISPATCH_INTROSPECTION_QUEUE_HEADER; })
40
41 struct dispatch_introspection_state_s {
42 TAILQ_HEAD(, dispatch_introspection_thread_s) threads;
43 TAILQ_HEAD(, dispatch_queue_s) queues;
44 dispatch_unfair_lock_s threads_lock;
45 dispatch_unfair_lock_s queues_lock;
46
47 ptrdiff_t thread_queue_offset;
48
49 // dispatch introspection features
50 bool debug_queue_inversions; // DISPATCH_DEBUG_QUEUE_INVERSIONS
51 };
52
53 extern struct dispatch_introspection_state_s _dispatch_introspection;
54
55 void _dispatch_introspection_init(void);
56 void _dispatch_introspection_thread_add(void);
57 dispatch_queue_t _dispatch_introspection_queue_create(dispatch_queue_t dq);
58 void _dispatch_introspection_queue_dispose(dispatch_queue_t dq);
59 void _dispatch_introspection_queue_item_enqueue(dispatch_queue_t dq,
60 dispatch_object_t dou);
61 void _dispatch_introspection_queue_item_dequeue(dispatch_queue_t dq,
62 dispatch_object_t dou);
63 void _dispatch_introspection_queue_item_complete(dispatch_object_t dou);
64 void _dispatch_introspection_callout_entry(void *ctxt, dispatch_function_t f);
65 void _dispatch_introspection_callout_return(void *ctxt, dispatch_function_t f);
66
67 #if DISPATCH_PURE_C
68
69 void _dispatch_sync_recurse_invoke(void *ctxt);
70 static dispatch_queue_t _dispatch_queue_get_current(void);
71
72 DISPATCH_ALWAYS_INLINE
73 static inline void
74 _dispatch_introspection_queue_push_list(dispatch_queue_t dq,
75 dispatch_object_t head, dispatch_object_t tail) {
76 struct dispatch_object_s *dou = head._do;
77 do {
78 _dispatch_introspection_queue_item_enqueue(dq, dou);
79 } while (dou != tail._do && (dou = dou->do_next));
80 };
81
82 DISPATCH_ALWAYS_INLINE
83 static inline void
84 _dispatch_introspection_queue_push(dispatch_queue_t dq, dispatch_object_t dou) {
85 _dispatch_introspection_queue_item_enqueue(dq, dou);
86 };
87
88 DISPATCH_ALWAYS_INLINE
89 static inline void
90 _dispatch_introspection_queue_pop(dispatch_queue_t dq, dispatch_object_t dou) {
91 _dispatch_introspection_queue_item_dequeue(dq, dou);
92 };
93
94 void
95 _dispatch_introspection_order_record(dispatch_queue_t top_q,
96 dispatch_queue_t bottom_q);
97
98 void
99 _dispatch_introspection_target_queue_changed(dispatch_queue_t dq);
100
101 DISPATCH_ALWAYS_INLINE
102 static inline void
103 _dispatch_introspection_barrier_sync_begin(dispatch_queue_t dq,
104 dispatch_function_t func)
105 {
106 if (!_dispatch_introspection.debug_queue_inversions) return;
107 if (func != _dispatch_sync_recurse_invoke) {
108 _dispatch_introspection_order_record(dq, _dispatch_queue_get_current());
109 }
110 }
111
112 DISPATCH_ALWAYS_INLINE
113 static inline void
114 _dispatch_introspection_non_barrier_sync_begin(dispatch_queue_t dq,
115 dispatch_function_t func)
116 {
117 if (!_dispatch_introspection.debug_queue_inversions) return;
118 if (func != _dispatch_sync_recurse_invoke) {
119 _dispatch_introspection_order_record(dq, _dispatch_queue_get_current());
120 }
121 }
122
123 #endif // DISPATCH_PURE_C
124
125 #else // DISPATCH_INTROSPECTION
126
127 #define DISPATCH_INTROSPECTION_QUEUE_HEADER
128 #define DISPATCH_INTROSPECTION_QUEUE_HEADER_SIZE 0
129
130 #define _dispatch_introspection_init()
131 #define _dispatch_introspection_thread_add()
132 #define _dispatch_introspection_thread_remove()
133
134 DISPATCH_ALWAYS_INLINE
135 static inline dispatch_queue_t
136 _dispatch_introspection_queue_create(dispatch_queue_t dq) { return dq; }
137
138 DISPATCH_ALWAYS_INLINE
139 static inline void
140 _dispatch_introspection_queue_dispose(dispatch_queue_t dq) { (void)dq; }
141
142 DISPATCH_ALWAYS_INLINE
143 static inline void
144 _dispatch_introspection_queue_push_list(dispatch_queue_t dq DISPATCH_UNUSED,
145 dispatch_object_t head DISPATCH_UNUSED,
146 dispatch_object_t tail DISPATCH_UNUSED) {}
147
148 DISPATCH_ALWAYS_INLINE
149 static inline void
150 _dispatch_introspection_queue_push(dispatch_queue_t dq DISPATCH_UNUSED,
151 dispatch_object_t dou DISPATCH_UNUSED) {}
152
153 DISPATCH_ALWAYS_INLINE
154 static inline void
155 _dispatch_introspection_queue_pop(dispatch_queue_t dq DISPATCH_UNUSED,
156 dispatch_object_t dou DISPATCH_UNUSED) {}
157
158 DISPATCH_ALWAYS_INLINE
159 static inline void
160 _dispatch_introspection_queue_item_complete(
161 dispatch_object_t dou DISPATCH_UNUSED) {}
162
163 DISPATCH_ALWAYS_INLINE
164 static inline void
165 _dispatch_introspection_callout_entry(void *ctxt DISPATCH_UNUSED,
166 dispatch_function_t f DISPATCH_UNUSED) {}
167
168 DISPATCH_ALWAYS_INLINE
169 static inline void
170 _dispatch_introspection_callout_return(void *ctxt DISPATCH_UNUSED,
171 dispatch_function_t f DISPATCH_UNUSED) {}
172
173 DISPATCH_ALWAYS_INLINE
174 static inline void
175 _dispatch_introspection_target_queue_changed(
176 dispatch_queue_t dq DISPATCH_UNUSED) {}
177
178 DISPATCH_ALWAYS_INLINE
179 static inline void
180 _dispatch_introspection_barrier_sync_begin(dispatch_queue_t dq DISPATCH_UNUSED,
181 dispatch_function_t func DISPATCH_UNUSED) {}
182
183 DISPATCH_ALWAYS_INLINE
184 static inline void
185 _dispatch_introspection_non_barrier_sync_begin(dispatch_queue_t dq DISPATCH_UNUSED,
186 dispatch_function_t func DISPATCH_UNUSED) {}
187
188 #endif // DISPATCH_INTROSPECTION
189
190 #endif // __DISPATCH_INTROSPECTION_INTERNAL__