purge.cpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/NonnullRefPtrVector.h>
  7. #include <Kernel/Memory/AnonymousVMObject.h>
  8. #include <Kernel/Memory/InodeVMObject.h>
  9. #include <Kernel/Memory/MemoryManager.h>
  10. #include <Kernel/Process.h>
  11. namespace Kernel {
  12. KResultOr<FlatPtr> Process::sys$purge(int mode)
  13. {
  14. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  15. REQUIRE_NO_PROMISES;
  16. if (!is_superuser())
  17. return EPERM;
  18. size_t purged_page_count = 0;
  19. if (mode & PURGE_ALL_VOLATILE) {
  20. NonnullRefPtrVector<Memory::AnonymousVMObject> vmobjects;
  21. {
  22. KResult result(KSuccess);
  23. MM.for_each_vmobject([&](auto& vmobject) {
  24. if (vmobject.is_anonymous()) {
  25. // In the event that the append fails, only attempt to continue
  26. // the purge if we have already appended something successfully.
  27. if (!vmobjects.try_append(static_cast<Memory::AnonymousVMObject&>(vmobject)) && vmobjects.is_empty()) {
  28. result = ENOMEM;
  29. return IterationDecision::Break;
  30. }
  31. }
  32. return IterationDecision::Continue;
  33. });
  34. if (result.is_error())
  35. return result.error();
  36. }
  37. for (auto& vmobject : vmobjects) {
  38. purged_page_count += vmobject.purge();
  39. }
  40. }
  41. if (mode & PURGE_ALL_CLEAN_INODE) {
  42. NonnullRefPtrVector<Memory::InodeVMObject> vmobjects;
  43. {
  44. KResult result(KSuccess);
  45. MM.for_each_vmobject([&](auto& vmobject) {
  46. if (vmobject.is_inode()) {
  47. // In the event that the append fails, only attempt to continue
  48. // the purge if we have already appended something successfully.
  49. if (!vmobjects.try_append(static_cast<Memory::InodeVMObject&>(vmobject)) && vmobjects.is_empty()) {
  50. result = ENOMEM;
  51. return IterationDecision::Break;
  52. }
  53. }
  54. return IterationDecision::Continue;
  55. });
  56. if (result.is_error())
  57. return result.error();
  58. }
  59. for (auto& vmobject : vmobjects) {
  60. purged_page_count += vmobject.release_all_clean_pages();
  61. }
  62. }
  63. return purged_page_count;
  64. }
  65. }