KBuffer.h 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #pragma once
  2. // KBuffer: Statically sized kernel-only memory buffer.
  3. //
  4. // A KBuffer is a value-type convenience class that wraps a NonnullRefPtr<KBufferImpl>.
  5. // The memory is allocated via the global kernel-only page allocator, rather than via
  6. // kmalloc() which is what ByteBuffer/Vector/etc will use.
  7. //
  8. // This makes KBuffer a little heavier to allocate, but much better for large and/or
  9. // long-lived allocations, since they don't put all that weight and pressure on the
  10. // severely limited kmalloc heap.
  11. #include <AK/Assertions.h>
  12. #include <AK/LogStream.h>
  13. #include <Kernel/VM/MemoryManager.h>
  14. #include <Kernel/VM/Region.h>
  15. class KBufferImpl : public RefCounted<KBufferImpl> {
  16. public:
  17. static NonnullRefPtr<KBufferImpl> create_with_size(size_t size, u8 access)
  18. {
  19. auto region = MM.allocate_kernel_region(PAGE_ROUND_UP(size), "KBuffer", access, false, false);
  20. ASSERT(region);
  21. return adopt(*new KBufferImpl(region.release_nonnull(), size));
  22. }
  23. static NonnullRefPtr<KBufferImpl> copy(const void* data, size_t size, u8 access)
  24. {
  25. auto buffer = create_with_size(size, access);
  26. memcpy(buffer->data(), data, size);
  27. return buffer;
  28. }
  29. u8* data() { return m_region->vaddr().as_ptr(); }
  30. const u8* data() const { return m_region->vaddr().as_ptr(); }
  31. size_t size() const { return m_size; }
  32. size_t capacity() const { return m_region->size(); }
  33. void set_size(size_t size)
  34. {
  35. ASSERT(size <= capacity());
  36. m_size = size;
  37. }
  38. private:
  39. explicit KBufferImpl(NonnullOwnPtr<Region>&& region, size_t size)
  40. : m_size(size)
  41. , m_region(move(region))
  42. {
  43. }
  44. size_t m_size { 0 };
  45. NonnullOwnPtr<Region> m_region;
  46. };
  47. class KBuffer {
  48. public:
  49. static KBuffer create_with_size(size_t size, u8 access = Region::Access::Read | Region::Access::Write)
  50. {
  51. return KBuffer(KBufferImpl::create_with_size(size, access));
  52. }
  53. static KBuffer copy(const void* data, size_t size, u8 access = Region::Access::Read | Region::Access::Write)
  54. {
  55. return KBuffer(KBufferImpl::copy(data, size, access));
  56. }
  57. u8* data() { return m_impl->data(); }
  58. const u8* data() const { return m_impl->data(); }
  59. size_t size() const { return m_impl->size(); }
  60. size_t capacity() const { return m_impl->capacity(); }
  61. void set_size(size_t size) { m_impl->set_size(size); }
  62. const KBufferImpl& impl() const { return m_impl; }
  63. KBuffer(const ByteBuffer& buffer, u8 access = Region::Access::Read | Region::Access::Write)
  64. : m_impl(KBufferImpl::copy(buffer.data(), buffer.size(), access))
  65. {
  66. }
  67. private:
  68. explicit KBuffer(NonnullRefPtr<KBufferImpl>&& impl)
  69. : m_impl(move(impl))
  70. {
  71. }
  72. NonnullRefPtr<KBufferImpl> m_impl;
  73. };
  74. inline const LogStream& operator<<(const LogStream& stream, const KBuffer& value)
  75. {
  76. return stream << StringView(value.data(), value.size());
  77. }