// Copyright 2017 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_HYPERVISOR_INCLUDE_HYPERVISOR_ID_ALLOCATOR_H_
#define ZIRCON_KERNEL_HYPERVISOR_INCLUDE_HYPERVISOR_ID_ALLOCATOR_H_

#include <lib/zx/status.h>

#include <bitmap/raw-bitmap.h>
#include <bitmap/storage.h>
#include <kernel/mutex.h>
#include <ktl/type_traits.h>

namespace hypervisor {

using GenType = uint32_t;

template <typename T>
class [[nodiscard]] Id {
 public:
  static_assert(ktl::is_unsigned_v<T>, "T must be unsigned");

  Id(T val, GenType gen) : val_(val), gen_(gen) {}

  Id(Id&&) noexcept = default;
  Id& operator=(Id&&) noexcept = default;
  Id(const Id&) = delete;
  Id& operator=(const Id&) = delete;

  T val() const { return val_; }
  GenType gen() const { return gen_; }

 private:
  T val_;
  GenType gen_;
};

// Allocates architecture-specific resource IDs.
//
// IDs of type `T` will be allocated in the range [`MinId`, `MaxId`).
//
// If `Alloc` is used to allocate an ID, then an ID is guaranteed to be
// allocated. To do this, IDs are allocated and assigned a generation. If no IDs
// are available, then the generation count is increment and all IDs become
// available again.
//
// To ensure an ID is valid, before an operation that relies on the ID is
// attempted, `Migrate` should be called on the ID.
//
// `T` is the type of the ID, and is an integral type.
// `MaxId` is the maximum value of an ID.
// `MinId` is the minimum value of an ID. This defaults to 1.
template <typename T, T MaxId, T MinId = 1>
class IdAllocator {
 public:
  static_assert(ktl::is_unsigned_v<T>, "T must be unsigned");
  static_assert(MaxId > MinId, "MaxId must be greater than MinId");

  IdAllocator() {
    auto result = Reset();
    // We use `FixedStorage` and we statically assert `MaxId` > `MinId`,
    // therefore this should not fail.
    ZX_DEBUG_ASSERT(result.is_ok());
  }

  // Resets the allocator, and sets a new `max_id`, where `max_id` <= `MaxId`.
  zx::status<> Reset(T max_id = MaxId) {
    if (max_id <= MinId) {
      return zx::error(ZX_ERR_OUT_OF_RANGE);
    }
    Guard<Mutex> lock{&mutex_};
    zx_status_t status = bitmap_.Reset(max_id);
    return zx::make_status(status);
  }

  // Allocate an ID, potentially within a new generation.
  Id<T> Alloc() {
    Guard<Mutex> lock{&mutex_};
    auto id = AllocFromHint(next_, /*use_gen*/ true);
    UpdateNext(*id);
    return std::move(*id);
  }

  // Try to allocate an ID within the current generation.
  zx::status<Id<T>> TryAlloc() {
    Guard<Mutex> lock{&mutex_};
    auto id = AllocFromHint(next_, /*use_gen*/ false);
    if (id.is_ok()) {
      UpdateNext(*id);
    }
    return id;
  }

  zx::status<> Free(Id<T> id) {
    // If the generations do not match, return as we have nothing to do.
    if (id.gen() != gen_) {
      return zx::ok();
    }
    if (!InRange(id.val())) {
      return zx::error(ZX_ERR_OUT_OF_RANGE);
    }
    Guard<Mutex> lock{&mutex_};
    if (!bitmap_.GetOne(id.val())) {
      return zx::error(ZX_ERR_INVALID_ARGS);
    }
    zx_status_t status = bitmap_.ClearOne(id.val());
    return zx::make_status(status);
  }

  // Migrate `id` to the latest generation. If `id` was not at the latest
  // generation, then `invalidate` will be called.
  template <typename F>
  void Migrate(Id<T>& id, F invalidate) {
    T last_val = id.val();
    GenType last_gen = id.gen();
    // If the generations match, or if the value is out of range, return as we
    // have nothing to do.
    if (last_gen == gen_ || !InRange(last_val)) {
      return;
    }
    {
      Guard<Mutex> lock{&mutex_};
      // Reallocate a new `id`, and execute the invalidation function.
      id = *AllocFromHint(id.val(), /*use_gen*/ true);
    }
    // If `id` has the same value and was only one generation behind, we can
    // safely skip the invalidation.
    if (last_val != id.val() || last_gen + 1u != id.gen()) {
      invalidate(id.val());
    }
  }

 private:
  bool InRange(T val) const { return val >= MinId && val < MaxId; }

  zx::status<Id<T>> AllocFromHint(T next, bool use_gen) TA_REQ(mutex_) {
    size_t first_unset;
  retry:
    if (bitmap_.Get(next, MaxId, &first_unset)) {
      if (bitmap_.Get(MinId, next, &first_unset)) {
        if (use_gen) {
          // There are no more free IDs in this generation, so increment the
          // generation and start again.
          ++gen_;
          bitmap_.Reset(bitmap_.size());
          goto retry;
        }
        return zx::error(ZX_ERR_NO_RESOURCES);
      }
    }
    zx_status_t status = bitmap_.SetOne(first_unset);
    // The bitmap returned this index as unset, therefore this should not fail.
    ZX_DEBUG_ASSERT(status == ZX_OK);
    auto val = static_cast<T>(first_unset);
    return zx::ok(Id{val, gen_});
  }

  void UpdateNext(Id<T>& id) TA_REQ(mutex_) {
    next_ = static_cast<T>((id.val() + 1u) % MaxId);
    if (next_ == 0) {
      next_ = MinId;
    }
  }

  ktl::atomic<GenType> gen_ = 0;
  DECLARE_MUTEX(IdAllocator) mutex_;
  T next_ TA_GUARDED(mutex_) = MinId;
  bitmap::RawBitmapGeneric<bitmap::FixedStorage<MaxId>> bitmap_ TA_GUARDED(mutex_);
};

}  // namespace hypervisor

#endif  // ZIRCON_KERNEL_HYPERVISOR_INCLUDE_HYPERVISOR_ID_ALLOCATOR_H_
