AnonymousBuffer.cpp 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibCore/AnonymousBuffer.h>
  7. #include <LibIPC/File.h>
  8. #include <fcntl.h>
  9. #include <stdio.h>
  10. #include <sys/mman.h>
  11. #if defined(__serenity__)
  12. # include <serenity.h>
  13. #endif
  14. #if defined(__linux__) && !defined(MFD_CLOEXEC)
  15. # include <linux/memfd.h>
  16. # include <sys/syscall.h>
  17. static int memfd_create(const char* name, unsigned int flags)
  18. {
  19. return syscall(SYS_memfd_create, name, flags);
  20. }
  21. #endif
  22. namespace Core {
  23. AnonymousBuffer AnonymousBuffer::create_with_size(size_t size)
  24. {
  25. int fd = -1;
  26. #if defined(__serenity__)
  27. fd = anon_create(round_up_to_power_of_two(size, PAGE_SIZE), O_CLOEXEC);
  28. if (fd < 0) {
  29. perror("anon_create");
  30. return {};
  31. }
  32. #elif defined(__linux__)
  33. fd = memfd_create("", MFD_CLOEXEC);
  34. if (fd < 0) {
  35. perror("memfd_create");
  36. return {};
  37. }
  38. if (ftruncate(fd, size) < 0) {
  39. close(fd);
  40. perror("ftruncate");
  41. return {};
  42. }
  43. #endif
  44. if (fd < 0)
  45. return {};
  46. return create_from_anon_fd(fd, size);
  47. }
  48. RefPtr<AnonymousBufferImpl> AnonymousBufferImpl::create(int fd, size_t size)
  49. {
  50. auto* data = mmap(nullptr, round_up_to_power_of_two(size, PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0);
  51. if (data == MAP_FAILED) {
  52. perror("mmap");
  53. return {};
  54. }
  55. return adopt_ref(*new AnonymousBufferImpl(fd, size, data));
  56. }
  57. AnonymousBufferImpl::~AnonymousBufferImpl()
  58. {
  59. if (m_fd != -1) {
  60. auto rc = close(m_fd);
  61. VERIFY(rc == 0);
  62. }
  63. auto rc = munmap(m_data, round_up_to_power_of_two(m_size, PAGE_SIZE));
  64. VERIFY(rc == 0);
  65. }
  66. AnonymousBuffer AnonymousBuffer::create_from_anon_fd(int fd, size_t size)
  67. {
  68. auto impl = AnonymousBufferImpl::create(fd, size);
  69. if (!impl)
  70. return {};
  71. return AnonymousBuffer(impl.release_nonnull());
  72. }
  73. AnonymousBuffer::AnonymousBuffer(NonnullRefPtr<AnonymousBufferImpl> impl)
  74. : m_impl(move(impl))
  75. {
  76. }
  77. AnonymousBufferImpl::AnonymousBufferImpl(int fd, size_t size, void* data)
  78. : m_fd(fd)
  79. , m_size(size)
  80. , m_data(data)
  81. {
  82. }
  83. }