summaryrefslogtreecommitdiff
path: root/Kernel/Tasks/PerformanceEventBuffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Tasks/PerformanceEventBuffer.h')
-rw-r--r--Kernel/Tasks/PerformanceEventBuffer.h155
1 files changed, 155 insertions, 0 deletions
diff --git a/Kernel/Tasks/PerformanceEventBuffer.h b/Kernel/Tasks/PerformanceEventBuffer.h
new file mode 100644
index 0000000000..74233424be
--- /dev/null
+++ b/Kernel/Tasks/PerformanceEventBuffer.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Error.h>
+#include <Kernel/Library/KBuffer.h>
+
+namespace Kernel {
+
+class KBufferBuilder;
+struct RegisterState;
+
+struct [[gnu::packed]] MallocPerformanceEvent {
+ size_t size;
+ FlatPtr ptr;
+};
+
+struct [[gnu::packed]] FreePerformanceEvent {
+ size_t size;
+ FlatPtr ptr;
+};
+
+struct [[gnu::packed]] MmapPerformanceEvent {
+ size_t size;
+ FlatPtr ptr;
+ char name[64];
+};
+
+struct [[gnu::packed]] MunmapPerformanceEvent {
+ size_t size;
+ FlatPtr ptr;
+};
+
+struct [[gnu::packed]] ProcessCreatePerformanceEvent {
+ pid_t parent_pid;
+ char executable[64];
+};
+
+struct [[gnu::packed]] ProcessExecPerformanceEvent {
+ char executable[64];
+};
+
+struct [[gnu::packed]] ThreadCreatePerformanceEvent {
+ pid_t parent_tid;
+};
+
+struct [[gnu::packed]] ContextSwitchPerformanceEvent {
+ pid_t next_pid;
+ u32 next_tid;
+};
+
+struct [[gnu::packed]] KMallocPerformanceEvent {
+ size_t size;
+ FlatPtr ptr;
+};
+
+struct [[gnu::packed]] KFreePerformanceEvent {
+ size_t size;
+ FlatPtr ptr;
+};
+
+struct [[gnu::packed]] SignpostPerformanceEvent {
+ FlatPtr arg1;
+ FlatPtr arg2;
+};
+
+struct [[gnu::packed]] ReadPerformanceEvent {
+ int fd;
+ size_t size;
+ size_t filename_index;
+ size_t start_timestamp;
+ bool success;
+};
+
+struct [[gnu::packed]] PerformanceEvent {
+ u32 type { 0 };
+ u8 stack_size { 0 };
+ u32 pid { 0 };
+ u32 tid { 0 };
+ u64 timestamp;
+ u32 lost_samples;
+ union {
+ MallocPerformanceEvent malloc;
+ FreePerformanceEvent free;
+ MmapPerformanceEvent mmap;
+ MunmapPerformanceEvent munmap;
+ ProcessCreatePerformanceEvent process_create;
+ ProcessExecPerformanceEvent process_exec;
+ ThreadCreatePerformanceEvent thread_create;
+ ContextSwitchPerformanceEvent context_switch;
+ KMallocPerformanceEvent kmalloc;
+ KFreePerformanceEvent kfree;
+ SignpostPerformanceEvent signpost;
+ ReadPerformanceEvent read;
+ } data;
+ static constexpr size_t max_stack_frame_count = 64;
+ FlatPtr stack[max_stack_frame_count];
+};
+
+enum class ProcessEventType {
+ Create,
+ Exec
+};
+
+class PerformanceEventBuffer {
+public:
+ static OwnPtr<PerformanceEventBuffer> try_create_with_size(size_t buffer_size);
+
+ 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);
+ ErrorOr<void> append_with_ip_and_bp(ProcessID pid, ThreadID tid, FlatPtr eip, FlatPtr ebp,
+ int type, u32 lost_samples, FlatPtr arg1, FlatPtr arg2, StringView arg3, FlatPtr arg4 = 0, u64 arg5 = {}, ErrorOr<FlatPtr> const& arg6 = 0);
+ ErrorOr<void> append_with_ip_and_bp(ProcessID pid, ThreadID tid, RegisterState const& regs,
+ int type, u32 lost_samples, FlatPtr arg1, FlatPtr arg2, StringView arg3, FlatPtr arg4 = 0, u64 arg5 = {}, ErrorOr<FlatPtr> const& arg6 = 0);
+
+ void clear()
+ {
+ m_count = 0;
+ }
+
+ size_t capacity() const { return m_buffer->size() / sizeof(PerformanceEvent); }
+ size_t count() const { return m_count; }
+ PerformanceEvent const& at(size_t index) const
+ {
+ return const_cast<PerformanceEventBuffer&>(*this).at(index);
+ }
+
+ ErrorOr<void> to_json(KBufferBuilder&) const;
+
+ ErrorOr<void> add_process(Process const&, ProcessEventType event_type);
+
+ ErrorOr<FlatPtr> register_string(NonnullOwnPtr<KString>);
+
+private:
+ explicit PerformanceEventBuffer(NonnullOwnPtr<KBuffer>);
+
+ template<typename Serializer>
+ ErrorOr<void> to_json_impl(Serializer&) const;
+
+ PerformanceEvent& at(size_t index);
+
+ size_t m_count { 0 };
+ NonnullOwnPtr<KBuffer> m_buffer;
+
+ HashMap<NonnullOwnPtr<KString>, size_t> m_strings;
+};
+
+extern bool g_profiling_all_threads;
+extern PerformanceEventBuffer* g_global_perf_events;
+extern u64 g_profiling_event_mask;
+
+}