// 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 <err.h>
#include <inttypes.h>
#include <trace.h>

#include <kernel/event.h>
#include <kernel/lockdep.h>
#include <kernel/thread.h>
#include <platform.h>

#include <lib/ktrace.h>
#include <lib/user_copy/user_ptr.h>

#include <object/dispatcher.h>
#include <object/handle.h>
#include <object/port_dispatcher.h>
#include <object/process_dispatcher.h>
#include <object/wait_state_observer.h>

#include <fbl/inline_array.h>
#include <fbl/ref_ptr.h>

#include <zircon/types.h>

#include "priv.h"

#define LOCAL_TRACE 0

// TODO(ZX-1349) Re-lower this to 8.
constexpr uint32_t kMaxWaitHandleCount = 16u;

// ensure public headers agree
static_assert(ZX_WAIT_MANY_MAX_ITEMS == kMaxWaitHandleCount, "");

// 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;
    WaitStateObserver wait_state_observer;

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

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

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

    auto koid = static_cast<uint32_t>(up->GetKoidForHandle(handle_value));
    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_state_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_sleep_etc(slackDeadline, /* interruptable */ true, 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;

    WaitStateObserver wait_state_observers[kMaxWaitHandleCount];
    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_lock()};

        for (; num_added != count; ++num_added) {
            Handle* handle = up->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_state_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_state_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_state_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);

    auto up = ProcessDispatcher::GetCurrent();

    {
        Guard<BrwLockPi, BrwLockPi::Reader> guard{up->handle_table_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->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->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);
    }
}
