// Copyright 2016 The Fuchsia Authors
// Copyright (c) 2008-2014 Travis Geiselbrecht
//
// 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

/**
 * @file
 * @brief  Event wait and signal functions for threads.
 * @defgroup event Events
 *
 * An event is a subclass of a wait queue.
 *
 * Threads wait for events, with optional timeouts.
 *
 * Events are "signaled", releasing waiting threads to continue.
 * Signals may be one-shot signals (EVENT_FLAG_AUTOUNSIGNAL), in which
 * case one signal releases only one thread, at which point it is
 * automatically cleared. Otherwise, signals release all waiting threads
 * to continue immediately until the signal is manually cleared with
 * event_unsignal().
 *
 * @{
 */

#include <assert.h>
#include <debug.h>
#include <err.h>
#include <kernel/event.h>
#include <kernel/spinlock.h>
#include <kernel/thread.h>
#include <kernel/thread_lock.h>
#include <sys/types.h>
#include <zircon/types.h>

/**
 * @brief  Initialize an event object
 *
 * @param e        Event object to initialize
 * @param initial  Initial value for "signaled" state
 * @param flags    0 or EVENT_FLAG_AUTOUNSIGNAL
 */
void event_init(event_t* e, bool initial, uint flags) {
    *e = (event_t)EVENT_INITIAL_VALUE(*e, initial, flags);
}

/**
 * @brief  Destroy an event object.
 *
 * Event's resources are freed and it may no longer be
 * used until event_init() is called again.
 * Will panic if there are any threads still waiting.
 *
 * @param e        Event object to initialize
 */
void event_destroy(event_t* e) {
    DEBUG_ASSERT(e->magic == EVENT_MAGIC);

    e->magic = 0;
    e->signaled = false;
    e->flags = 0;
    wait_queue_destroy(&e->wait);
}

static zx_status_t event_wait_worker(event_t* e, zx_time_t deadline,
                                     bool interruptable,
                                     uint signal_mask) {
    thread_t* current_thread = get_current_thread();
    zx_status_t ret = ZX_OK;

    DEBUG_ASSERT(e->magic == EVENT_MAGIC);
    DEBUG_ASSERT(!arch_blocking_disallowed());

    Guard<spin_lock_t, IrqSave> guard{ThreadLock::Get()};

    current_thread->interruptable = interruptable;

    if (e->signaled) {
        /* signaled, we're going to fall through */
        if (e->flags & EVENT_FLAG_AUTOUNSIGNAL) {
            /* autounsignal flag lets one thread fall through before unsignaling */
            e->signaled = false;
        }
    } else {
        /* unsignaled, block here */
        ret = wait_queue_block_with_mask(&e->wait, deadline, signal_mask);
    }

    current_thread->interruptable = false;

    return ret;
}

/**
 * @brief  Wait for event to be signaled
 *
 * If the event has already been signaled, this function
 * returns immediately.  Otherwise, the current thread
 * goes to sleep until the event object is signaled,
 * the deadline is reached, or the event object is destroyed
 * by another thread.
 *
 * @param e        Event object
 * @param deadline Deadline to abort at, in ns
 * @param interruptable  Allowed to interrupt if thread is signaled
 *
 * @return  0 on success, ZX_ERR_TIMED_OUT on timeout,
 *          other values depending on wait_result value
 *          when event_signal_etc is used.
 */
zx_status_t event_wait_deadline(event_t* e, zx_time_t deadline, bool interruptable) {
    return event_wait_worker(e, deadline, interruptable, 0);
}

/**
 * @brief  Wait for event to be signaled, ignoring existing signals in
           |signal_mask|.
 *
 * If the event has already been signaled (except for signals in
 * |signal_mask|), this function returns immediately.
 * Otherwise, the current thread goes to sleep until the event object is
 * signaled, or the event object is destroyed by another thread.
 * There is no deadline, and the caller must be interruptable.
 *
 * @param e        Event object
 *
 * @return  0 on success, other values depending on wait_result value
 *          when event_signal_etc is used.
 */
