diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index 70ca9cfac2..de49c627b8 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -131,6 +131,7 @@ enum class NeedsBigProcessLock { S(munmap, NeedsBigProcessLock::Yes) \ S(open, NeedsBigProcessLock::Yes) \ S(perf_event, NeedsBigProcessLock::Yes) \ + S(perf_register_string, NeedsBigProcessLock::Yes) \ S(pipe, NeedsBigProcessLock::Yes) \ S(pledge, NeedsBigProcessLock::Yes) \ S(poll, NeedsBigProcessLock::Yes) \ diff --git a/Kernel/PerformanceEventBuffer.cpp b/Kernel/PerformanceEventBuffer.cpp index aabfddc467..db7aa3fc20 100644 --- a/Kernel/PerformanceEventBuffer.cpp +++ b/Kernel/PerformanceEventBuffer.cpp @@ -166,6 +166,13 @@ PerformanceEvent& PerformanceEventBuffer::at(size_t index) template bool PerformanceEventBuffer::to_json_impl(Serializer& object) const { + { + auto strings = object.add_object("strings"); + for (auto& it : m_strings) { + strings.add(String::number(it.key), it.value->view()); + } + } + auto array = object.add_array("events"); bool seen_first_sample = false; for (size_t i = 0; i < m_count; ++i) { @@ -298,4 +305,13 @@ void PerformanceEventBuffer::add_process(const Process& process, ProcessEventTyp } } +KResult PerformanceEventBuffer::register_string(FlatPtr string_id, NonnullOwnPtr string) +{ + m_strings.set(string_id, move(string)); + + // FIXME: Switch m_strings to something that can signal allocation failure, + // and then propagate such failures here. + return KSuccess; +} + } diff --git a/Kernel/PerformanceEventBuffer.h b/Kernel/PerformanceEventBuffer.h index 217d738b09..6278ad6ef4 100644 --- a/Kernel/PerformanceEventBuffer.h +++ b/Kernel/PerformanceEventBuffer.h @@ -120,6 +120,8 @@ public: void add_process(const Process&, ProcessEventType event_type); + KResult register_string(FlatPtr string_id, NonnullOwnPtr); + private: explicit PerformanceEventBuffer(NonnullOwnPtr); @@ -130,6 +132,8 @@ private: size_t m_count { 0 }; NonnullOwnPtr m_buffer; + + HashMap> m_strings; }; extern bool g_profiling_all_threads; diff --git a/Kernel/Process.h b/Kernel/Process.h index b0e56a3ad7..99711ed655 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -400,6 +400,7 @@ public: KResultOr sys$pledge(Userspace); KResultOr sys$unveil(Userspace); KResultOr sys$perf_event(int type, FlatPtr arg1, FlatPtr arg2); + KResultOr sys$perf_register_string(FlatPtr string_id, Userspace, size_t); KResultOr sys$get_stack_bounds(Userspace stack_base, Userspace stack_size); KResultOr sys$ptrace(Userspace); KResultOr sys$sendfd(int sockfd, int fd); diff --git a/Kernel/Syscalls/perf_event.cpp b/Kernel/Syscalls/perf_event.cpp index b25faacf2d..99cffb27b1 100644 --- a/Kernel/Syscalls/perf_event.cpp +++ b/Kernel/Syscalls/perf_event.cpp @@ -21,4 +21,18 @@ KResultOr Process::sys$perf_event(int type, FlatPtr arg1, FlatPtr arg2) return events_buffer->append(type, arg1, arg2, nullptr); } +KResultOr Process::sys$perf_register_string(FlatPtr string_id, Userspace user_string, size_t user_string_length) +{ + VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) + auto* events_buffer = current_perf_events_buffer(); + if (!events_buffer) + return KSuccess; + + auto string_or_error = try_copy_kstring_from_user(user_string, user_string_length); + if (string_or_error.is_error()) + return string_or_error.error(); + + return events_buffer->register_string(string_id, string_or_error.release_value()); +} + } diff --git a/Userland/Libraries/LibC/serenity.cpp b/Userland/Libraries/LibC/serenity.cpp index 7a8d8f69be..cd99ba64ee 100644 --- a/Userland/Libraries/LibC/serenity.cpp +++ b/Userland/Libraries/LibC/serenity.cpp @@ -95,6 +95,12 @@ int perf_event(int type, uintptr_t arg1, FlatPtr arg2) __RETURN_WITH_ERRNO(rc, rc, -1); } +int perf_register_string(uintptr_t string_id, char const* string, size_t string_length) +{ + int rc = syscall(SC_perf_register_string, string_id, string, string_length); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + int get_stack_bounds(uintptr_t* user_stack_base, size_t* user_stack_size) { int rc = syscall(SC_get_stack_bounds, user_stack_base, user_stack_size); diff --git a/Userland/Libraries/LibC/serenity.h b/Userland/Libraries/LibC/serenity.h index 6c7e0f3d7b..6d9ec2fc94 100644 --- a/Userland/Libraries/LibC/serenity.h +++ b/Userland/Libraries/LibC/serenity.h @@ -119,6 +119,7 @@ enum { #define PERF_EVENT_MASK_ALL (~0ull) int perf_event(int type, uintptr_t arg1, uintptr_t arg2); +int perf_register_string(uintptr_t string_id, char const* string, size_t string_length); int get_stack_bounds(uintptr_t* user_stack_base, size_t* user_stack_size);