// 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

#include "object/fifo_dispatcher.h"

#include <lib/counters.h>
#include <string.h>
#include <zircon/rights.h>

#include <fbl/alloc_checker.h>
#include <fbl/auto_lock.h>
#include <object/handle.h>

KCOUNTER(dispatcher_fifo_create_count, "dispatcher.fifo.create")
KCOUNTER(dispatcher_fifo_destroy_count, "dispatcher.fifo.destroy")

// static
zx_status_t FifoDispatcher::Create(size_t count, size_t elemsize, uint32_t options,
                                   KernelHandle<FifoDispatcher>* handle0,
                                   KernelHandle<FifoDispatcher>* handle1, zx_rights_t* rights) {
  // count and elemsize must be nonzero
  // count must be a power of two
  // total size must be <= kMaxSizeBytes
  if (!count || !elemsize || (count & (count - 1)) || (count > kMaxSizeBytes) ||
      (elemsize > kMaxSizeBytes) || ((count * elemsize) > kMaxSizeBytes)) {
    return ZX_ERR_OUT_OF_RANGE;
  }

  fbl::AllocChecker ac;
  auto holder0 = fbl::AdoptRef(new (&ac) PeerHolder<FifoDispatcher>());
  if (!ac.check())
    return ZX_ERR_NO_MEMORY;
  auto holder1 = holder0;

  auto data0 = ktl::unique_ptr<uint8_t[]>(new (&ac) uint8_t[count * elemsize]);
  if (!ac.check())
    return ZX_ERR_NO_MEMORY;

  KernelHandle fifo0(fbl::AdoptRef(
      new (&ac) FifoDispatcher(ktl::move(holder0), options, static_cast<uint32_t>(count),
                               static_cast<uint32_t>(elemsize), ktl::move(data0))));
  if (!ac.check())
    return ZX_ERR_NO_MEMORY;

  auto data1 = ktl::unique_ptr<uint8_t[]>(new (&ac) uint8_t[count * elemsize]);
  if (!ac.check())
    return ZX_ERR_NO_MEMORY;

  KernelHandle fifo1(fbl::AdoptRef(
      new (&ac) FifoDispatcher(ktl::move(holder1), options, static_cast<uint32_t>(count),
                               static_cast<uint32_t>(elemsize), ktl::move(data1))));
  if (!ac.check())
    return ZX_ERR_NO_MEMORY;

  fifo0.dispatcher()->Init(fifo1.dispatcher());
  fifo1.dispatcher()->Init(fifo0.dispatcher());

  *rights = default_rights();
  *handle0 = ktl::move(fifo0);
  *handle1 = ktl::move(fifo1);
  return ZX_OK;
}

FifoDispatcher::FifoDispatcher(fbl::RefPtr<PeerHolder<FifoDispatcher>> holder, uint32_t /*options*/,
                               uint32_t count, uint32_t elem_size, ktl::unique_ptr<uint8_t[]> data)
    : PeeredDispatcher(ktl::move(holder), ZX_FIFO_WRITABLE),
      elem_count_(count),
      elem_size_(elem_size),
      mask_(count - 1),
      head_(0u),
      tail_(0u),
      data_(ktl::move(data)) {
  kcounter_add(dispatcher_fifo_create_count, 1);
}

FifoDispatcher::~FifoDispatcher() { kcounter_add(dispatcher_fifo_destroy_count, 1); }

// Thread safety analysis disabled as this happens during creation only,
// when no other thread could be accessing the object.
void FifoDispatcher::Init(fbl::RefPtr<FifoDispatcher> other) TA_NO_THREAD_SAFETY_ANALYSIS {
  peer_ = ktl::move(other);
  peer_koid_ = peer_->get_koid();
}

zx_status_t FifoDispatcher::UserSignalSelfLocked(uint32_t clear_mask, uint32_t set_mask) {
  canary_.Assert();
  UpdateStateLocked(clear_mask, set_mask);
  return ZX_OK;
}

void FifoDispatcher::on_zero_handles_locked() { canary_.Assert(); }

void FifoDispatcher::OnPeerZeroHandlesLocked() {
  canary_.Assert();

  UpdateStateLocked(ZX_FIFO_WRITABLE, ZX_FIFO_PEER_CLOSED);
}

