// Copyright 2018 The Chromium 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 "base/fuchsia/async_dispatcher.h"

#include <lib/async/default.h>
#include <lib/async/task.h>
#include <lib/async/wait.h>
#include <lib/zx/handle.h>
#include <lib/zx/time.h>
#include <zircon/syscalls.h>

#include "base/fuchsia/fuchsia_logging.h"
#include "starboard/types.h"

namespace base {

namespace {

template <typename T>
uintptr_t key_from_ptr(T* ptr) {
  return reinterpret_cast<uintptr_t>(ptr);
};

}  // namespace

class AsyncDispatcher::ExceptionState : public LinkNode<ExceptionState> {
 public:
  explicit ExceptionState(AsyncDispatcher* async_dispatcher) {
    async_dispatcher->exception_list_.Append(this);
  }
  ~ExceptionState() { RemoveFromList(); }

  async_exception_t* exception() {
    // ExceptionState objects are allocated in-place in the |state| field of an
    // enclosing async_exceptionwait_t, so async_exception_t address can be
    // calculated by subtracting state offset in async_exception_t from |this|.
    static_assert(std::is_standard_layout<async_exception_t>(),
                  "async_wait_t is expected to have standard layout.");
    return reinterpret_cast<async_exception_t*>(
        reinterpret_cast<uint8_t*>(this) - offsetof(async_exception_t, state));
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ExceptionState);
};

class AsyncDispatcher::WaitState : public LinkNode<WaitState> {
 public:
  explicit WaitState(AsyncDispatcher* async_dispatcher) {
    async_dispatcher->wait_list_.Append(this);
  }
  ~WaitState() { RemoveFromList(); }

  async_wait_t* wait() {
    // WaitState objects are allocated in-place in the |state| field of an
    // enclosing async_wait_t, so async_wait_t address can be calculated by
    // subtracting state offset in async_wait_t from |this|.
    static_assert(std::is_standard_layout<async_wait_t>(),
                  "async_wait_t is expected to have standard layout.");
    return reinterpret_cast<async_wait_t*>(reinterpret_cast<uint8_t*>(this) -
                                           offsetof(async_wait_t, state));
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(WaitState);
};

class AsyncDispatcher::TaskState : public LinkNode<TaskState> {
 public:
  explicit TaskState(LinkNode<TaskState>* previous_task) {
    InsertAfter(previous_task);
  }
  ~TaskState() { RemoveFromList(); }

  async_task_t* task() {
    // TaskState objects are allocated in-place in the |state| field of an
    // enclosing async_task_t, so async_task_t address can be calculated by
    // subtracting state offset in async_task_t from |this|.
    static_assert(std::is_standard_layout<async_task_t>(),
                  "async_task_t is expected to have standard layout.");
    return reinterpret_cast<async_task_t*>(reinterpret_cast<uint8_t*>(this) -
                                           offsetof(async_task_t, state));
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(TaskState);
};

AsyncDispatcher::AsyncDispatcher() : ops_storage_({}) {
  zx_status_t status = zx::port::create(0u, &port_);
  ZX_DCHECK(status == ZX_OK, status);

  status = zx::timer::create(0u, ZX_CLOCK_MONOTONIC, &timer_);
  ZX_DCHECK(status == ZX_OK, status);
  status = timer_.wait_async(port_, key_from_ptr(&timer_), ZX_TIMER_SIGNALED,
                             ZX_WAIT_ASYNC_REPEATING);
  ZX_DCHECK(status == ZX_OK, status);

  status = zx::event::create(0, &stop_event_);
  ZX_DCHECK(status == ZX_OK, status);
  status = stop_event_.wait_async(port_, key_from_ptr(&stop_event_),
                                  ZX_EVENT_SIGNALED, ZX_WAIT_ASYNC_REPEATING);
  ZX_DCHECK(status == ZX_OK, status);

  ops_storage_.version = ASYNC_OPS_V2;
  ops_storage_.v1.now = NowOp;
  ops_storage_.v1.begin_wait = BeginWaitOp;
  ops_storage_.v1.cancel_wait = CancelWaitOp;
  ops_storage_.v1.post_task = PostTaskOp;
  ops_storage_.v1.cancel_task = CancelTaskOp;
  ops_storage_.v1.queue_packet = QueuePacketOp;
  ops_storage_.v1.set_guest_bell_trap = SetGuestBellTrapOp;
  ops_storage_.v2.bind_exception_port = BindExceptionPortOp;
  ops_storage_.v2.unbind_exception_port = UnbindExceptionPortOp;
  ops = &ops_storage_;

  DCHECK(!async_get_default_dispatcher());
  async_set_default_dispatcher(this);
}

AsyncDispatcher::~AsyncDispatcher() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK_EQ(async_get_default_dispatcher(), this);

  // Some waits and tasks may be canceled while the dispatcher is being
  // destroyed, so pop-from-head until none remain.

