xref: /trueos/lib/libdispatch/private/voucher_activity_private.h (revision bf5f91cb28c5878845eb00fbf329c042f6c643c9)
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  */
56 typedef uint64_t voucher_activity_id_t;
57 
58 /*!
59  * @enum voucher_activity_tracepoint_type_t
60  *
61  * @abstract
62  * Types of tracepoints.
63  */
64 OS_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  */
77 OS_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  */
88 typedef uint64_t voucher_activity_trace_id_t;
89 static const uint8_t _voucher_activity_trace_id_type_shift = 40;
90 static 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  */
__OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)110 __OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)
111 OS_INLINE OS_ALWAYS_INLINE
112 voucher_activity_trace_id_t
113 voucher_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)
151 OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW
152 voucher_activity_id_t
153 voucher_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)
189 OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW
190 voucher_activity_id_t
191 voucher_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)
208 OS_VOUCHER_EXPORT OS_NOTHROW
209 void
210 voucher_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)
230 OS_VOUCHER_EXPORT OS_NOTHROW
231 unsigned int
232 voucher_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)
249 OS_VOUCHER_EXPORT OS_NOTHROW
250 uint8_t
251 voucher_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)
275 OS_VOUCHER_EXPORT OS_NOTHROW
276 uint64_t
277 voucher_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)
309 OS_VOUCHER_EXPORT OS_NOTHROW
310 uint64_t
311 voucher_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  */
330 OS_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)
347 OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW
348 voucher_activity_mode_t
349 voucher_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)
363 OS_VOUCHER_EXPORT OS_NOTHROW
364 void
365 voucher_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)
386 OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW OS_NONNULL_ALL
387 void*
388 voucher_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 
399 OS_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
413 OS_ENUM(_voucher_activity_tracepoint_namespace, uint8_t,
414 	_voucher_activity_tracepoint_namespace_ipc = 0x1
415 );
416 OS_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 
421 typedef 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 
442 static const atm_subaid32_t _voucher_default_activity_subid =
443 		ATM_SUBAID32_MAX-1;
444 
445 static const size_t _voucher_activity_buffer_size = 4096;
446 static const size_t _voucher_activity_tracepoints_per_buffer =
447 		_voucher_activity_buffer_size /
448 		sizeof(struct _voucher_activity_tracepoint_s);
449 typedef uint8_t _voucher_activity_buffer_t[_voucher_activity_buffer_size];
450 
451 struct _voucher_activity_self_metadata_s {
452 	struct _voucher_activity_metadata_opaque_s *vasm_baseaddr;
453 };
454 typedef 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 
463 typedef os_lock_handoff_s _voucher_activity_lock_s;
464 
465 typedef 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
481 typedef 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
494 typedef 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