profiling.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/CoreDump.h>
  7. #include <Kernel/FileSystem/FileDescription.h>
  8. #include <Kernel/FileSystem/VirtualFileSystem.h>
  9. #include <Kernel/PerformanceManager.h>
  10. #include <Kernel/Process.h>
  11. #include <Kernel/Time/TimeManagement.h>
  12. namespace Kernel {
  13. bool g_profiling_all_threads;
  14. PerformanceEventBuffer* g_global_perf_events;
  15. u64 g_profiling_event_mask;
  16. KResultOr<FlatPtr> Process::sys$profiling_enable(pid_t pid, u64 event_mask)
  17. {
  18. REQUIRE_NO_PROMISES;
  19. if (pid == -1) {
  20. if (!is_superuser())
  21. return EPERM;
  22. ScopedCritical critical;
  23. g_profiling_event_mask = PERF_EVENT_PROCESS_CREATE | PERF_EVENT_THREAD_CREATE | PERF_EVENT_MMAP;
  24. if (g_global_perf_events)
  25. g_global_perf_events->clear();
  26. else
  27. g_global_perf_events = PerformanceEventBuffer::try_create_with_size(32 * MiB).leak_ptr();
  28. ScopedSpinLock lock(g_processes_lock);
  29. if (!TimeManagement::the().enable_profile_timer())
  30. return ENOTSUP;
  31. g_profiling_all_threads = true;
  32. PerformanceManager::add_process_created_event(*Scheduler::colonel());
  33. Process::for_each([](auto& process) {
  34. PerformanceManager::add_process_created_event(process);
  35. return IterationDecision::Continue;
  36. });
  37. g_profiling_event_mask = event_mask;
  38. return 0;
  39. }
  40. ScopedSpinLock lock(g_processes_lock);
  41. auto process = Process::from_pid(pid);
  42. if (!process)
  43. return ESRCH;
  44. if (process->is_dead())
  45. return ESRCH;
  46. if (!is_superuser() && process->uid() != euid())
  47. return EPERM;
  48. g_profiling_event_mask = PERF_EVENT_PROCESS_CREATE | PERF_EVENT_THREAD_CREATE | PERF_EVENT_MMAP;
  49. process->set_profiling(true);
  50. if (!process->create_perf_events_buffer_if_needed()) {
  51. process->set_profiling(false);
  52. return ENOMEM;
  53. }
  54. g_profiling_event_mask = event_mask;
  55. if (!TimeManagement::the().enable_profile_timer()) {
  56. process->set_profiling(false);
  57. return ENOTSUP;
  58. }
  59. return 0;
  60. }
  61. KResultOr<FlatPtr> Process::sys$profiling_disable(pid_t pid)
  62. {
  63. REQUIRE_NO_PROMISES;
  64. if (pid == -1) {
  65. if (!is_superuser())
  66. return EPERM;
  67. ScopedCritical critical;
  68. if (!TimeManagement::the().disable_profile_timer())
  69. return ENOTSUP;
  70. g_profiling_all_threads = false;
  71. return 0;
  72. }
  73. ScopedSpinLock lock(g_processes_lock);
  74. auto process = Process::from_pid(pid);
  75. if (!process)
  76. return ESRCH;
  77. if (!is_superuser() && process->uid() != euid())
  78. return EPERM;
  79. if (!process->is_profiling())
  80. return EINVAL;
  81. // FIXME: If we enabled the profile timer and it's not supported, how do we disable it now?
  82. if (!TimeManagement::the().disable_profile_timer())
  83. return ENOTSUP;
  84. process->set_profiling(false);
  85. return 0;
  86. }
  87. KResultOr<FlatPtr> Process::sys$profiling_free_buffer(pid_t pid)
  88. {
  89. REQUIRE_NO_PROMISES;
  90. if (pid == -1) {
  91. if (!is_superuser())
  92. return EPERM;
  93. OwnPtr<PerformanceEventBuffer> perf_events;
  94. {
  95. ScopedCritical critical;
  96. perf_events = adopt_own_if_nonnull(g_global_perf_events);
  97. g_global_perf_events = nullptr;
  98. }
  99. return 0;
  100. }
  101. ScopedSpinLock lock(g_processes_lock);
  102. auto process = Process::from_pid(pid);
  103. if (!process)
  104. return ESRCH;
  105. if (!is_superuser() && process->uid() != euid())
  106. return EPERM;
  107. if (process->is_profiling())
  108. return EINVAL;
  109. process->delete_perf_events_buffer();
  110. return 0;
  111. }
  112. }