  while (!exception_list_.empty()) {
    ExceptionState* state = exception_list_.head()->value();
    async_exception_t* exception = state->exception();
    state->~ExceptionState();
    exception->handler(this, exception, ZX_ERR_CANCELED, nullptr);
  }

  while (!wait_list_.empty()) {
    WaitState* state = wait_list_.head()->value();
    async_wait_t* wait = state->wait();
    state->~WaitState();
    wait->handler(this, wait, ZX_ERR_CANCELED, nullptr);
  }

  while (!task_list_.empty()) {
    TaskState* state = task_list_.head()->value();
    async_task_t* task = state->task();
    state->~TaskState();
    task->handler(this, task, ZX_ERR_CANCELED);
  }

  async_set_default_dispatcher(nullptr);
}

zx_status_t AsyncDispatcher::DispatchOrWaitUntil(zx_time_t deadline) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  zx_port_packet_t packet = {};
  zx_status_t status = port_.wait(zx::time(deadline), &packet);
  if (status != ZX_OK)
    return status;

  if (ZX_PKT_IS_SIGNAL_ONE(packet.type) || ZX_PKT_IS_SIGNAL_REP(packet.type)) {
    if (packet.key == key_from_ptr(&timer_)) {
      // |timer_| has expired.
      DCHECK(packet.signal.observed & ZX_TIMER_SIGNALED);
      DispatchTasks();
      return ZX_OK;
    } else if (packet.key == key_from_ptr(&stop_event_)) {
      // Stop() was called.
      DCHECK(packet.signal.observed & ZX_EVENT_SIGNALED);
      status = zx_object_signal(stop_event_.get(), ZX_EVENT_SIGNALED, 0);
      ZX_DCHECK(status == ZX_OK, status);
      return ZX_ERR_CANCELED;
    } else {
      DCHECK_EQ(packet.type, ZX_PKT_TYPE_SIGNAL_ONE);
      auto* wait = reinterpret_cast<async_wait_t*>(packet.key);

      // Clean the state before invoking the handler: it may destroy |*wait|.
      auto* state = reinterpret_cast<WaitState*>(&wait->state);
      state->~WaitState();

      wait->handler(this, wait, packet.status, &packet.signal);

      return ZX_OK;
    }
  } else if (ZX_PKT_IS_EXCEPTION(packet.type)) {
    auto* exception = reinterpret_cast<async_exception_t*>(packet.key);

    // |exception| may have been deleted by the time |handler| returns.
    exception->handler(this, exception, packet.status, &packet);

    return ZX_OK;
  }

  NOTREACHED();
  return ZX_ERR_INTERNAL;
}

void AsyncDispatcher::Stop() {
  // Can be called on any thread.
  zx_status_t status =
      zx_object_signal(stop_event_.get(), 0, ZX_EVENT_SIGNALED);
  ZX_DCHECK(status == ZX_OK, status);
}

zx_time_t AsyncDispatcher::NowOp(async_dispatcher_t* async) {
  DCHECK(async);
  return zx_clock_get(ZX_CLOCK_MONOTONIC);
}

zx_status_t AsyncDispatcher::BeginWaitOp(async_dispatcher_t* async,
                                         async_wait_t* wait) {
  return static_cast<AsyncDispatcher*>(async)->BeginWait(wait);
}

zx_status_t AsyncDispatcher::CancelWaitOp(async_dispatcher_t* async,
                                          async_wait_t* wait) {
  return static_cast<AsyncDispatcher*>(async)->CancelWait(wait);
}

zx_status_t AsyncDispatcher::PostTaskOp(async_dispatcher_t* async,
                                        async_task_t* task) {
  return static_cast<AsyncDispatcher*>(async)->PostTask(task);
}

zx_status_t AsyncDispatcher::CancelTaskOp(async_dispatcher_t* async,
                                          async_task_t* task) {
  return static_cast<AsyncDispatcher*>(async)->CancelTask(task);
}

zx_status_t AsyncDispatcher::QueuePacketOp(async_dispatcher_t* async,
                                           async_receiver_t* receiver,
                                           const zx_packet_user_t* data) {
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t AsyncDispatcher::SetGuestBellTrapOp(async_dispatcher_t* async,
                                                async_guest_bell_trap_t* trap,
                                                zx_handle_t guest,
                                                zx_vaddr_t addr,
                                                size_t length) {
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t AsyncDispatcher::BindExceptionPortOp(async_dispatcher_t* async,
                                                 async_exception_t* exception) {
  return static_cast<AsyncDispatcher*>(async)->BindExceptionPort(exception);
}

zx_status_t AsyncDispatcher::UnbindExceptionPortOp(
    async_dispatcher_t* async,
    async_exception_t* exception) {
  return static_cast<AsyncDispatcher*>(async)->UnbindExceptionPort(exception);
}

zx_status_t AsyncDispatcher::BeginWait(async_wait_t* wait) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  static_assert(sizeof(AsyncDispatcher::WaitState) <= sizeof(async_state_t),
                "WaitState is too big");
  WaitState* state = new (&wait->state) WaitState(this);
  zx_status_t status =
      zx::unowned_handle(wait->object)
          ->wait_async(port_, reinterpret_cast<uintptr_t>(wait), wait->trigger,
                       ZX_WAIT_ASYNC_ONCE);

  if (status != ZX_OK)
    state->~WaitState();

  return status;
}

zx_status_t AsyncDispatcher::CancelWait(async_wait_t* wait) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  if (!wait->state.reserved[0])
    return ZX_ERR_NOT_FOUND;

  zx_status_t status = port_.cancel(*zx::unowned_handle(wait->object),
                                    reinterpret_cast<uintptr_t>(wait));
  if (status == ZX_OK) {
    auto* state = reinterpret_cast<WaitState*>(&(wait->state));
    state->~WaitState();
  }

  return status;
}

zx_status_t AsyncDispatcher::PostTask(async_task_t* task) {
  // Can be called on any thread.
  AutoLock lock(lock_);

  // Find correct position for the new task in |task_list_| to keep the list
  // sorted by deadline. This implementation has O(N) complexity, but it's
  // acceptable - async task are not expected to be used frequently.
  // TODO(sergeyu): Consider using a more efficient data structure if tasks
  // performance becomes important.
  LinkNode<TaskState>* node;
  for (node = task_list_.head(); node != task_list_.end();
       node = node->previous()) {
    if (task->deadline >= node->value()->task()->deadline)
      break;
  }

  static_assert(sizeof(AsyncDispatcher::TaskState) <= sizeof(async_state_t),
                "TaskState is too big");

  // Will insert new task after |node|.
  new (&task->state) TaskState(node);

  if (reinterpret_cast<TaskState*>(&task->state) == task_list_.head()) {
    // Task inserted at head. Earliest deadline changed.
    RestartTimerLocked();
  }

  return ZX_OK;
}

zx_status_t AsyncDispatcher::CancelTask(async_task_t* task) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  AutoLock lock(lock_);

