// 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<BrwLock, BrwLock::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<BrwLock, BrwLock::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<BrwLock, BrwLock::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);
    }
}
