1 // Copyright 2017 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // 6 // The ABI-stable entry points used by trace instrumentation libraries. 7 // 8 // Trace handlers manage the configuration, lifecycle, and external communication 9 // of the trace engine. The trace engine binds to a single trace handler for 10 // the duration of a trace. During the trace, the trace engine invokes methods 11 // on the trace handler to ask about enabled categories and to report relevant 12 // state changes. 13 // 14 // Client code shouldn't be using these APIs directly. 15 // See <trace/event.h> for instrumentation macros. 16 // 17 18 #pragma once 19 20 #include <stdbool.h> 21 22 #include <zircon/compiler.h> 23 #include <zircon/types.h> 24 25 #include <lib/async/dispatcher.h> 26 #include <trace-engine/instrumentation.h> 27 28 __BEGIN_CDECLS 29 30 // Trace handler interface. 31 // 32 // Implementations must supply valid function pointers for each function 33 // defined in the |ops| structure. 34 typedef struct trace_handler_ops trace_handler_ops_t; 35 36 typedef struct trace_handler { 37 const trace_handler_ops_t* ops; 38 } trace_handler_t; 39 40 struct trace_handler_ops { 41 // Called by the trace engine to ask whether the specified category is enabled. 42 // 43 // This method may be called frequently so it must be efficiently implemented. 44 // Clients may cache the results while a trace is running; dynamic changes 45 // to the enabled categories may go unnoticed until the next trace. 46 // 47 // |handler| is the trace handler object itself. 48 // |category| is the name of the category. 49 // 50 // Called by instrumentation on any thread. Must be thread-safe. 51 bool (*is_category_enabled)(trace_handler_t* handler, const char* category); 52 53 // Called by the trace engine to indicate it has completed startup. 54 void (*trace_started)(trace_handler_t* handler); 55 56 // Called by the trace engine when tracing has stopped. 57 // 58 // The trace collection status is |ZX_OK| if trace collection was successful. 59 // An error indicates that the trace data may be inaccurate or incomplete. 60 // 61 // |handler| is the trace handler object itself. 62 // |async| is the trace engine's asynchronous dispatcher. 63 // |disposition| is |ZX_OK| if tracing stopped normally, otherwise indicates 64 // that tracing was aborted due to an error. 65 // |buffer_bytes_written| is number of bytes which were written to the trace buffer. 66 // 67 // Called on an asynchronous dispatch thread. 68 void (*trace_stopped)(trace_handler_t* handler, async_dispatcher_t* dispatcher, 69 zx_status_t disposition, size_t buffer_bytes_written); 70 71 // Called by the trace engine after an attempt to allocate space 72 // for a new record has failed because the buffer is full. 73 // 74 // Called by instrumentation on any thread. Must be thread-safe. 75 void (*notify_buffer_full)(trace_handler_t* handler, 76 uint32_t wrapped_count, 77 uint64_t durable_data_end); 78 }; 79 80 // Asynchronously starts the trace engine. 81 // 82 // |async| is the asynchronous dispatcher which the trace engine will use for dispatch (borrowed). 83 // |handler| is the trace handler which will handle lifecycle events (borrowed). 84 // |buffer| is the trace buffer into which the trace engine will write trace events (borrowed). 85 // |buffer_num_bytes| is the size of the trace buffer in bytes. 86 // 87 // Returns |ZX_OK| if tracing is ready to go. 88 // Returns |ZX_ERR_BAD_STATE| if tracing is already in progress. 89 // Returns |ZX_ERR_NO_MEMORY| if allocation failed. 90 // 91 // This function is thread-safe. 92 // 93 // NOTE: Asynchronous dispatcher shutdown behavior: 94 // 95 // The trace engine will attempt to stop itself automatically when the 96 // asynchronous dispatcher specified in |async| begins the process of shutting 97 // itself down (usually just prior to the dispatcher's destruction). However, 98 // the trace engine may fail to come to a complete stop if there remain outstanding 99 // references to the trace context during dispatcher shutdown. When this happens, 100 // the trace handler will not be notified of trace completion and subsequent calls 101 // to |trace_start_engine()| will return |ZX_ERR_BAD_STATE|. 102 // 103 // For this reason, it is a good idea to call |trace_stop_engine()| and wait 104 // for the handler to receive the |trace_handler_ops.trace_stopped()| callback 105 // prior to shutting down the trace engine's asynchronous dispatcher. 106 // 107 // Better yet, don't shut down the trace engine's asynchronous dispatcher unless 108 // the process is already about to exit. 109 zx_status_t trace_start_engine(async_dispatcher_t* dispatcher, 110 trace_handler_t* handler, 111 trace_buffering_mode_t buffering_mode, 112 void* buffer, 113 size_t buffer_num_bytes); 114 115 // Asynchronously stops the trace engine. 116 // 117 // The trace handler's |trace_stopped()| method will be invoked asynchronously 118 // when the trace engine transitions to the |TRACE_STOPPED| states. 119 // 120 // |disposition| is |ZX_OK| if tracing is being stopped normally, otherwise indicates 121 // that tracing is being aborted due to an error. 122 // 123 // Returns |ZX_OK| if the current state is |TRACE_STARTED| or |TRACE_STOPPING|. 124 // Returns |ZX_ERR_BAD_STATE| if current state is |TRACE_STOPPED|. 125 // 126 // This function is thread-safe. 127 zx_status_t trace_stop_engine(zx_status_t disposition); 128 129 // Asynchronously notifies the engine that buffers up to |wrapped_count| 130 // have been saved. 131 // 132 // Returns |ZX_OK| if the current state is |TRACE_STARTED| or |TRACE_STOPPING|. 133 // Returns |ZX_ERR_BAD_STATE| if current state is |TRACE_STOPPED|. 134 // 135 // This function is thread-safe. 136 zx_status_t trace_engine_mark_buffer_saved(uint32_t wrapped_count, 137 uint64_t durable_data_end); 138 139 __END_CDECLS 140