]> git.saurik.com Git - apple/libdispatch.git/blob - src/trace.h
libdispatch-187.10.tar.gz
[apple/libdispatch.git] / src / trace.h
1 /*
2 * Copyright (c) 2010-2011 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_TRACE__
28 #define __DISPATCH_TRACE__
29
30 #if DISPATCH_USE_DTRACE
31
32 #include "provider.h"
33
34 #define _dispatch_trace_callout(_c, _f, _dcc) do { \
35 if (slowpath(DISPATCH_CALLOUT_ENTRY_ENABLED()) || \
36 slowpath(DISPATCH_CALLOUT_RETURN_ENABLED())) { \
37 dispatch_queue_t _dq = _dispatch_queue_get_current(); \
38 char *_label = _dq ? _dq->dq_label : ""; \
39 dispatch_function_t _func = (dispatch_function_t)(_f); \
40 void *_ctxt = (_c); \
41 DISPATCH_CALLOUT_ENTRY(_dq, _label, _func, _ctxt); \
42 _dcc; \
43 DISPATCH_CALLOUT_RETURN(_dq, _label, _func, _ctxt); \
44 return; \
45 } \
46 return _dcc; \
47 } while (0)
48
49 DISPATCH_ALWAYS_INLINE
50 static inline void
51 _dispatch_trace_client_callout(void *ctxt, dispatch_function_t f)
52 {
53 _dispatch_trace_callout(ctxt, f == _dispatch_call_block_and_release &&
54 ctxt ? ((struct Block_basic *)ctxt)->Block_invoke : f,
55 _dispatch_client_callout(ctxt, f));
56 }
57
58 DISPATCH_ALWAYS_INLINE
59 static inline void
60 _dispatch_trace_client_callout2(void *ctxt, size_t i, void (*f)(void *, size_t))
61 {
62 _dispatch_trace_callout(ctxt, f, _dispatch_client_callout2(ctxt, i, f));
63 }
64
65 #ifdef __BLOCKS__
66 DISPATCH_ALWAYS_INLINE
67 static inline void
68 _dispatch_trace_client_callout_block(dispatch_block_t b)
69 {
70 struct Block_basic *bb = (void*)b;
71 _dispatch_trace_callout(b, bb->Block_invoke,
72 _dispatch_client_callout(b, (dispatch_function_t)bb->Block_invoke));
73 }
74 #endif
75
76 #define _dispatch_client_callout _dispatch_trace_client_callout
77 #define _dispatch_client_callout2 _dispatch_trace_client_callout2
78 #define _dispatch_client_callout_block _dispatch_trace_client_callout_block
79
80 #define _dispatch_trace_continuation(_q, _o, _t) do { \
81 dispatch_queue_t _dq = (_q); \
82 char *_label = _dq ? _dq->dq_label : ""; \
83 struct dispatch_object_s *_do = (_o); \
84 char *_kind; \
85 dispatch_function_t _func; \
86 void *_ctxt; \
87 if (DISPATCH_OBJ_IS_VTABLE(_do)) { \
88 _ctxt = _do->do_ctxt; \
89 _kind = (char*)dx_kind(_do); \
90 if (dx_type(_do) == DISPATCH_SOURCE_KEVENT_TYPE && \
91 (_dq) != &_dispatch_mgr_q) { \
92 _func = ((dispatch_source_t)_do)->ds_refs->ds_handler_func; \
93 } else { \
94 _func = (dispatch_function_t)_dispatch_queue_invoke; \
95 } \
96 } else { \
97 struct dispatch_continuation_s *_dc = (void*)(_do); \
98 _ctxt = _dc->dc_ctxt; \
99 if ((long)_dc->do_vtable & DISPATCH_OBJ_SYNC_SLOW_BIT) { \
100 _kind = "semaphore"; \
101 _func = (dispatch_function_t)dispatch_semaphore_signal; \
102 } else if (_dc->dc_func == _dispatch_call_block_and_release) { \
103 _kind = "block"; \
104 _func = ((struct Block_basic *)_dc->dc_ctxt)->Block_invoke;\
105 } else { \
106 _kind = "function"; \
107 _func = _dc->dc_func; \
108 } \
109 } \
110 _t(_dq, _label, _do, _kind, _func, _ctxt); \
111 } while (0)
112
113 DISPATCH_ALWAYS_INLINE
114 static inline void
115 _dispatch_trace_queue_push_list(dispatch_queue_t dq, dispatch_object_t _head,
116 dispatch_object_t _tail)
117 {
118 if (slowpath(DISPATCH_QUEUE_PUSH_ENABLED())) {
119 struct dispatch_object_s *dou = _head._do;
120 do {
121 _dispatch_trace_continuation(dq, dou, DISPATCH_QUEUE_PUSH);
122 } while (dou != _tail._do && (dou = dou->do_next));
123 }
124 _dispatch_queue_push_list(dq, _head, _tail);
125 }
126
127 DISPATCH_ALWAYS_INLINE
128 static inline void
129 _dispatch_queue_push_notrace(dispatch_queue_t dq, dispatch_object_t dou)
130 {
131 _dispatch_queue_push_list(dq, dou, dou);
132 }
133
134 #define _dispatch_queue_push_list _dispatch_trace_queue_push_list
135
136 DISPATCH_ALWAYS_INLINE
137 static inline void
138 _dispatch_trace_continuation_pop(dispatch_queue_t dq,
139 dispatch_object_t dou)
140 {
141 if (slowpath(DISPATCH_QUEUE_POP_ENABLED())) {
142 _dispatch_trace_continuation(dq, dou._do, DISPATCH_QUEUE_POP);
143 }
144 }
145 #else
146
147 #define _dispatch_queue_push_notrace _dispatch_queue_push
148 #define _dispatch_trace_continuation_pop(dq, dou)
149
150 #endif // DISPATCH_USE_DTRACE
151
152 #endif // __DISPATCH_TRACE__