Serenity Operating System
at master 155 lines 4.0 kB view raw
1/* 2 * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/Error.h> 10#include <Kernel/KBuffer.h> 11 12namespace Kernel { 13 14class KBufferBuilder; 15struct RegisterState; 16 17struct [[gnu::packed]] MallocPerformanceEvent { 18 size_t size; 19 FlatPtr ptr; 20}; 21 22struct [[gnu::packed]] FreePerformanceEvent { 23 size_t size; 24 FlatPtr ptr; 25}; 26 27struct [[gnu::packed]] MmapPerformanceEvent { 28 size_t size; 29 FlatPtr ptr; 30 char name[64]; 31}; 32 33struct [[gnu::packed]] MunmapPerformanceEvent { 34 size_t size; 35 FlatPtr ptr; 36}; 37 38struct [[gnu::packed]] ProcessCreatePerformanceEvent { 39 pid_t parent_pid; 40 char executable[64]; 41}; 42 43struct [[gnu::packed]] ProcessExecPerformanceEvent { 44 char executable[64]; 45}; 46 47struct [[gnu::packed]] ThreadCreatePerformanceEvent { 48 pid_t parent_tid; 49}; 50 51struct [[gnu::packed]] ContextSwitchPerformanceEvent { 52 pid_t next_pid; 53 u32 next_tid; 54}; 55 56struct [[gnu::packed]] KMallocPerformanceEvent { 57 size_t size; 58 FlatPtr ptr; 59}; 60 61struct [[gnu::packed]] KFreePerformanceEvent { 62 size_t size; 63 FlatPtr ptr; 64}; 65 66struct [[gnu::packed]] SignpostPerformanceEvent { 67 FlatPtr arg1; 68 FlatPtr arg2; 69}; 70 71struct [[gnu::packed]] ReadPerformanceEvent { 72 int fd; 73 size_t size; 74 size_t filename_index; 75 size_t start_timestamp; 76 bool success; 77}; 78 79struct [[gnu::packed]] PerformanceEvent { 80 u32 type { 0 }; 81 u8 stack_size { 0 }; 82 u32 pid { 0 }; 83 u32 tid { 0 }; 84 u64 timestamp; 85 u32 lost_samples; 86 union { 87 MallocPerformanceEvent malloc; 88 FreePerformanceEvent free; 89 MmapPerformanceEvent mmap; 90 MunmapPerformanceEvent munmap; 91 ProcessCreatePerformanceEvent process_create; 92 ProcessExecPerformanceEvent process_exec; 93 ThreadCreatePerformanceEvent thread_create; 94 ContextSwitchPerformanceEvent context_switch; 95 KMallocPerformanceEvent kmalloc; 96 KFreePerformanceEvent kfree; 97 SignpostPerformanceEvent signpost; 98 ReadPerformanceEvent read; 99 } data; 100 static constexpr size_t max_stack_frame_count = 64; 101 FlatPtr stack[max_stack_frame_count]; 102}; 103 104enum class ProcessEventType { 105 Create, 106 Exec 107}; 108 109class PerformanceEventBuffer { 110public: 111 static OwnPtr<PerformanceEventBuffer> try_create_with_size(size_t buffer_size); 112 113 ErrorOr<void> append(int type, FlatPtr arg1, FlatPtr arg2, StringView arg3, Thread* current_thread = Thread::current(), FlatPtr arg4 = 0, u64 arg5 = 0, ErrorOr<FlatPtr> const& arg6 = 0); 114 ErrorOr<void> append_with_ip_and_bp(ProcessID pid, ThreadID tid, FlatPtr eip, FlatPtr ebp, 115 int type, u32 lost_samples, FlatPtr arg1, FlatPtr arg2, StringView arg3, FlatPtr arg4 = 0, u64 arg5 = {}, ErrorOr<FlatPtr> const& arg6 = 0); 116 ErrorOr<void> append_with_ip_and_bp(ProcessID pid, ThreadID tid, RegisterState const& regs, 117 int type, u32 lost_samples, FlatPtr arg1, FlatPtr arg2, StringView arg3, FlatPtr arg4 = 0, u64 arg5 = {}, ErrorOr<FlatPtr> const& arg6 = 0); 118 119 void clear() 120 { 121 m_count = 0; 122 } 123 124 size_t capacity() const { return m_buffer->size() / sizeof(PerformanceEvent); } 125 size_t count() const { return m_count; } 126 PerformanceEvent const& at(size_t index) const 127 { 128 return const_cast<PerformanceEventBuffer&>(*this).at(index); 129 } 130 131 ErrorOr<void> to_json(KBufferBuilder&) const; 132 133 ErrorOr<void> add_process(Process const&, ProcessEventType event_type); 134 135 ErrorOr<FlatPtr> register_string(NonnullOwnPtr<KString>); 136 137private: 138 explicit PerformanceEventBuffer(NonnullOwnPtr<KBuffer>); 139 140 template<typename Serializer> 141 ErrorOr<void> to_json_impl(Serializer&) const; 142 143 PerformanceEvent& at(size_t index); 144 145 size_t m_count { 0 }; 146 NonnullOwnPtr<KBuffer> m_buffer; 147 148 HashMap<NonnullOwnPtr<KString>, size_t> m_strings; 149}; 150 151extern bool g_profiling_all_threads; 152extern PerformanceEventBuffer* g_global_perf_events; 153extern u64 g_profiling_event_mask; 154 155}