// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <utility>

#include <dispatcher-pool/dispatcher-event-source.h>
#include <dispatcher-pool/dispatcher-execution-domain.h>
#include <dispatcher-pool/dispatcher-thread-pool.h>

namespace dispatcher {

EventSource::EventSource(zx_signals_t process_signal_mask)
    : process_signal_mask_(process_signal_mask) {}

EventSource::~EventSource() {
  ZX_DEBUG_ASSERT(domain_ == nullptr);
  ZX_DEBUG_ASSERT(!InExecutionDomain());
  ZX_DEBUG_ASSERT(!InPendingList());
  ZX_DEBUG_ASSERT(dispatch_state() == DispatchState::Idle);
}

void EventSource::InternalDeactivateLocked() {
  // If we are no longer active, we can just get out now.  We should be able
  // to assert that our handle has been closed and that we are in either the
  // Idle or Dispatching state, or that handle is still valid and we are in
  // WaitingOnPort state (meaning that there is a thread in flight from the
  // thread pool which is about to realize that we have become deactivated)
  if (!is_active()) {
    ZX_DEBUG_ASSERT((handle_.is_valid() && (dispatch_state() == DispatchState::WaitingOnPort)) ||
                    (!handle_.is_valid() && ((dispatch_state() == DispatchState::Dispatching) ||
                                             (dispatch_state() == DispatchState::Idle))));
    return;
  }

  // Attempt to cancel any pending operations.  Do not close the handle if it
  // was too late to cancel and we are still waiting on the port.
  CancelPendingLocked();
  if (dispatch_state() != DispatchState::WaitingOnPort) {
    ZX_DEBUG_ASSERT((dispatch_state() == DispatchState::Idle) ||
                    (dispatch_state() == DispatchState::Dispatching));
    handle_.reset();
  }

  // If we still have a domain, remove ourselves from the domain's event
  // source list, then release our reference to it.
  if (domain_ != nullptr) {
    domain_->RemoveEventSource(this);
    domain_ = nullptr;
  }

  // Release our cached thread pool reference.
  thread_pool_.reset();
}

zx_status_t EventSource::ActivateLocked(zx::handle handle, fbl::RefPtr<ExecutionDomain> domain) {
  if ((domain == nullptr) || !handle.is_valid())
    return ZX_ERR_INVALID_ARGS;

  if (is_active() || handle_.is_valid())
    return ZX_ERR_BAD_STATE;
  ZX_DEBUG_ASSERT(thread_pool_ == nullptr);

  auto thread_pool = domain->GetThreadPool();
  if (thread_pool == nullptr)
    return ZX_ERR_BAD_STATE;

  // Add ourselves to our domain's list of event sources.
  zx_status_t res = domain->AddEventSource(fbl::RefPtr(this));
  if (res != ZX_OK)
    return res;

  handle_ = std::move(handle);
  domain_ = std::move(domain);
  thread_pool_ = std::move(thread_pool);

  return ZX_OK;
}

zx_status_t EventSource::WaitOnPortLocked() {
  // If we are attempting to wait, we should not already have a wait pending.
  // In particular, we need to be in the idle state.
  ZX_DEBUG_ASSERT(dispatch_state() == DispatchState::Idle);

  // Attempting to wait when our domain is null indicates that we are in the
  // process of dying, and the wait should be denied.
  if (!is_active())
    return ZX_ERR_BAD_STATE;

  zx_status_t res = DoPortWaitLocked();

  // If the wait async succeeded, then we now have a pending wait operation,
  // and the kernel is now holding an unmanaged reference to us.  Flag the
  // pending wait, and manually bump our ref count.
  if (res == ZX_OK) {
    dispatch_state_ = DispatchState::WaitingOnPort;
    this->AddRef();
  }

  return res;
}

zx_status_t EventSource::CancelPendingLocked() {
  // If we are still active, remove ourselves from the domain's
  // pending work list.
  if (is_active()) {
    // If we were on the pending work list, then our state must have been
    // DispatchPending (and now should be Idle)
    if (domain_->RemovePendingWork(this)) {
      ZX_DEBUG_ASSERT(dispatch_state() == DispatchState::DispatchPending);
      dispatch_state_ = DispatchState::Idle;
    }

    // If there is a wait operation currently pending, attempt to cancel it.
    //
    // If we succeed, manually drop the unmanaged reference which the kernel
    // was holding and transition to the Idle state.
    //
    // If we fail, it must be because the wait has completed and is being
    // dispatched on another thread.  Do not transition to Idle, or release
    // the kernel reference.
    if (dispatch_state() == DispatchState::WaitingOnPort) {
      zx_status_t res = DoPortCancelLocked();

      if (res == ZX_OK) {
        __UNUSED bool should_destruct;

        dispatch_state_ = DispatchState::Idle;
        should_destruct = this->Release();

        ZX_DEBUG_ASSERT(should_destruct == false);
      } else {
        ZX_DEBUG_ASSERT(res == ZX_ERR_NOT_FOUND);
      }
    }
  }

  return (dispatch_state() == DispatchState::Idle) ? ZX_OK : ZX_ERR_BAD_STATE;
}

zx_status_t EventSource::DoPortWaitLocked() {
  ZX_DEBUG_ASSERT(thread_pool_ != nullptr);
  return thread_pool_->WaitOnPort(handle_, reinterpret_cast<uint64_t>(this), process_signal_mask(),
                                  0);
}

zx_status_t EventSource::DoPortCancelLocked() {
  ZX_DEBUG_ASSERT(thread_pool_ != nullptr);
  return thread_pool_->CancelWaitOnPort(handle_, reinterpret_cast<uint64_t>(this));
}

bool EventSource::BeginDispatching() {
  fbl::AutoLock obj_lock(&obj_lock_);
  if (dispatch_state() != DispatchState::DispatchPending)
    return false;

  ZX_DEBUG_ASSERT(InPendingList());

  __UNUSED zx_status_t res;
  res = CancelPendingLocked();
  ZX_DEBUG_ASSERT(res == ZX_OK);
  ZX_DEBUG_ASSERT(dispatch_state() == DispatchState::Idle);

  dispatch_state_ = DispatchState::Dispatching;

  return true;
}

fbl::RefPtr<ExecutionDomain> EventSource::ScheduleDispatch(const zx_port_packet_t& pkt) {
  // Something interesting happened.  Enter the lock and...
  //
  // 1) Sanity check our dispatch state.  We should be in "WaitingOnPort.
  // 2) Assert that something interesting happened.
  // 3) If our domain is still active, add this event source to the pending work
  //    queue.  If we are the first event source to enter the queue, return a
  //    reference to our domain to the dispatcher thread so that it can start
  //    to process the pending work.
  fbl::AutoLock obj_lock(&obj_lock_);

  ZX_DEBUG_ASSERT(dispatch_state() == DispatchState::WaitingOnPort);

  ZX_DEBUG_ASSERT((pkt.type == ZX_PKT_TYPE_INTERRUPT) ||
                  (pkt.signal.observed & process_signal_mask()));

  if (!is_active()) {
    // We have no domain, we must have become deactivated while the thread
    // from the thread pool was in flight (making it impossible for the
    // Deactivator to reclaim the kernel's reference to us).  Go ahead and
    // transition to idle, and close our handle.
    dispatch_state_ = DispatchState::Idle;
    handle_.reset();
    return nullptr;
  }

  // Copy the pending port packet to the internal event source storage,
  // then add ourselves to the domain's pending queue.  If we were the
  // first event source to join our domain's pending queue, then take a
  // reference to our domain so that we can start to process pending work
  // once we have left the obj_lock.  If we are not the first to join the
  // queue, just get out.  The thread which is currently handling pending
  // jobs for this domain will handle this one when the time comes.
  pending_pkt_ = pkt;
  return domain_->AddPendingWork(this) ? domain_ : nullptr;
}

}  // namespace dispatcher
