| // Copyright 2021 The Fuchsia Authors |
| // |
| // Use of this source code is governed by a MIT-style |
| // license that can be found in the LICENSE file or at |
| // https://opensource.org/licenses/MIT |
| |
| #ifndef ZIRCON_KERNEL_PHYS_INCLUDE_PHYS_ALLOCATION_H_ |
| #define ZIRCON_KERNEL_PHYS_INCLUDE_PHYS_ALLOCATION_H_ |
| |
| #include <lib/fitx/result.h> |
| #include <lib/memalloc/pool.h> |
| #include <lib/memalloc/range.h> |
| |
| #include <fbl/alloc_checker.h> |
| #include <ktl/algorithm.h> |
| #include <ktl/byte.h> |
| #include <ktl/move.h> |
| #include <ktl/optional.h> |
| #include <ktl/span.h> |
| #include <ktl/string_view.h> |
| |
| // This object represents one memory allocation, and owns that allocation so |
| // destroying this object frees the allocation. It acts as a smart pointer |
| // that also knows the size so it can deliver a raw pointer or a span<byte>. |
| class Allocation { |
| public: |
| // A default-constructed object is like a null pointer. |
| // Allocation::New() must be called to create a non-null Allocation. |
| Allocation() = default; |
| |
| Allocation(const Allocation&) = delete; |
| |
| Allocation(Allocation&& other) noexcept { *this = ktl::move(other); } |
| |
| Allocation& operator=(const Allocation&) = delete; |
| |
| Allocation& operator=(Allocation&& other) noexcept { |
| ktl::swap(data_, other.data_); |
| ktl::swap(alignment_, other.alignment_); |
| ktl::swap(type_, other.type_); |
| return *this; |
| } |
| |
| ~Allocation() { reset(); } |
| |
| auto data() const { return data_; } |
| |
| size_t size_bytes() const { return data_.size(); } |
| |
| auto get() const { return data_.data(); } |
| |
| // Gives the intended minimal alignment. |
| size_t alignment() const { return alignment_; } |
| |
| memalloc::Type type() const { return type_; } |
| |
| void reset(); |
| |
| // This returns the span like data() but transfers ownership like a move. |
| [[nodiscard]] auto release() { |
| auto result = data_; |
| data_ = {}; |
| alignment_ = 0; |
| type_ = memalloc::Type::kMaxExtended; |
| return result; |
| } |
| |
| explicit operator bool() const { return !data_.empty(); } |
| |
| void Resize(fbl::AllocChecker& ac, size_t new_size); |
| |
| // This must be called exactly once before using GetPool or New. |
| static void Init(ktl::span<memalloc::Range> mem_ranges, |
| ktl::span<memalloc::Range> special_ranges); |
| |
| // If allocation fails, operator bool will return false later. |
| // The AllocChecker must be checked after construction, too. |
| static Allocation New(fbl::AllocChecker& ac, memalloc::Type type, size_t size, |
| size_t alignment = __STDCPP_DEFAULT_NEW_ALIGNMENT__, |
| ktl::optional<uint64_t> min_addr = ktl::nullopt, |
| ktl::optional<uint64_t> max_addr = ktl::nullopt); |
| |
| // Get the memalloc::Pool instance used to construct Allocation objects. |
| // Every call returns the same object, but the first may initialize it. Note |
| // separate #include <lib/memalloc/pool.h> is necessary to use the instance. |
| [[gnu::const]] static memalloc::Pool& GetPool(); |
| |
| private: |
| ktl::span<ktl::byte> data_; |
| size_t alignment_ = 0; |
| memalloc::Type type_ = memalloc::Type::kMaxExtended; |
| }; |
| |
| #endif // ZIRCON_KERNEL_PHYS_INCLUDE_PHYS_ALLOCATION_H_ |