1/*
2 * Copyright (c) 2013-2014 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#ifndef __OS_VOUCHER_ACTIVITY_PRIVATE__
22#define __OS_VOUCHER_ACTIVITY_PRIVATE__
23
24#include <os/base.h>
25#include <os/object.h>
26#if !defined(__DISPATCH_BUILDING_DISPATCH__)
27#include <os/voucher_private.h>
28#endif
29
30#define OS_VOUCHER_ACTIVITY_SPI_VERSION 20140708
31
32#if OS_VOUCHER_WEAK_IMPORT
33#define OS_VOUCHER_EXPORT OS_EXPORT OS_WEAK_IMPORT
34#else
35#define OS_VOUCHER_EXPORT OS_EXPORT
36#endif
37
38__BEGIN_DECLS
39
40#if OS_VOUCHER_ACTIVITY_SPI
41
42/*!
43 * @group Voucher Activity SPI
44 * SPI intended for libtrace only
45 */
46
47/*!
48 * @typedef voucher_activity_id_t
49 *
50 * @abstract
51 * Opaque activity identifier.
52 *
53 * @discussion
54 * Scalar value type, not reference counted.
55 */
56typedef uint64_t voucher_activity_id_t;
57
58/*!
59 * @enum voucher_activity_tracepoint_type_t
60 *
61 * @abstract
62 * Types of tracepoints.
63 */
64OS_ENUM(voucher_activity_tracepoint_type, uint8_t,
65	voucher_activity_tracepoint_type_release = (1u << 0),
66	voucher_activity_tracepoint_type_debug = (1u << 1),
67	voucher_activity_tracepoint_type_error = (1u << 6) | (1u << 0),
68	voucher_activity_tracepoint_type_fault = (1u << 7) | (1u << 6) | (1u << 0),
69);
70
71/*!
72 * @enum voucher_activity_flag_t
73 *
74 * @abstract
75 * Flags to pass to voucher_activity_start/voucher_activity_start_with_location
76 */
77OS_ENUM(voucher_activity_flag, unsigned long,
78	voucher_activity_flag_default = 0,
79	voucher_activity_flag_force = 0x1,
80);
81
82/*!
83 * @typedef voucher_activity_trace_id_t
84 *
85 * @abstract
86 * Opaque tracepoint identifier.
87 */
88typedef uint64_t voucher_activity_trace_id_t;
89static const uint8_t _voucher_activity_trace_id_type_shift = 40;
90static const uint8_t _voucher_activity_trace_id_code_namespace_shift = 32;
91
92/*!
93 * @function voucher_activity_trace_id
94 *
95 * @abstract
96 * Return tracepoint identifier for specified arguments.
97 *
98 * @param type
99 * Tracepoint type from voucher_activity_tracepoint_type_t.
100 *
101 * @param code_namespace
102 * Namespace of 'code' argument.
103 *
104 * @param code
105 * Tracepoint code.
106 *
107 * @result
108 * Tracepoint identifier.
109 */
110__OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)
111OS_INLINE OS_ALWAYS_INLINE
112voucher_activity_trace_id_t
113voucher_activity_trace_id(uint8_t type, uint8_t code_namespace, uint32_t code)
114{
115	return ((voucher_activity_trace_id_t)type <<
116			_voucher_activity_trace_id_type_shift) |
117			((voucher_activity_trace_id_t)code_namespace <<
118			_voucher_activity_trace_id_code_namespace_shift) |
119			(voucher_activity_trace_id_t)code;
120}
121
122/*!
123 * @function voucher_activity_start
124 *
125 * @abstract
126 * Creates a new activity identifier and marks the current thread as
127 * participating in the activity.
128 *
129 * @discussion
130 * As part of voucher transport, activities are automatically propagated by the
131 * system to other threads and processes (across IPC).
132 *
133 * Activities persist as long as any threads in any process are marked as
134 * participating. There may be many calls to voucher_activity_end()
135 * corresponding to one call to voucher_activity_start().
136 *
137 * @param trace_id
138 * Tracepoint identifier returned by voucher_activity_trace_id(), intended for
139 * identification of the automatic tracepoint generated as part of creating the
140 * new activity.
141 *
142 * @param flags
143 * Pass voucher_activity_flag_force to indicate that existing activities
144 * on the current thread should not be inherited and that a new toplevel
145 * activity should be created.
146 *
147 * @result
148 * A new activity identifier.
149 */
150__OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)
151OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW
152voucher_activity_id_t
153voucher_activity_start(voucher_activity_trace_id_t trace_id,
154		voucher_activity_flag_t flags);
155
156/*!
157 * @function voucher_activity_start_with_location
158 *
159 * @abstract
160 * Creates a new activity identifier and marks the current thread as
161 * participating in the activity.
162 *
163 * @discussion
164 * As part of voucher transport, activities are automatically propagated by the
165 * system to other threads and processes (across IPC).
166 *
167 * Activities persist as long as any threads in any process are marked as
168 * participating. There may be many calls to voucher_activity_end()
169 * corresponding to one call to voucher_activity_start_with_location().
170 *
171 * @param trace_id
172 * Tracepoint identifier returned by voucher_activity_trace_id(), intended for
173 * identification of the automatic tracepoint generated as part of creating the
174 * new activity.
175 *
176 * @param location
177 * Location identifier for the automatic tracepoint generated as part of
178 * creating the new activity.
179 *
180 * @param flags
181 * Pass voucher_activity_flag_force to indicate that existing activities
182 * on the current thread should not be inherited and that a new toplevel
183 * activity should be created.
184 *
185 * @result
186 * A new activity identifier.
187 */
188__OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)
189OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW
190voucher_activity_id_t
191voucher_activity_start_with_location(voucher_activity_trace_id_t trace_id,
192		uint64_t location, voucher_activity_flag_t flags);
193
194/*!
195 * @function voucher_activity_end
196 *
197 * @abstract
198 * Unmarks the current thread if it is marked as particpating in the activity
199 * with the specified identifier.
200 *
201 * @discussion
202 * Activities persist as long as any threads in any process are marked as
203 * participating. There may be many calls to voucher_activity_end()
204 * corresponding to one call to voucher_activity_start() or
205 * voucher_activity_start_with_location().
206 */
207__OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)
208OS_VOUCHER_EXPORT OS_NOTHROW
209void
210voucher_activity_end(voucher_activity_id_t activity_id);
211
212/*!
213 * @function voucher_get_activities
214 *
215 * @abstract
216 * Returns the list of activity identifiers that the current thread is marked
217 * with.
218 *
219 * @param entries
220 * Pointer to an array of activity identifiers to be filled in.
221 *
222 * @param count
223 * Pointer to the requested number of activity identifiers.
224 * On output will be filled with the number of activities that are available.
225 *
226 * @result
227 * Number of activity identifiers written to 'entries'
228 */
229__OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)
230OS_VOUCHER_EXPORT OS_NOTHROW
231unsigned int
232voucher_get_activities(voucher_activity_id_t *entries, unsigned int *count);
233
234/*!
235 * @group Voucher Activity Trace SPI
236 * SPI intended for libtrace only
237 */
238
239/*!
240 * @function voucher_activity_get_namespace
241 *
242 * @abstract
243 * Returns the namespace of the current activity.
244 *
245 * @result
246 * The namespace of the current activity (if any).
247 */
248__OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)
249OS_VOUCHER_EXPORT OS_NOTHROW
250uint8_t
251voucher_activity_get_namespace(void);
252
253/*!
254 * @function voucher_activity_trace
255 *
256 * @abstract
257 * Add a tracepoint to trace buffer of the current activity.
258 *
259 * @param trace_id
260 * Tracepoint identifier returned by voucher_activity_trace_id()
261 *
262 * @param location
263 * Tracepoint location.
264 *
265 * @param buffer
266 * Pointer to packed buffer of tracepoint data.
267 *
268 * @param length
269 * Length of data at 'buffer'.
270 *
271 * @result
272 * Timestamp recorded in tracepoint or 0 if no tracepoint was recorded.
273 */
274__OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)
275OS_VOUCHER_EXPORT OS_NOTHROW
276uint64_t
277voucher_activity_trace(voucher_activity_trace_id_t trace_id, uint64_t location,
278		void *buffer, size_t length);
279
280/*!
281 * @function voucher_activity_trace_args
282 *
283 * @abstract
284 * Add a tracepoint to trace buffer of the current activity, recording
285 * specified arguments passed in registers.
286 *
287 * @param trace_id
288 * Tracepoint identifier returned by voucher_activity_trace_id()
289 *
290 * @param location
291 * Tracepoint location.
292 *
293 * @param arg1
294 * Argument to be recorded in tracepoint data.
295 *
296 * @param arg2
297 * Argument to be recorded in tracepoint data.
298 *
299 * @param arg3
300 * Argument to be recorded in tracepoint data.
301 *
302 * @param arg4
303 * Argument to be recorded in tracepoint data.
304 *
305 * @result
306 * Timestamp recorded in tracepoint or 0 if no tracepoint was recorded.
307 */
308__OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)
309OS_VOUCHER_EXPORT OS_NOTHROW
310uint64_t
311voucher_activity_trace_args(voucher_activity_trace_id_t trace_id,
312		uint64_t location, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3,
313		uintptr_t arg4);
314
315/*!
316 * @group Voucher Activity Mode SPI
317 * SPI intended for libtrace only
318 */
319
320/*!
321 * @enum voucher_activity_mode_t
322 *
323 * @abstract
324 * Voucher activity mode.
325 *
326 * @discussion
327 * Configure at process start by setting the OS_ACTIVITY_MODE environment
328 * variable.
329 */
330OS_ENUM(voucher_activity_mode, unsigned long,
331	voucher_activity_mode_disable = 0,
332	voucher_activity_mode_release = (1u << 0),
333	voucher_activity_mode_debug = (1u << 1),
334	voucher_activity_mode_stream = (1u << 2),
335);
336
337/*!
338 * @function voucher_activity_get_mode
339 *
340 * @abstract
341 * Return current mode of voucher activity subsystem.
342 *
343 * @result
344 * Value from voucher_activity_mode_t enum.
345 */
346__OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)
347OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW
348voucher_activity_mode_t
349voucher_activity_get_mode(void);
350
351/*!
352 * @function voucher_activity_set_mode_4libtrace(void)
353 *
354 * @abstract
355 * Set the current mode of voucher activity subsystem.
356 *
357 * @param mode
358 * The new mode.
359 *
360 * Note that the new mode will take effect soon, but not immediately.
361 */
362__OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)
363OS_VOUCHER_EXPORT OS_NOTHROW
364void
365voucher_activity_set_mode_4libtrace(voucher_activity_mode_t mode);
366
367/*!
368 * @group Voucher Activity Metadata SPI
369 * SPI intended for libtrace only
370 */
371
372/*!
373 * @function voucher_activity_get_metadata_buffer
374 *
375 * @abstract
376 * Return address and length of buffer in the process trace memory area
377 * reserved for libtrace metadata.
378 *
379 * @param length
380 * Pointer to size_t variable, filled with length of metadata buffer.
381 *
382 * @result
383 * Address of metadata buffer.
384 */
385__OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)
386OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW OS_NONNULL_ALL
387void*
388voucher_activity_get_metadata_buffer(size_t *length);
389
390#endif // OS_VOUCHER_ACTIVITY_SPI
391
392#if OS_VOUCHER_ACTIVITY_BUFFER_SPI
393
394/*!
395 * @group Voucher Activity Tracepoint SPI
396 * SPI intended for diagnosticd only
397 */
398
399OS_ENUM(_voucher_activity_tracepoint_flag, uint16_t,
400	_voucher_activity_trace_flag_buffer_empty = 0,
401	_voucher_activity_trace_flag_tracepoint = (1u << 0),
402	_voucher_activity_trace_flag_tracepoint_args = (1u << 1),
403	_voucher_activity_trace_flag_wide_first = (1u << 6),
404	_voucher_activity_trace_flag_wide_second = (1u << 6) | (1u << 7),
405	_voucher_activity_trace_flag_start = (1u << 8),
406	_voucher_activity_trace_flag_end = (1u << 8) | (1u << 9),
407	_voucher_activity_trace_flag_libdispatch = (1u << 13),
408	_voucher_activity_trace_flag_activity = (1u << 14),
409	_voucher_activity_trace_flag_buffer_header = (1u << 15),
410);
411
412// for tracepoints with _voucher_activity_trace_flag_libdispatch
413OS_ENUM(_voucher_activity_tracepoint_namespace, uint8_t,
414	_voucher_activity_tracepoint_namespace_ipc = 0x1
415);
416OS_ENUM(_voucher_activity_tracepoint_code, uint32_t,
417	_voucher_activity_tracepoint_namespace_ipc_send = 0x1,
418	_voucher_activity_tracepoint_namespace_ipc_receive = 0x2,
419);
420
421typedef struct _voucher_activity_tracepoint_s {
422	uint16_t vat_flags;		// voucher_activity_tracepoint_flag_t
423	uint8_t  vat_type;		// voucher_activity_tracepoint_type_t
424	uint8_t  vat_namespace;	// namespace for tracepoint code
425	uint32_t vat_code;		// tracepoint code
426	uint64_t vat_thread;	// pthread_t
427	uint64_t vat_timestamp;	// absolute time
428	uint64_t vat_location;	// tracepoint PC
429	uint64_t vat_data[4];	// trace data
430} *_voucher_activity_tracepoint_t;
431
432/*!
433 * @group Voucher Activity Buffer Internals
434 * SPI intended for diagnosticd only
435 * Layout of structs is subject to change without notice
436 */
437
438#include <sys/queue.h>
439#include <atm/atm_types.h>
440#include <os/lock_private.h>
441
442static const atm_subaid32_t _voucher_default_activity_subid =
443		ATM_SUBAID32_MAX-1;
444
445static const size_t _voucher_activity_buffer_size = 4096;
446static const size_t _voucher_activity_tracepoints_per_buffer =
447		_voucher_activity_buffer_size /
448		sizeof(struct _voucher_activity_tracepoint_s);
449typedef uint8_t _voucher_activity_buffer_t[_voucher_activity_buffer_size];
450
451struct _voucher_activity_self_metadata_s {
452	struct _voucher_activity_metadata_opaque_s *vasm_baseaddr;
453};
454typedef struct _voucher_activity_metadata_opaque_s {
455	_voucher_activity_buffer_t vam_kernel_metadata;
456	_voucher_activity_buffer_t vam_client_metadata;
457	union {
458		struct _voucher_activity_self_metadata_s vam_self_metadata;
459		_voucher_activity_buffer_t vam_self_metadata_opaque;
460	};
461} *_voucher_activity_metadata_opaque_t;
462
463typedef os_lock_handoff_s _voucher_activity_lock_s;
464
465typedef struct _voucher_atm_s {
466	int32_t volatile vatm_refcnt;
467	mach_voucher_t vatm_kvoucher;
468	atm_aid_t vatm_id;
469	atm_mailbox_offset_t vatm_mailbox_offset;
470	TAILQ_ENTRY(_voucher_atm_s) vatm_list;
471#if __LP64__
472	uintptr_t vatm_pad[3];
473	// cacheline
474#endif
475	_voucher_activity_lock_s vatm_activities_lock;
476	TAILQ_HEAD(_voucher_atm_activities_s, _voucher_activity_s) vatm_activities;
477	TAILQ_HEAD(, _voucher_activity_s) vatm_used_activities;
478} *_voucher_atm_t;
479
480// must match layout of _voucher_activity_tracepoint_s
481typedef struct _voucher_activity_buffer_header_s {
482	uint16_t vabh_flags;	// _voucher_activity_trace_flag_buffer_header
483	uint8_t  vabh_unused[6];
484	uint64_t vabh_thread;
485	uint64_t vabh_timestamp;
486	uint32_t volatile vabh_next_tracepoint_idx;
487	uint32_t vabh_sequence_no;
488	voucher_activity_id_t vabh_activity_id;
489	uint64_t vabh_reserved;
490	TAILQ_ENTRY(_voucher_activity_buffer_header_s) vabh_list;
491} *_voucher_activity_buffer_header_t;
492
493// must match layout of _voucher_activity_buffer_header_s
494typedef struct _voucher_activity_s {
495	// first tracepoint entry
496	// must match layout of _voucher_activity_tracepoint_s
497	uint16_t va_flags;		// _voucher_activity_trace_flag_buffer_header |
498							// _voucher_activity_trace_flag_activity |
499							// _voucher_activity_trace_flag_start |
500							// _voucher_activity_trace_flag_wide_first
501	uint8_t  va_type;
502	uint8_t  va_namespace;
503	uint32_t va_code;
504	uint64_t va_thread;
505	uint64_t va_timestamp;
506	uint32_t volatile vabh_next_tracepoint_idx;
507	uint32_t volatile va_max_sequence_no;
508	voucher_activity_id_t va_id;
509	int32_t volatile va_use_count;
510	uint32_t va_buffer_limit;
511	TAILQ_HEAD(_voucher_activity_buffer_list_s,
512			_voucher_activity_buffer_header_s) va_buffers;
513#if !__LP64__
514	uint64_t va_pad;
515#endif
516
517	// second tracepoint entry
518	// must match layout of _voucher_activity_tracepoint_s
519	uint16_t va_flags2;
520	uint8_t va_unused2[2];
521	int32_t volatile va_refcnt;
522	uint64_t va_location;
523	_voucher_activity_buffer_header_t volatile va_current_buffer;
524	_voucher_atm_t va_atm;
525	_voucher_activity_lock_s va_buffers_lock;
526	uintptr_t va_pad2[2];
527
528#if __LP64__
529	// third tracepoint entry
530	// must match layout of _voucher_activity_tracepoint_s
531	uint16_t va_flags3;
532	uint8_t va_unused3[6];
533	uintptr_t va_pad3;
534#endif
535	TAILQ_ENTRY(_voucher_activity_s) va_list;
536	TAILQ_ENTRY(_voucher_activity_s) va_atm_list;
537	TAILQ_ENTRY(_voucher_activity_s) va_atm_used_list;
538} *_voucher_activity_t;
539
540#endif // OS_VOUCHER_ACTIVITY_BUFFER_SPI
541
542__END_DECLS
543
544#endif // __OS_VOUCHER_ACTIVITY_PRIVATE__
545