zx_status_t FifoDispatcher::WriteFromUser(size_t elem_size, user_in_ptr<const uint8_t> ptr,
                                          size_t count,
                                          size_t* actual) TA_NO_THREAD_SAFETY_ANALYSIS {
  canary_.Assert();

  Guard<fbl::Mutex> guard{get_lock()};
  if (!peer_)
    return ZX_ERR_PEER_CLOSED;
  return peer_->WriteSelfLocked(elem_size, ptr, count, actual);
}

zx_status_t FifoDispatcher::WriteSelfLocked(size_t elem_size, user_in_ptr<const uint8_t> ptr,
                                            size_t count,
                                            size_t* actual) TA_NO_THREAD_SAFETY_ANALYSIS {
  canary_.Assert();

  if (elem_size != elem_size_)
    return ZX_ERR_OUT_OF_RANGE;
  if (count == 0)
    return ZX_ERR_OUT_OF_RANGE;

  uint32_t old_head = head_;

  // total number of available empty slots in the fifo
  size_t avail = elem_count_ - (head_ - tail_);

  if (avail == 0)
    return ZX_ERR_SHOULD_WAIT;

  bool was_empty = (avail == elem_count_);

  if (count > avail)
    count = avail;

  while (count > 0) {
    uint32_t offset = (head_ & mask_);

    // number of slots from target to end, inclusive
    uint32_t n = elem_count_ - offset;

    // number of slots we can actually copy
    size_t to_copy = (count > n) ? n : count;

    zx_status_t status =
        ptr.copy_array_from_user(&data_[offset * elem_size_], to_copy * elem_size_);
    if (status != ZX_OK) {
      // roll back, in case this is the second copy
      head_ = old_head;
      return ZX_ERR_INVALID_ARGS;
    }

    // adjust head and count
    // due to size limitations on fifo, to_copy will always fit in a u32
    head_ += static_cast<uint32_t>(to_copy);
    count -= to_copy;
    ptr = ptr.byte_offset(to_copy * elem_size_);
  }

  // if was empty, we've become readable
  if (was_empty)
    UpdateStateLocked(0u, ZX_FIFO_READABLE);

  // if now full, we're no longer writable
  if (elem_count_ == (head_ - tail_))
    peer_->UpdateStateLocked(ZX_FIFO_WRITABLE, 0u);

  *actual = (head_ - old_head);
  return ZX_OK;
}

zx_status_t FifoDispatcher::ReadToUser(size_t elem_size, user_out_ptr<uint8_t> ptr, size_t count,
                                       size_t* actual) TA_NO_THREAD_SAFETY_ANALYSIS {
  canary_.Assert();

  if (elem_size != elem_size_)
    return ZX_ERR_OUT_OF_RANGE;
  if (count == 0)
    return ZX_ERR_OUT_OF_RANGE;

  Guard<fbl::Mutex> guard{get_lock()};

  uint32_t old_tail = tail_;

  // total number of available entries to read from the fifo
  size_t avail = (head_ - tail_);

  if (avail == 0)
    return peer_ ? ZX_ERR_SHOULD_WAIT : ZX_ERR_PEER_CLOSED;

  bool was_full = (avail == elem_count_);

  if (count > avail)
    count = avail;

  while (count > 0) {
    uint32_t offset = (tail_ & mask_);

    // number of slots from target to end, inclusive
    uint32_t n = elem_count_ - offset;

    // number of slots we can actually copy
    size_t to_copy = (count > n) ? n : count;

    zx_status_t status = ptr.copy_array_to_user(&data_[offset * elem_size_], to_copy * elem_size_);
    if (status != ZX_OK) {
      // roll back, in case this is the second copy
      tail_ = old_tail;
      return ZX_ERR_INVALID_ARGS;
    }

    // adjust tail and count
    // due to size limitations on fifo, to_copy will always fit in a u32
    tail_ += static_cast<uint32_t>(to_copy);
    count -= to_copy;
    ptr = ptr.byte_offset(to_copy * elem_size_);
  }

  // if we were full, we have become writable
  if (was_full && peer_)
    peer_->UpdateStateLocked(0u, ZX_FIFO_WRITABLE);

  // if we've become empty, we're no longer readable
  if ((head_ - tail_) == 0)
    UpdateStateLocked(ZX_FIFO_READABLE, 0u);

  *actual = (tail_ - old_tail);
  return ZX_OK;
}
