2 * Copyright (c) 2010-2013 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_TRACE__
28 #define __DISPATCH_TRACE__
32 #if DISPATCH_USE_DTRACE_INTROSPECTION
33 #define _dispatch_trace_callout(_c, _f, _dcc) do { \
34 if (slowpath(DISPATCH_CALLOUT_ENTRY_ENABLED()) || \
35 slowpath(DISPATCH_CALLOUT_RETURN_ENABLED())) { \
36 dispatch_queue_t _dq = _dispatch_queue_get_current(); \
37 const char *_label = _dq && _dq->dq_label ? _dq->dq_label : ""; \
38 dispatch_function_t _func = (dispatch_function_t)(_f); \
40 DISPATCH_CALLOUT_ENTRY(_dq, _label, _func, _ctxt); \
42 DISPATCH_CALLOUT_RETURN(_dq, _label, _func, _ctxt); \
47 #elif DISPATCH_INTROSPECTION
48 #define _dispatch_trace_callout(_c, _f, _dcc) \
49 do { (void)(_c); (void)(_f); _dcc; } while (0)
50 #endif // DISPATCH_USE_DTRACE_INTROSPECTION || DISPATCH_INTROSPECTION
52 #if DISPATCH_USE_DTRACE_INTROSPECTION || DISPATCH_INTROSPECTION
53 DISPATCH_ALWAYS_INLINE
55 _dispatch_trace_client_callout(void *ctxt
, dispatch_function_t f
)
57 dispatch_function_t func
= (f
== _dispatch_call_block_and_release
&&
58 ctxt
? _dispatch_Block_invoke(ctxt
) : f
);
59 _dispatch_introspection_callout_entry(ctxt
, func
);
60 _dispatch_trace_callout(ctxt
, func
, _dispatch_client_callout(ctxt
, f
));
61 _dispatch_introspection_callout_return(ctxt
, func
);
64 DISPATCH_ALWAYS_INLINE
66 _dispatch_trace_client_callout2(void *ctxt
, size_t i
, void (*f
)(void *, size_t))
68 dispatch_function_t func
= (dispatch_function_t
)f
;
69 _dispatch_introspection_callout_entry(ctxt
, func
);
70 _dispatch_trace_callout(ctxt
, func
, _dispatch_client_callout2(ctxt
, i
, f
));
71 _dispatch_introspection_callout_return(ctxt
, func
);
74 #define _dispatch_client_callout _dispatch_trace_client_callout
75 #define _dispatch_client_callout2 _dispatch_trace_client_callout2
76 #endif // DISPATCH_USE_DTRACE_INTROSPECTION || DISPATCH_INTROSPECTION
78 #if DISPATCH_USE_DTRACE_INTROSPECTION
79 #define _dispatch_trace_continuation(_q, _o, _t) do { \
80 dispatch_queue_t _dq = (_q); \
81 const char *_label = _dq && _dq->dq_label ? _dq->dq_label : ""; \
82 struct dispatch_object_s *_do = (_o); \
83 dispatch_continuation_t _dc; \
85 dispatch_function_t _func; \
87 if (_dispatch_object_has_vtable(_do)) { \
88 _kind = (char*)dx_kind(_do); \
89 if ((dx_type(_do) & _DISPATCH_META_TYPE_MASK) == \
90 _DISPATCH_SOURCE_TYPE && (_dq) != &_dispatch_mgr_q) { \
91 dispatch_source_t _ds = (dispatch_source_t)_do; \
92 _dc = os_atomic_load(&_ds->ds_refs->ds_handler[ \
93 DS_EVENT_HANDLER], relaxed); \
94 _func = _dc ? _dc->dc_func : NULL; \
95 _ctxt = _dc ? _dc->dc_ctxt : NULL; \
97 _func = (dispatch_function_t)_dispatch_queue_invoke; \
98 _ctxt = _do->do_ctxt; \
102 _ctxt = _dc->dc_ctxt; \
103 if (_dc->dc_flags & DISPATCH_OBJ_SYNC_WAITER_BIT) { \
104 _kind = "semaphore"; \
105 _func = (dispatch_function_t)dispatch_semaphore_signal; \
106 } else if (_dc->dc_flags & DISPATCH_OBJ_BLOCK_BIT) { \
108 _func = _dispatch_Block_invoke(_dc->dc_ctxt); \
110 _kind = "function"; \
111 _func = _dc->dc_func; \
114 _t(_dq, _label, _do, _kind, _func, _ctxt); \
116 #elif DISPATCH_INTROSPECTION
117 #define _dispatch_trace_continuation(_q, _o, _t) \
118 do { (void)(_q); (void)(_o); } while(0)
119 #define DISPATCH_QUEUE_PUSH_ENABLED() 0
120 #define DISPATCH_QUEUE_POP_ENABLED() 0
121 #endif // DISPATCH_USE_DTRACE_INTROSPECTION || DISPATCH_INTROSPECTION
123 #if DISPATCH_USE_DTRACE_INTROSPECTION || DISPATCH_INTROSPECTION
124 DISPATCH_ALWAYS_INLINE
126 _dispatch_trace_root_queue_push_list(dispatch_queue_t dq
,
127 dispatch_object_t _head
, dispatch_object_t _tail
, int n
)
129 if (slowpath(DISPATCH_QUEUE_PUSH_ENABLED())) {
130 struct dispatch_object_s
*dou
= _head
._do
;
132 _dispatch_trace_continuation(dq
, dou
, DISPATCH_QUEUE_PUSH
);
133 } while (dou
!= _tail
._do
&& (dou
= dou
->do_next
));
135 _dispatch_introspection_queue_push_list(dq
, _head
, _tail
);
136 _dispatch_root_queue_push_inline(dq
, _head
, _tail
, n
);
139 DISPATCH_ALWAYS_INLINE
141 _dispatch_trace_queue_push_inline(dispatch_queue_t dq
, dispatch_object_t _tail
,
144 if (slowpath(DISPATCH_QUEUE_PUSH_ENABLED())) {
145 struct dispatch_object_s
*dou
= _tail
._do
;
146 _dispatch_trace_continuation(dq
, dou
, DISPATCH_QUEUE_PUSH
);
148 _dispatch_introspection_queue_push(dq
, _tail
);
149 _dispatch_queue_push_inline(dq
, _tail
, qos
);
152 DISPATCH_ALWAYS_INLINE
154 _dispatch_trace_continuation_push(dispatch_queue_t dq
, dispatch_object_t _tail
)
156 if (slowpath(DISPATCH_QUEUE_PUSH_ENABLED())) {
157 struct dispatch_object_s
*dou
= _tail
._do
;
158 _dispatch_trace_continuation(dq
, dou
, DISPATCH_QUEUE_PUSH
);
160 _dispatch_introspection_queue_push(dq
, _tail
);
163 #define _dispatch_root_queue_push_inline _dispatch_trace_root_queue_push_list
164 #define _dispatch_queue_push_inline _dispatch_trace_queue_push_inline
166 DISPATCH_ALWAYS_INLINE
168 _dispatch_trace_continuation_pop(dispatch_queue_t dq
, dispatch_object_t dou
)
170 if (slowpath(DISPATCH_QUEUE_POP_ENABLED())) {
171 _dispatch_trace_continuation(dq
, dou
._do
, DISPATCH_QUEUE_POP
);
173 _dispatch_introspection_queue_pop(dq
, dou
);
176 #define _dispatch_trace_continuation_push(dq, dou) \
177 do { (void)(dq); (void)(dou); } while(0)
178 #define _dispatch_trace_continuation_pop(dq, dou) \
179 do { (void)(dq); (void)(dou); } while(0)
180 #endif // DISPATCH_USE_DTRACE_INTROSPECTION || DISPATCH_INTROSPECTION
182 #if DISPATCH_USE_DTRACE
183 static inline dispatch_function_t
184 _dispatch_trace_timer_function(dispatch_timer_source_refs_t dr
)
186 dispatch_continuation_t dc
;
187 dc
= os_atomic_load(&dr
->ds_handler
[DS_EVENT_HANDLER
], relaxed
);
188 return dc
? dc
->dc_func
: NULL
;
191 DISPATCH_ALWAYS_INLINE
192 static inline dispatch_trace_timer_params_t
193 _dispatch_trace_timer_params(dispatch_clock_t clock
,
194 struct dispatch_timer_source_s
*values
, uint64_t deadline
,
195 dispatch_trace_timer_params_t params
)
197 #define _dispatch_trace_time2nano3(t) \
198 (clock == DISPATCH_CLOCK_MACH ? _dispatch_time_mach2nano(t) : (t))
199 #define _dispatch_trace_time2nano2(v, t) ({ uint64_t _t = (t); \
200 (v) >= INT64_MAX ? -1ll : (int64_t)_dispatch_trace_time2nano3(_t);})
201 #define _dispatch_trace_time2nano(v) ({ uint64_t _t; \
202 _t = _dispatch_trace_time2nano3(v); _t >= INT64_MAX ? -1ll : \
205 params
->deadline
= (int64_t)deadline
;
207 uint64_t now
= _dispatch_time_now(clock
);
208 params
->deadline
= _dispatch_trace_time2nano2(values
->target
,
209 values
->target
< now
? 0 : values
->target
- now
);
211 uint64_t leeway
= values
->deadline
- values
->target
;
212 params
->interval
= _dispatch_trace_time2nano(values
->interval
);
213 params
->leeway
= _dispatch_trace_time2nano(leeway
);
217 DISPATCH_ALWAYS_INLINE
219 _dispatch_trace_timer_configure_enabled(void)
221 return slowpath(DISPATCH_TIMER_CONFIGURE_ENABLED());
224 DISPATCH_ALWAYS_INLINE
226 _dispatch_trace_timer_configure(dispatch_source_t ds
, dispatch_clock_t clock
,
227 struct dispatch_timer_source_s
*values
)
229 dispatch_timer_source_refs_t dr
= ds
->ds_timer_refs
;
230 struct dispatch_trace_timer_params_s params
;
231 DISPATCH_TIMER_CONFIGURE(ds
, _dispatch_trace_timer_function(dr
),
232 _dispatch_trace_timer_params(clock
, values
, 0, ¶ms
));
235 DISPATCH_ALWAYS_INLINE
237 _dispatch_trace_timer_program(dispatch_timer_source_refs_t dr
, uint64_t deadline
)
239 if (slowpath(DISPATCH_TIMER_PROGRAM_ENABLED())) {
240 if (deadline
&& dr
) {
241 dispatch_source_t ds
= _dispatch_source_from_refs(dr
);
242 dispatch_clock_t clock
= DISPATCH_TIMER_CLOCK(dr
->du_ident
);
243 struct dispatch_trace_timer_params_s params
;
244 DISPATCH_TIMER_PROGRAM(ds
, _dispatch_trace_timer_function(dr
),
245 _dispatch_trace_timer_params(clock
, &dr
->dt_timer
,
251 DISPATCH_ALWAYS_INLINE
253 _dispatch_trace_timer_wake(dispatch_timer_source_refs_t dr
)
255 if (slowpath(DISPATCH_TIMER_WAKE_ENABLED())) {
257 dispatch_source_t ds
= _dispatch_source_from_refs(dr
);
258 DISPATCH_TIMER_WAKE(ds
, _dispatch_trace_timer_function(dr
));
263 DISPATCH_ALWAYS_INLINE
265 _dispatch_trace_timer_fire(dispatch_timer_source_refs_t dr
, uint64_t data
,
268 if (slowpath(DISPATCH_TIMER_FIRE_ENABLED())) {
269 if (!(data
- missed
) && dr
) {
270 dispatch_source_t ds
= _dispatch_source_from_refs(dr
);
271 DISPATCH_TIMER_FIRE(ds
, _dispatch_trace_timer_function(dr
));
278 #define _dispatch_trace_timer_configure_enabled() false
279 #define _dispatch_trace_timer_configure(ds, clock, values) \
280 do { (void)(ds); (void)(clock); (void)(values); } while(0)
281 #define _dispatch_trace_timer_program(dr, deadline) \
282 do { (void)(dr); (void)(deadline); } while(0)
283 #define _dispatch_trace_timer_wake(dr) \
284 do { (void)(dr); } while(0)
285 #define _dispatch_trace_timer_fire(dr, data, missed) \
286 do { (void)(dr); (void)(data); (void)(missed); } while(0)
288 #endif // DISPATCH_USE_DTRACE
290 #endif // DISPATCH_PURE_C
292 #endif // __DISPATCH_TRACE__