zx_status_t event_wait_with_mask(event_t* e, uint signal_mask) {
    return event_wait_worker(e, ZX_TIME_INFINITE, true, signal_mask);
}

static int event_signal_internal(event_t* e, bool reschedule,
                                 zx_status_t wait_result) TA_REQ(thread_lock) {
    DEBUG_ASSERT(e->magic == EVENT_MAGIC);

    int wake_count = 0;

    if (!e->signaled) {
        if (e->flags & EVENT_FLAG_AUTOUNSIGNAL) {
            /* try to release one thread and leave unsignaled if successful */
            if ((wake_count = wait_queue_wake_one(&e->wait, reschedule, wait_result)) <= 0) {
                /*
                 * if we didn't actually find a thread to wake up, go to
                 * signaled state and let the next call to event_wait
                 * unsignal the event.
                 */
                e->signaled = true;
            }
        } else {
            /* release all threads and remain signaled */
            e->signaled = true;
            wake_count = wait_queue_wake_all(&e->wait, reschedule, wait_result);
        }
    }

    return wake_count;
}

/**
 * @brief  Signal an event
 *
 * Signals an event.  If EVENT_FLAG_AUTOUNSIGNAL is set in the event
 * object's flags, only one waiting thread is allowed to proceed.  Otherwise,
 * all waiting threads are allowed to proceed until such time as
 * event_unsignal() is called.
 *
 * @param e           Event object
 * @param reschedule  If true, waiting thread(s) are executed immediately,
 *                    and the current thread resumes only after the
 *                    waiting threads have been satisfied. If false,
 *                    waiting threads are placed at the head of the run
 *                    queue.
 * @param wait_result What status event_wait_deadline will return to the
 *                    thread or threads that are woken up.
 *
 * @return  Returns the number of threads that have been unblocked.
 */
int event_signal_etc(event_t* e, bool reschedule, zx_status_t wait_result) {
    Guard<spin_lock_t, IrqSave> guard{ThreadLock::Get()};
    return event_signal_internal(e, reschedule, wait_result);
}

/**
 * @brief  Signal an event
 *
 * Signals an event.  If EVENT_FLAG_AUTOUNSIGNAL is set in the event
 * object's flags, only one waiting thread is allowed to proceed.  Otherwise,
 * all waiting threads are allowed to proceed until such time as
 * event_unsignal() is called.
 *
 * @param e           Event object
 * @param reschedule  If true, waiting thread(s) are executed immediately,
 *                    and the current thread resumes only after the
 *                    waiting threads have been satisfied. If false,
 *                    waiting threads are placed at the head of the run
 *                    queue.
 *
 * @return  Returns the number of threads that have been unblocked.
 */
int event_signal(event_t* e, bool reschedule) {
    Guard<spin_lock_t, IrqSave> guard{ThreadLock::Get()};
    return event_signal_internal(e, reschedule, ZX_OK);
}

/* same as above, but the thread lock must already be held */
int event_signal_thread_locked(event_t* e) {
    DEBUG_ASSERT(arch_ints_disabled());
    DEBUG_ASSERT(spin_lock_held(&thread_lock));

    return event_signal_internal(e, false, ZX_OK);
}

/**
 * @brief  Clear the "signaled" property of an event
 *
 * Used mainly for event objects without the EVENT_FLAG_AUTOUNSIGNAL
 * flag.  Once this function is called, threads that call event_wait()
 * functions will once again need to wait until the event object
 * is signaled.
 *
 * @param e  Event object
 *
 * @return  Returns ZX_OK on success.
 */
zx_status_t event_unsignal(event_t* e) {
    DEBUG_ASSERT(e->magic == EVENT_MAGIC);

    e->signaled = false;

    return ZX_OK;
}
