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

#include <inttypes.h>
#include <lib/ktrace.h>
#include <lib/user_copy/user_ptr.h>
#include <platform.h>
#include <trace.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <fbl/inline_array.h>
#include <fbl/ref_ptr.h>
#include <kernel/event.h>
#include <kernel/lockdep.h>
#include <kernel/thread.h>
#include <object/dispatcher.h>
#include <object/handle.h>
#include <object/port_dispatcher.h>
#include <object/process_dispatcher.h>
#include <object/wait_signal_observer.h>

#include "priv.h"

#define LOCAL_TRACE 0

constexpr uint32_t kMaxWaitHandleCount = ZX_WAIT_MANY_MAX_ITEMS;

static_assert(ZX_WAIT_MANY_MAX_ITEMS == ZX_CHANNEL_MAX_MSG_HANDLES);

// zx_status_t zx_object_wait_one
zx_status_t sys_object_wait_one(zx_handle_t handle_value, zx_signals_t signals, zx_time_t deadline,
                                user_out_ptr<zx_signals_t> observed) {
  LTRACEF("handle %x\n", handle_value);

  Event event;

  zx_status_t result;
  WaitSignalObserver wait_signal_observer;
  uint32_t koid;

  auto up = ProcessDispatcher::GetCurrent();
  {
    Guard<BrwLockPi, BrwLockPi::Reader> guard{up->handle_table().get_lock()};

    Handle* handle = up->handle_table().GetHandleLocked(handle_value);
    if (!handle)
      return ZX_ERR_BAD_HANDLE;
    if (!handle->HasRights(ZX_RIGHT_WAIT))
      return ZX_ERR_ACCESS_DENIED;

    result = wait_signal_observer.Begin(&event, handle, signals);
    if (result != ZX_OK)
      return result;

    koid = static_cast<uint32_t>(handle->dispatcher()->get_koid());
  }

  ktrace(TAG_WAIT_ONE, koid, signals, (uint32_t)deadline, (uint32_t)(deadline >> 32));

  const TimerSlack slack = up->GetTimerSlackPolicy();
  const Deadline slackDeadline(deadline, slack);

  // Event::Wait() will return ZX_OK if already signaled,
  // even if the deadline has passed.  It will return ZX_ERR_TIMED_OUT
  // after the deadline passes if the event has not been
  // signaled.
  {
    ThreadDispatcher::AutoBlocked by(ThreadDispatcher::Blocked::WAIT_ONE);
    result = event.Wait(slackDeadline);
  }

  // Regardless of wait outcome, we must call End().
  auto signals_state = wait_signal_observer.End();

  ktrace(TAG_WAIT_ONE_DONE, koid, signals_state, result, 0);

  if (observed) {
    zx_status_t status = observed.copy_to_user(signals_state);
    if (status != ZX_OK)
      return status;
  }

  if (signals_state & ZX_SIGNAL_HANDLE_CLOSED)
    return ZX_ERR_CANCELED;

  return result;
}

