// 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 "object/dispatcher.h"

#include <inttypes.h>
#include <lib/counters.h>
#include <lib/ktrace.h>

#include <arch/ops.h>
#include <kernel/koid.h>
#include <kernel/mutex.h>
#include <ktl/atomic.h>

// Counts the number of times a dispatcher has been created and destroyed.
KCOUNTER(dispatcher_create_count, "dispatcher.create")
KCOUNTER(dispatcher_destroy_count, "dispatcher.destroy")

namespace {

// Helper class that safely allows deleting Dispatchers without risk of
// blowing up the kernel stack.  It uses one pointer in the Thread
// structure to unwind the recursion.
class SafeDeleter {
 public:
  static void Delete(Dispatcher* kobj) {
    auto recursive_deleter =
        static_cast<SafeDeleter*>(Thread::Current::Get()->recursive_object_deletion_list());
    if (recursive_deleter) {
      // Delete() was called recursively.
      recursive_deleter->pending_.push_front(kobj);
    } else {
      SafeDeleter deleter;
      Thread::Current::Get()->set_recursive_object_deletion_list(&deleter);

      do {
        // This delete call can cause recursive calls to
        // Dispatcher::fbl_recycle() and hence to Delete().
        delete kobj;

        kobj = deleter.pending_.pop_front();
      } while (kobj);

      Thread::Current::Get()->set_recursive_object_deletion_list(nullptr);
    }
  }

 private:
  fbl::SinglyLinkedListCustomTraits<Dispatcher*, Dispatcher::DeleterListTraits> pending_;
};

}  // namespace

Dispatcher::Dispatcher(zx_signals_t signals)
    : koid_(KernelObjectId::Generate()), handle_count_(0u), signals_(signals) {
  kcounter_add(dispatcher_create_count, 1);
}

Dispatcher::~Dispatcher() {
  ktrace(TAG_OBJECT_DELETE, (uint32_t)koid_, 0, 0, 0);
  kcounter_add(dispatcher_destroy_count, 1);
}

// The refcount of this object has reached zero: delete self
// using the SafeDeleter to avoid potential recursion hazards.
// TODO(cpu): Not all object need the SafeDeleter. Only objects
// that can control the lifetime of dispatchers that in turn
// can control the lifetime of others. For example events do
// not fall in this category.
void Dispatcher::fbl_recycle() {
  canary_.Assert();

  SafeDeleter::Delete(this);
}

zx_status_t Dispatcher::AddObserver(SignalObserver* observer, const Handle* handle,
                                    zx_signals_t signals, Dispatcher::TriggerMode trigger_mode) {
  canary_.Assert();
  ZX_DEBUG_ASSERT(observer != nullptr);

  if (!is_waitable()) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  Guard<Mutex> guard{get_lock()};

  if (trigger_mode == Dispatcher::TriggerMode::Level) {
    // If the currently active signals already match the desired signals,
    // just execute the match now.
    if ((signals_ & signals) != 0) {
      observer->OnMatch(signals_);
      return ZX_OK;
    }
  }

  // Otherwise, enqueue this observer.
  observer->handle_ = handle;
  observer->triggering_signals_ = signals;
  observers_.push_front(observer);

  return ZX_OK;
}

bool Dispatcher::RemoveObserver(SignalObserver* observer, zx_signals_t* signals) {
  canary_.Assert();

  ZX_DEBUG_ASSERT(is_waitable());
  ZX_DEBUG_ASSERT(observer != nullptr);

  Guard<Mutex> guard{get_lock()};

  if (signals != nullptr) {
    *signals = signals_;
  }

  if (observer->InContainer()) {
    observers_.erase(*observer);
    return true;
  }

  return false;
}

void Dispatcher::Cancel(const Handle* handle) {
  canary_.Assert();
  ZX_DEBUG_ASSERT(is_waitable());

  Guard<Mutex> guard{get_lock()};

  // Cancel all observers that registered on "handle".
  for (auto it = observers_.begin(); it != observers_.end(); /* nothing */) {
    if (it->handle_ != handle) {
      ++it;
      continue;
    }

    // Remove the element.
    auto to_remove = it;
    ++it;
    observers_.erase(to_remove);
    to_remove->OnCancel(signals_);
  }
}

bool Dispatcher::CancelByKey(const Handle* handle, const void* port, uint64_t key) {
  canary_.Assert();
  ZX_DEBUG_ASSERT(is_waitable());

  Guard<Mutex> guard{get_lock()};

  // Cancel all observers that registered on "handle" that match the given key.
  bool remove_performed = false;
  for (auto it = observers_.begin(); it != observers_.end(); /* nothing */) {
    if (it->handle_ != handle || !it->MatchesKey(port, key)) {
      ++it;
      continue;
    }

    // Remove the element.
    auto to_remove = it;
    ++it;
    observers_.erase(to_remove);
    to_remove->OnCancel(signals_);
    remove_performed = true;
  }

  return remove_performed;
}

void Dispatcher::UpdateState(zx_signals_t clear_mask, zx_signals_t set_mask) {
  canary_.Assert();

  Guard<Mutex> guard{get_lock()};

  UpdateStateLocked(clear_mask, set_mask);
}

void Dispatcher::UpdateStateLocked(zx_signals_t clear_mask, zx_signals_t set_mask) {
  ZX_DEBUG_ASSERT(is_waitable());

  auto previous_signals = signals_;
  signals_ &= ~clear_mask;
  signals_ |= set_mask;

  if (previous_signals == signals_) {
    return;
  }

  // Update signal observers.
  for (auto it = observers_.begin(); it != observers_.end(); /* nothing */) {
    // Ignore observers that don't need to be notified.
    if ((it->triggering_signals_ & signals_) == 0) {
      ++it;
      continue;
    }

    auto to_remove = it;
    ++it;
    observers_.erase(to_remove);
    to_remove->OnMatch(signals_);
  }
}

zx_signals_t Dispatcher::PollSignals() const {
  Guard<Mutex> guard{get_lock()};
  return signals_;
}
