SharedMemoryCursor.h (3759B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_ipc_SharedMemoryCursor_h 8 #define mozilla_ipc_SharedMemoryCursor_h 9 10 #include "mozilla/ipc/SharedMemoryHandle.h" 11 #include "mozilla/ipc/SharedMemoryMapping.h" 12 13 namespace mozilla::ipc::shared_memory { 14 15 // The `Cursor` is a similar type to a mutable `Mapping`, in that it 16 // provides read/write access to the contents of a shared memory region. 17 // However, it can recover from situations where address fragmentation means 18 // that mapping the full shared memory region fails, by instead mapping each 19 // page at a time, and seeking around the region. 20 // 21 // Because of this, the `Cursor` does not provide direct access to the shared 22 // memory region. 23 // 24 // NOTE: Cursor currently only operates on mutable mappings, even when reading. 25 // It can be generalized in the future if it would be found to be useful. 26 class Cursor { 27 public: 28 // Default constructor for invalid cursor. All reads and writes will fail. 29 Cursor() = default; 30 31 // Construct a new Cursor which can be used to read from or write to the 32 // shared memory region indicated by aHandle. 33 explicit Cursor(MutableHandle&& aHandle) : mHandle(std::move(aHandle)) {} 34 35 bool IsValid() const { return mHandle.IsValid(); } 36 uint64_t Size() const { return mHandle.Size(); } 37 uint64_t Offset() const { return mOffset; } 38 uint64_t Remaining() const { return Size() - Offset(); } 39 40 // Read aCount bytes into aBuffer from the shared memory region, advancing the 41 // internal offset. Returns `false` if this fails for any reason. 42 bool Read(void* aBuffer, size_t aCount); 43 44 // Write aCount bytes from aBuffer into the shared memory region, advancing 45 // the internal offset. Returns `false` if this fails for any reason. 46 bool Write(const void* aBuffer, size_t aCount); 47 48 // Seek the Cursor to a given offset in the shared memory region. 49 // aOffset must be less than Size(). 50 void Seek(uint64_t aOffset); 51 52 // Invalidate the Cursor, and return the underlying handle. 53 MutableHandle TakeHandle(); 54 55 // Set the ChunkSize for the shared memory regions in this chunk. This is 56 // intended to be used for testing purposes. 57 // The chunk size must be a power of two, and at least 58 // SystemAllocationGranularity(). 59 void SetChunkSize(size_t aChunkSize); 60 61 private: 62 // Default to mapping at most 1GiB/256MiB, depending on address space size. 63 #ifdef HAVE_64BIT_BUILD 64 static constexpr size_t kDefaultMaxChunkSize = size_t(1) << 30; // 1GiB 65 #else 66 static constexpr size_t kDefaultMaxChunkSize = size_t(1) << 28; // 256MiB 67 #endif 68 69 size_t ChunkSize() const { return mChunkSize; } 70 uint64_t ChunkOffsetMask() const { return uint64_t(ChunkSize()) - 1; } 71 uint64_t ChunkStartMask() const { return ~ChunkOffsetMask(); } 72 size_t ChunkOffset() const { return Offset() & ChunkOffsetMask(); } 73 uint64_t ChunkStart() const { return Offset() & ChunkStartMask(); } 74 75 bool Consume(void* aBuffer, size_t aCount, bool aWriteToShmem); 76 bool EnsureMapping(); 77 78 // Shared memory handle this Cursor allows accessing. 79 MutableHandle mHandle; 80 // Memory map for the currently active chunk. Lazily initialized. 81 MutableMapping mMapping; 82 // Absolute offset into the shared memory handle. 83 uint64_t mOffset = 0; 84 // Current size of each chunk. Always a power of two. May be reduced in 85 // response to allocation failures. 86 size_t mChunkSize = kDefaultMaxChunkSize; 87 }; 88 89 } // namespace mozilla::ipc::shared_memory 90 91 #endif // mozilla_ipc_SharedMemoryCursor_h