// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/iwlwifi/platform/task-internal.h"

#include <lib/async/time.h>
#include <lib/stdcompat/atomic.h>
#include <zircon/assert.h>

#include <limits>

namespace wlan::iwlwifi {
namespace {

enum TaskState : zx_futex_t {
  kInvalid = 0,
  kIdle = 1,
  kQueued = 2,
  kExecuting = 3,
};

}  // namespace

TaskInternal::TaskInternal(async_dispatcher_t* dispatcher, FuncType func, void* data)
    : async_task_t{}, dispatcher_(dispatcher), func_(func), data_(data), state_(TaskState::kIdle) {
  this->handler = [](async_dispatcher_t* dispatcher, async_task_t* task, zx_status_t status) {
    auto task_internal = static_cast<TaskInternal*>(task);
    cpp20::atomic_ref<zx_futex_t> state_ref(task_internal->state_);
    ZX_DEBUG_ASSERT(state_ref.load() == TaskState::kQueued);

    if (status == ZX_OK) {
      state_ref.store(TaskState::kExecuting, std::memory_order_release);
      (*task_internal->func_)(task_internal->data_);
    }

    state_ref.store(TaskState::kIdle, std::memory_order_release);
    zx_futex_wake(&task_internal->state_, std::numeric_limits<uint32_t>::max());
  };
}

TaskInternal::~TaskInternal() {
  CancelSync();
  ZX_DEBUG_ASSERT(cpp20::atomic_ref<zx_futex_t>(state_).load() == TaskState::kIdle);
}

zx_status_t TaskInternal::Post(zx_duration_t delay) {
  zx_status_t status = ZX_OK;

  // The async_dpsatcher interface does not allow tasks to be multiply posted.
  if ((status = CancelSync()) != ZX_OK) {
    if (status != ZX_ERR_NOT_FOUND) {
      return status;
    }
  }

  zx_futex_t expected = TaskState::kIdle;
  zx_futex_t desired = TaskState::kQueued;
  cpp20::atomic_ref<zx_futex_t> state_ref(state_);
  if (!state_ref.compare_exchange_strong(expected, desired, std::memory_order_acq_rel)) {
    // Post() is being called simultaneously from multiple threads, so we just early-return the
    // calls after the first.
    return ZX_OK;
  }

  // Post the task.
  this->deadline = async_now(dispatcher_) + delay;
  if ((status = async_post_task(dispatcher_, this)) != ZX_OK) {
    state_ref.store(TaskState::kIdle, std::memory_order_release);
    zx_futex_wake(&state_, std::numeric_limits<uint32_t>::max());
    return status;
  }

  return ZX_OK;
}

zx_status_t TaskInternal::Wait() {
  zx_status_t status = ZX_OK;
  cpp20::atomic_ref<zx_futex_t> state_ref(state_);
  zx_futex_t value = state_ref.load(std::memory_order_acquire);
  while (value != TaskState::kIdle) {
    if ((status = zx_futex_wait(&state_, value, ZX_HANDLE_INVALID, ZX_TIME_INFINITE)) != ZX_OK) {
      if (status != ZX_ERR_BAD_STATE) {
        return status;
      }

      // ZX_ERR_BAD_STATE means that `state_` has already changed to be different than `value`,
      // which is not an error condition here.
    }
    value = state_ref.load(std::memory_order_acquire);
  }

  return ZX_OK;
}

zx_status_t TaskInternal::Cancel() {
  zx_status_t status = async_cancel_task(dispatcher_, this);
  if (status != ZX_OK) {
    return status;
  }

  cpp20::atomic_ref<zx_futex_t> state_ref(state_);
  ZX_DEBUG_ASSERT(state_ref.load() == TaskState::kQueued);
  state_ref.store(TaskState::kIdle, std::memory_order_release);
  zx_futex_wake(&state_, std::numeric_limits<uint32_t>::max());

  return ZX_OK;
}

zx_status_t TaskInternal::CancelSync() {
  // Cancel the task.
  zx_status_t status = ZX_OK;
  if ((status = Cancel()) != ZX_OK) {
    return status;
  }

  // Now wait for completion.
  return Wait();
}

}  // namespace wlan::iwlwifi