  if (!task->state.reserved[0])
    return ZX_ERR_NOT_FOUND;

  auto* state = reinterpret_cast<TaskState*>(&task->state);
  state->~TaskState();

  return ZX_OK;
}

zx_status_t AsyncDispatcher::BindExceptionPort(async_exception_t* exception) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  static_assert(
      sizeof(AsyncDispatcher::ExceptionState) <= sizeof(async_state_t),
      "ExceptionState is too big");
  ExceptionState* state = new (&exception->state) ExceptionState(this);

  zx_status_t status = zx_task_bind_exception_port(
      exception->task, port_.get(), reinterpret_cast<uintptr_t>(exception),
      exception->options);
  if (status != ZX_OK)
    state->~ExceptionState();

  return status;
}

zx_status_t AsyncDispatcher::UnbindExceptionPort(async_exception_t* exception) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  if (!exception->state.reserved[0])
    return ZX_ERR_NOT_FOUND;

  zx_status_t status = zx_task_bind_exception_port(
      exception->task, ZX_HANDLE_INVALID,
      reinterpret_cast<uintptr_t>(exception), exception->options);
  if (status == ZX_OK) {
    auto* state = reinterpret_cast<ExceptionState*>(&exception->state);
    state->~ExceptionState();
  }

  return status;
}

void AsyncDispatcher::DispatchTasks() {
  // Snapshot now value to set implicit bound for the tasks that will run before
  // DispatchTasks() returns. This also helps to avoid calling zx_clock_get()
  // more than necessary.
  zx_time_t now = zx_clock_get(ZX_CLOCK_MONOTONIC);

  while (true) {
    async_task_t* task;
    {
      AutoLock lock(lock_);
      if (task_list_.empty())
        break;

      TaskState* task_state = task_list_.head()->value();
      task = task_state->task();

      if (task->deadline > now) {
        RestartTimerLocked();
        break;
      }

      task_state->~TaskState();

      // ~TaskState() is expected to reset the state to 0. The destructor
      // removes the task from the |task_list_| and LinkNode::RemoveFromList()
      // sets both its fields to nullptr, which is equivalent to resetting the
      // state to 0.
      DCHECK_EQ(task->state.reserved[0], 0u);
    }

    // The handler is responsible for freeing the |task| or it may reuse it.
    task->handler(this, task, ZX_OK);
  }
}

void AsyncDispatcher::RestartTimerLocked() {
  lock_.AssertAcquired();

  if (task_list_.empty())
    return;
  zx_time_t deadline = task_list_.head()->value()->task()->deadline;
  zx_status_t status = timer_.set(zx::time(deadline), zx::duration());
  ZX_DCHECK(status == ZX_OK, status);
}

}  // namespace base
