// Copyright 2016 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_OBJECT_INCLUDE_OBJECT_RESOURCE_DISPATCHER_H_
#define ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_RESOURCE_DISPATCHER_H_

#include <lib/zircon-internal/thread_annotations.h>
#include <sys/types.h>
#include <zircon/compiler.h>
#include <zircon/rights.h>
#include <zircon/syscalls/resource.h>
#include <zircon/types.h>

#include <array>

#include <fbl/intrusive_double_list.h>
#include <fbl/name.h>
#include <kernel/lockdep.h>
#include <kernel/mutex.h>
#include <object/dispatcher.h>
#include <object/handle.h>
#include <region-alloc/region-alloc.h>

class ResourceRecord;

class ResourceDispatcher final
    : public SoloDispatcher<ResourceDispatcher, ZX_DEFAULT_RESOURCE_RIGHTS>,
      public fbl::DoublyLinkedListable<ResourceDispatcher*> {
 public:
  static constexpr size_t kMaxRegionPoolSize = 64 << 10;

  using ResourceList = fbl::DoublyLinkedList<ResourceDispatcher*>;
  using RefPtr = fbl::RefPtr<ResourceDispatcher>;

  struct ResourceStorage {
    ResourceList resource_list;
    ktl::array<RegionAllocator, ZX_RSRC_KIND_COUNT> rallocs;
  };

  // Creates ResourceDispatcher object representing access rights to a
  // given region of address space from a particular address space allocator, or a root resource
  // granted full access permissions. Only one instance of the root resource is created at boot.
  static zx_status_t Create(KernelHandle<ResourceDispatcher>* handle, zx_rights_t* rights,
                            zx_rsrc_kind_t kind, uint64_t base, size_t size, uint32_t flags,
                            const char name[ZX_MAX_NAME_LEN], ResourceStorage* = nullptr);
  // Creates ResourceDispatcher object representing access rights to all
  // regions of address space for a ranged resource.
  static zx_status_t CreateRangedRoot(KernelHandle<ResourceDispatcher>* handle, zx_rights_t* rights,
                                      zx_rsrc_kind_t kind, const char name[ZX_MAX_NAME_LEN],
                                      ResourceStorage* storage = nullptr);
  // Initializes the static mmembers used for bookkeeping and storage.
  static zx_status_t InitializeAllocator(zx_rsrc_kind_t kind, uint64_t base, size_t size,
                                         ResourceStorage* = nullptr);
  static void DumpResources();
  static void DumpAllocators();

  template <typename T>
  static zx_status_t ForEachResource(T func, ResourceStorage* storage = nullptr)
      TA_EXCL(ResourcesLock::Get()) {
    Guard<Mutex> guard{ResourcesLock::Get()};
    return ForEachResourceLocked(func, (storage != nullptr) ? storage : &static_storage_);
  }

  bool IsRangedRoot(zx_rsrc_kind_t kind) const {
    switch (kind_) {
      case ZX_RSRC_KIND_ROOT:
        return false;
    }
    return (kind_ == kind && base_ == 0 && size_ == 0);
  }

  zx_obj_type_t get_type() const final { return ZX_OBJ_TYPE_RESOURCE; }

  // Returns a null-terminated name, or the empty string if set_name() has not
  // been called.
  [[nodiscard]] zx_status_t get_name(char (&out_name)[ZX_MAX_NAME_LEN]) const final {
    name_.get(ZX_MAX_NAME_LEN, out_name);
    return ZX_OK;
  }

  // Sets the name of the object. May truncate internally. |size| is the size
  // of the buffer pointed to by |name|.
  [[nodiscard]] zx_status_t set_name(const char* name, size_t size) final {
    return name_.set(name, size);
  }

  uint64_t get_base() const { return base_; }
  size_t get_size() const { return size_; }
  uint32_t get_kind() const { return kind_; }
  uint32_t get_flags() const { return flags_; }
  ~ResourceDispatcher();

 private:
  ResourceDispatcher(zx_rsrc_kind_t kind, uint64_t base, size_t size, uint32_t flags,
                     RegionAllocator::Region::UPtr&& region, ResourceStorage* storage);

  template <typename T>
  static zx_status_t ForEachResourceLocked(T callback, ResourceStorage* storage)
      TA_REQ(ResourcesLock::Get()) {
    for (const auto& resource : storage->resource_list) {
      zx_status_t status = callback(resource);
      if (status != ZX_OK) {
        return status;
      }
    }
    return ZX_OK;
  }

  const zx_rsrc_kind_t kind_;
  const uint64_t base_;
  const size_t size_;
  const uint32_t flags_;
  ResourceList* resource_list_;
  fbl::Name<ZX_MAX_NAME_LEN> name_;
  RegionAllocator::Region::UPtr exclusive_region_;

  // Static tracking data structures for physical address space allocations.
  // Exclusive allocations are pulled out of the RegionAllocators, and all
  // allocations are added to |static_resource_list_|. Shared allocations will
  // check that no exclusive reservation exists, but then release the region
  // back to the allocator. Likewise, exclusive allocations will check to
  // ensure that the region has not already been allocated as a shared region
  // by checking the static resource list.
  DECLARE_SINGLETON_MUTEX(ResourcesLock);
  static RegionAllocator::RegionPool::RefPtr region_pool_;
  // A single global list is used for all resources so that root and hypervisor resources can
  // still be tracked, and filtering can be done via client tools/commands when displaying
  // the list is concerned.
  static ResourceStorage static_storage_ TA_GUARDED(ResourcesLock::Get());
};

#endif  // ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_RESOURCE_DISPATCHER_H_
