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