blob: 9cb6678b93d2502f25c56f89019f3cd2a707b8ed [file] [log] [blame]
// 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_