// 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::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 "kernel/event.h"

#include <assert.h>
#include <debug.h>
#include <lib/fit/defer.h>
#include <lib/kconcurrent/chainlock_transaction.h>
#include <lib/zircon-internal/macros.h>
#include <sys/types.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <kernel/auto_preempt_disabler.h>
#include <kernel/scheduler.h>
#include <kernel/spinlock.h>
#include <kernel/thread.h>

/**
 * @brief  Destruct an Event object.
 *
 * Event's resources are freed and it may no longer be used.
 * Will panic if there are any threads still waiting.
 */
Event::~Event() {
  DEBUG_ASSERT(magic_ == kMagic);

  magic_ = 0;
  result_.store(kNotSignaled, ktl::memory_order_relaxed);
  flags_ = Flags(0);
}

zx_status_t Event::WaitWorker(const Deadline& deadline, Interruptible interruptible,
                              uint signal_mask) {
  DEBUG_ASSERT(magic_ == kMagic);
  DEBUG_ASSERT(!arch_blocking_disallowed());

  // Start by grabbing our wait queue's lock.  The state of the event is only
  // allowed to change from un-signaled to signaled when we are holding this
  // lock, so by holding it here, we can check the state of the signal and fast
  // abort if we need to, or descend into the wait queue and be certain to fully
  // block in the queue before releasing the lock.
  ChainLockTransactionIrqSave clt{CLT_TAG("Event::WaitWorker")};
  for (;; clt.Relax()) {
    wait_.get_lock().AcquireUnconditionally();

    zx_status_t ret = result_.load(ktl::memory_order_relaxed);
    if (ret == kNotSignaled) {
      // Looks like we are not currently signaled.  Now try to obtain the
      // current thread's lock so we can block it.
      Thread* current_thread = Thread::Current::Get();
      if (current_thread->get_lock().Acquire() == ChainLock::LockResult::kBackoff) {
        wait_.get_lock().Release();
        continue;
      }
      current_thread->get_lock().AssertAcquired();
      clt.Finalize();

      // We got the lock, go ahead and block the thread.  This will
      // automatically release the queue's lock after the thread has been added
      // to the queue and is committed to blocking.  We will need release the
      // thread's lock ourselves after it wakes up, as it will be obtained as it
      // becomes scheduled.
      ret = wait_.BlockEtc(current_thread, deadline, signal_mask, ResourceOwnership::Normal,
                           interruptible);
      current_thread->get_lock().Release();
      return ret;
    }

    /* signaled, we're going to fall through */
    if (flags_ & Event::AUTOUNSIGNAL) {
      /* autounsignal flag lets one thread fall through before unsignaling */
      result_.store(kNotSignaled, ktl::memory_order_relaxed);
    }

    wait_.get_lock().Release();
    return ret;
  }
}

/**
 * @brief  Signal an event
 *
 * Signals an event.  If Event::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 wait_result What status a wait call will return to the
 *                    thread or threads that are woken up.
 */
void Event::Signal(zx_status_t wait_result) {
  DEBUG_ASSERT(magic_ == kMagic);
  DEBUG_ASSERT(wait_result != kNotSignaled);

  // In order to transition from not-signaled to signaled, we must be
  // holding our wait queue's lock.
  ChainLockTransactionIrqSave clt{CLT_TAG("Event::Signal")};
  auto finalize_clt = fit::defer([&clt]() TA_NO_THREAD_SAFETY_ANALYSIS { clt.Finalize(); });
  for (;; clt.Relax()) {
    UnconditionalChainLockGuard guard{wait_.get_lock()};

    // If we are already signaled, we are finished.  We should be able to assert
    // that there are no waiters right now.
    if (result_.load(ktl::memory_order_relaxed) != kNotSignaled) {
      DEBUG_ASSERT(wait_.Count() == 0);
      break;
    }

    // If there are no threads waiting in the event, we can just mark it
    // signaled and get out.
    if (wait_.Count() == 0) {
      result_.store(wait_result, ktl::memory_order_relaxed);
      break;
    }

    // Try to lock with one or all of the threads for wake.
    ktl::optional<Thread::UnblockList> maybe_unblock_list =
        (flags_ & Event::AUTOUNSIGNAL) ? WaitQueueLockOps::LockForWakeOne(wait_, wait_result)
                                       : WaitQueueLockOps::LockForWakeAll(wait_, wait_result);

    // If we failed to lock, we need to drop the queue lock, then try again.
    if (!maybe_unblock_list.has_value()) {
      continue;
    }

    // We have all of our locks now, time to proceed with the wake operations (if any)
    finalize_clt.call();

    // Success.  If we not an auto-reset event, or we failed to find anyone to
    // wake, make sure to set the event to the signaled state.
    const bool has_threads_to_wake = !maybe_unblock_list.value().is_empty();
    if (!(flags_ & Event::AUTOUNSIGNAL) || !has_threads_to_wake) {
      result_.store(wait_result, ktl::memory_order_relaxed);
    }

    // We've finished our bookkeeping.  Go ahead and drop the queue lock, then
    // unblock all of the threads.
    guard.Release();
    if (has_threads_to_wake) {
      Scheduler::Unblock(ktl::move(maybe_unblock_list).value());
    }
    break;
  }
}

/**
 * @brief  Clear the "signaled" property of an event
 *
 * Used mainly for event objects without the Event::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() {
  DEBUG_ASSERT(magic_ == kMagic);
  result_.store(kNotSignaled, ktl::memory_order_relaxed);
  return ZX_OK;
}
