PowerStateSwitchTask.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Copyright (c) 2023, kleines Filmröllchen <filmroellchen@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Platform.h>
  7. #if ARCH(X86_64)
  8. # include <Kernel/Arch/x86_64/I8042Reboot.h>
  9. # include <Kernel/Arch/x86_64/Shutdown.h>
  10. #elif ARCH(AARCH64)
  11. # include <Kernel/Arch/aarch64/RPi/Watchdog.h>
  12. #endif
  13. #include <AK/StringView.h>
  14. #include <Kernel/Arch/PowerState.h>
  15. #include <Kernel/FileSystem/FileSystem.h>
  16. #include <Kernel/FileSystem/VirtualFileSystem.h>
  17. #include <Kernel/Firmware/ACPI/Parser.h>
  18. #include <Kernel/Library/Panic.h>
  19. #include <Kernel/Sections.h>
  20. #include <Kernel/TTY/ConsoleManagement.h>
  21. #include <Kernel/Tasks/FinalizerTask.h>
  22. #include <Kernel/Tasks/PowerStateSwitchTask.h>
  23. #include <Kernel/Tasks/Process.h>
  24. #include <Kernel/Tasks/Scheduler.h>
  25. namespace Kernel {
  26. static constexpr StringView power_state_switch_task_name_view = "Power State Switch Task"sv;
  27. Thread* g_power_state_switch_task;
  28. bool g_in_system_shutdown { false };
  29. void PowerStateSwitchTask::power_state_switch_task(void* raw_entry_data)
  30. {
  31. Thread::current()->set_priority(THREAD_PRIORITY_HIGH);
  32. auto entry_data = bit_cast<PowerStateCommand>(raw_entry_data);
  33. switch (entry_data) {
  34. case PowerStateCommand::Shutdown:
  35. MUST(PowerStateSwitchTask::perform_shutdown());
  36. break;
  37. case PowerStateCommand::Reboot:
  38. MUST(PowerStateSwitchTask::perform_reboot());
  39. break;
  40. default:
  41. PANIC("Unknown power state command: {}", to_underlying(entry_data));
  42. }
  43. // Although common, the system may not halt through this task.
  44. // Clear the power state switch task so that it can be spawned again.
  45. g_power_state_switch_task = nullptr;
  46. }
  47. void PowerStateSwitchTask::spawn(PowerStateCommand command)
  48. {
  49. // FIXME: If we switch power states during memory pressure, don't let the system crash just because of our task name.
  50. NonnullOwnPtr<KString> power_state_switch_task_name = MUST(KString::try_create(power_state_switch_task_name_view));
  51. VERIFY(g_power_state_switch_task == nullptr);
  52. auto [_, power_state_switch_task_thread] = MUST(Process::create_kernel_process(
  53. move(power_state_switch_task_name), power_state_switch_task, bit_cast<void*>(command)));
  54. g_power_state_switch_task = move(power_state_switch_task_thread);
  55. }
  56. ErrorOr<void> PowerStateSwitchTask::perform_reboot()
  57. {
  58. dbgln("acquiring FS locks...");
  59. FileSystem::lock_all();
  60. dbgln("syncing mounted filesystems...");
  61. FileSystem::sync();
  62. dbgln("attempting reboot via ACPI");
  63. if (ACPI::is_enabled())
  64. ACPI::Parser::the()->try_acpi_reboot();
  65. arch_specific_reboot();
  66. dbgln("reboot attempts failed, applications will stop responding.");
  67. dmesgln("Reboot can't be completed. It's safe to turn off the computer!");
  68. Processor::halt();
  69. }
  70. ErrorOr<void> PowerStateSwitchTask::perform_shutdown()
  71. {
  72. // We assume that by this point userland has tried as much as possible to shut down everything in an orderly fashion.
  73. // Therefore, we force kill remaining processes, including Kernel processes, except the finalizer and ourselves.
  74. dbgln("Killing remaining processes...");
  75. Optional<Process&> finalizer_process;
  76. Process::all_instances().for_each([&](Process& process) {
  77. if (process.pid() == g_finalizer->process().pid())
  78. finalizer_process = process;
  79. });
  80. VERIFY(finalizer_process.has_value());
  81. // Allow init process and finalizer task to be killed.
  82. g_in_system_shutdown = true;
  83. // Make sure to kill all user processes first, otherwise we might get weird hangups.
  84. TRY(kill_processes(ProcessKind::User, finalizer_process->pid()));
  85. TRY(kill_processes(ProcessKind::Kernel, finalizer_process->pid()));
  86. finalizer_process->die();
  87. finalizer_process->finalize();
  88. size_t alive_process_count = 0;
  89. Process::all_instances().for_each([&](Process& process) {
  90. if (process.pid() != Process::current().pid() && !process.is_dead())
  91. alive_process_count++;
  92. });
  93. // Don't panic here (since we may panic in a bit anyways) but report the probable cause of an unclean shutdown.
  94. if (alive_process_count != 0)
  95. dbgln("We're not the last process alive; proper shutdown may fail!");
  96. ConsoleManagement::the().switch_to_debug();
  97. dbgln("Locking all file systems...");
  98. FileSystem::lock_all();
  99. FileSystem::sync();
  100. dbgln("Unmounting all file systems...");
  101. auto unmount_was_successful = true;
  102. while (unmount_was_successful) {
  103. unmount_was_successful = false;
  104. Vector<Mount&, 16> mounts;
  105. TRY(VirtualFileSystem::the().for_each_mount([&](auto const& mount) -> ErrorOr<void> {
  106. TRY(mounts.try_append(const_cast<Mount&>(mount)));
  107. return {};
  108. }));
  109. if (mounts.is_empty())
  110. break;
  111. auto const remaining_mounts = mounts.size();
  112. while (!mounts.is_empty()) {
  113. auto& mount = mounts.take_last();
  114. mount.guest_fs().flush_writes();
  115. auto mount_path = TRY(mount.absolute_path());
  116. auto& mount_inode = mount.guest();
  117. auto const result = VirtualFileSystem::the().unmount(mount_inode, mount_path->view());
  118. if (result.is_error()) {
  119. dbgln("Error during unmount of {}: {}", mount_path, result.error());
  120. // FIXME: For unknown reasons the root FS stays busy even after everything else has shut down and was unmounted.
  121. // Until we find the underlying issue, allow an unclean shutdown here.
  122. if (remaining_mounts <= 1)
  123. dbgln("BUG! One mount remaining; the root file system may not be unmountable at all. Shutting down anyways.");
  124. } else {
  125. unmount_was_successful = true;
  126. }
  127. }
  128. }
  129. dbgln("Attempting system shutdown...");
  130. arch_specific_poweroff();
  131. dbgln("shutdown attempts failed, applications will stop responding.");
  132. dmesgln("Shutdown can't be completed. It's safe to turn off the computer!");
  133. Processor::halt();
  134. }
  135. ErrorOr<void> PowerStateSwitchTask::kill_processes(ProcessKind kind, ProcessID finalizer_pid)
  136. {
  137. bool kill_kernel_processes = kind == ProcessKind::Kernel;
  138. Process::all_instances().for_each([&](Process& process) {
  139. if (process.pid() != Process::current().pid() && process.pid() != finalizer_pid && process.is_kernel_process() == kill_kernel_processes) {
  140. process.die();
  141. }
  142. });
  143. // Although we *could* finalize processes ourselves (g_in_system_shutdown allows this),
  144. // we're nice citizens and let the finalizer task perform final duties before we kill it.
  145. Scheduler::notify_finalizer();
  146. int alive_process_count = 1;
  147. MonotonicTime last_status_time = TimeManagement::the().monotonic_time();
  148. while (alive_process_count > 0) {
  149. Scheduler::yield();
  150. alive_process_count = 0;
  151. Process::all_instances().for_each([&](Process& process) {
  152. if (process.pid() != Process::current().pid() && !process.is_dead() && process.pid() != finalizer_pid && process.is_kernel_process() == kill_kernel_processes)
  153. alive_process_count++;
  154. });
  155. if (TimeManagement::the().monotonic_time() - last_status_time > Duration::from_seconds(2)) {
  156. last_status_time = TimeManagement::the().monotonic_time();
  157. dmesgln("Waiting on {} processes to exit...", alive_process_count);
  158. if constexpr (PROCESS_DEBUG) {
  159. Process::all_instances().for_each_const([&](Process const& process) {
  160. if (process.pid() != Process::current().pid() && !process.is_dead() && process.pid() != finalizer_pid && process.is_kernel_process() == kill_kernel_processes) {
  161. dbgln("Process {:2} kernel={} dead={} dying={} ({})",
  162. process.pid(), process.is_kernel_process(), process.is_dead(), process.is_dying(),
  163. process.name().with([](auto& name) { return name->view(); }));
  164. }
  165. });
  166. }
  167. }
  168. }
  169. return {};
  170. }
  171. }