// zx_status_t zx_object_wait_many
zx_status_t sys_object_wait_many(user_inout_ptr<zx_wait_item_t> user_items, size_t count,
                                 zx_time_t deadline) {
  LTRACEF("count %zu\n", count);

  const auto up = ProcessDispatcher::GetCurrent();
  const Deadline slackDeadline(deadline, up->GetTimerSlackPolicy());

  if (!count) {
    const zx_time_t now = current_time();
    {
      ThreadDispatcher::AutoBlocked by(ThreadDispatcher::Blocked::WAIT_MANY);
      zx_status_t result = Thread::Current::SleepEtc(slackDeadline, Interruptible::Yes, now);
      if (result != ZX_OK) {
        return result;
      }
    }
    return ZX_ERR_TIMED_OUT;
  }

  if (count > kMaxWaitHandleCount)
    return ZX_ERR_OUT_OF_RANGE;

  zx_wait_item_t items[kMaxWaitHandleCount];
  if (user_items.copy_array_from_user(items, count) != ZX_OK)
    return ZX_ERR_INVALID_ARGS;

  // WaitSignalObserver is heavier than it looks so make sure we know how
  // much stack InlineArray is going to use, given limited kernel stack size.
  static_assert(sizeof(WaitSignalObserver) * 8 < 640);

  fbl::AllocChecker ac;
  fbl::InlineArray<WaitSignalObserver, 8u> wait_signal_observers(&ac, count);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  Event event;

  // We may need to unwind (which can be done outside the lock).
  zx_status_t result = ZX_OK;
  size_t num_added = 0;
  {
    Guard<BrwLockPi, BrwLockPi::Reader> guard{up->handle_table().get_lock()};

    for (; num_added != count; ++num_added) {
      Handle* handle = up->handle_table().GetHandleLocked(items[num_added].handle);
      if (!handle) {
        result = ZX_ERR_BAD_HANDLE;
        break;
      }
      if (!handle->HasRights(ZX_RIGHT_WAIT)) {
        result = ZX_ERR_ACCESS_DENIED;
        break;
      }

      result = wait_signal_observers[num_added].Begin(&event, handle, items[num_added].waitfor);
      if (result != ZX_OK)
        break;
    }
  }
  if (result != ZX_OK) {
    for (size_t ix = 0; ix < num_added; ++ix)
      wait_signal_observers[ix].End();
    return result;
  }

  // Event::Wait() will return ZX_OK if already signaled,
  // even if deadline has passed.  It will return ZX_ERR_TIMED_OUT
  // after the deadline passes if the event has not been
  // signaled.
  {
    ThreadDispatcher::AutoBlocked by(ThreadDispatcher::Blocked::WAIT_MANY);
    result = event.Wait(slackDeadline);
  }

  // Regardless of wait outcome, we must call End().
  zx_signals_t combined = 0;
  for (size_t ix = 0; ix != count; ++ix) {
    combined |= (items[ix].pending = wait_signal_observers[ix].End());
  }

  if (user_items.copy_array_to_user(items, count) != ZX_OK)
    return ZX_ERR_INVALID_ARGS;

  if (combined & ZX_SIGNAL_HANDLE_CLOSED)
    return ZX_ERR_CANCELED;

  return result;
}

// zx_status_t zx_object_wait_async
zx_status_t sys_object_wait_async(zx_handle_t handle_value, zx_handle_t port_handle_value,
                                  uint64_t key, zx_signals_t signals, uint32_t options) {
  LTRACEF("handle %x\n", handle_value);

  if ((options & ~(ZX_WAIT_ASYNC_TIMESTAMP | ZX_WAIT_ASYNC_EDGE)) != 0u) {
    return ZX_ERR_INVALID_ARGS;
  }

  auto up = ProcessDispatcher::GetCurrent();

  {
    Guard<BrwLockPi, BrwLockPi::Reader> guard{up->handle_table().get_lock()};

    // Note, we're doing this all while holding the handle table lock for two reasons.
    //
    // First, this thread may be racing with another thread that's closing the last handle to
    // the port. By holding the lock we can ensure that this syscall behaves as if the port was
    // closed just *before* the syscall started or closed just *after* it has completed.
    //
    // Second, MakeObserver takes a Handle. By holding the lock we ensure the Handle isn't
    // destroyed out from under it.

    Handle* port_handle = up->handle_table().GetHandleLocked(port_handle_value);
    if (!port_handle) {
      return ZX_ERR_BAD_HANDLE;
    }
    fbl::RefPtr<Dispatcher> disp = port_handle->dispatcher();
    fbl::RefPtr<PortDispatcher> port = DownCastDispatcher<PortDispatcher>(&disp);
    if (!port) {
      return ZX_ERR_WRONG_TYPE;
    }
    if (!port_handle->HasRights(ZX_RIGHT_WRITE)) {
      return ZX_ERR_ACCESS_DENIED;
    }

    Handle* handle = up->handle_table().GetHandleLocked(handle_value);
    if (!handle) {
      return ZX_ERR_BAD_HANDLE;
    }
    if (!handle->HasRights(ZX_RIGHT_WAIT)) {
      return ZX_ERR_ACCESS_DENIED;
    }

    return port->MakeObserver(options, handle, key, signals);
  }
}
