// Copyright 2021 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include "pw_thread/thread.h"

#include "pw_assert/check.h"
#include "pw_preprocessor/compiler.h"
#include "pw_thread/id.h"
#include "pw_thread_threadx/config.h"
#include "pw_thread_threadx/context.h"
#include "pw_thread_threadx/options.h"
#include "tx_event_flags.h"

using pw::thread::threadx::Context;

namespace pw::thread {
namespace {
#if PW_THREAD_JOINING_ENABLED
constexpr ULONG kThreadDoneBit = 1;
#endif  // PW_THREAD_JOINING_ENABLED
}  // namespace

void Context::RunThread(ULONG void_context_ptr) {
  Context& context = *reinterpret_cast<Context*>(void_context_ptr);
  context.entry_(context.arg_);

  // Raise our preemption threshold as a thread only critical section to guard
  // against join() and detach().
  UINT original_preemption_threshold = TX_MAX_PRIORITIES;  // Invalid.
  UINT preemption_success = tx_thread_preemption_change(
      &context.tcb(), 0, &original_preemption_threshold);
  PW_DCHECK_UINT_EQ(TX_SUCCESS,
                    preemption_success,
                    "Failed to enter thread critical section");
  if (context.detached()) {
    // There is no threadsafe way to re-use detached threads, as there's no way
    // to invoke tx_thread_delete() from the running thread! Joining MUST be
    // used for this. However to enable unit test coverage we go ahead and clear
    // this.
    context.set_in_use(false);

#if PW_THREAD_JOINING_ENABLED
    // Just in case someone abused our API, ensure their use of the event group
    // is properly handled by the kernel regardless.
    const UINT event_group_result =
        tx_event_flags_delete(&context.join_event_group());
    PW_DCHECK_UINT_EQ(TX_SUCCESS,
                      event_group_result,
                      "Failed to delete the join event group");
#endif  // PW_THREAD_JOINING_ENABLED

    // Note that we do not have to restore our preemption threshold as this
    // thread is completing execution.

    // WARNING: The thread at this point continues to be registered with the
    // kernel in TX_COMPLETED state, as tx_thread_delete cannot be invoked!
    return;
  }

  // Otherwise the task finished before the thread was detached or joined, defer
  // cleanup to Thread's join() or detach().
  context.set_thread_done();
  UINT unused = 0;
  preemption_success = tx_thread_preemption_change(
      &context.tcb(), original_preemption_threshold, &unused);
  PW_DCHECK_UINT_EQ(TX_SUCCESS,
                    preemption_success,
                    "Failed to leave thread critical section");

#if PW_THREAD_JOINING_ENABLED
  const UINT result =
      tx_event_flags_set(&context.join_event_group(), kThreadDoneBit, TX_OR);
  PW_DCHECK_UINT_EQ(TX_SUCCESS, result, "Failed to set the join event");
#endif  // PW_THREAD_JOINING_ENABLED
  return;
}

void Context::DeleteThread(Context& context) {
  // Stop the other task first.
  UINT thread_result = tx_thread_terminate(&context.tcb());
  PW_CHECK_UINT_EQ(TX_SUCCESS, thread_result, "Failed to terminate the thread");

  // Delete the thread, removing it out of the kernel.
  thread_result = tx_thread_delete(&context.tcb());
  PW_CHECK_UINT_EQ(TX_SUCCESS, thread_result, "Failed to delete the thread");

  // Mark the context as unused for potential later re-use.
  context.set_in_use(false);

#if PW_THREAD_JOINING_ENABLED
  // Just in case someone abused our API, ensure their use of the event group is
  // properly handled by the kernel regardless.
  const UINT event_group_result =
      tx_event_flags_delete(&context.join_event_group());
  PW_DCHECK_UINT_EQ(
      TX_SUCCESS, event_group_result, "Failed to delete the join event group");
#endif  // PW_THREAD_JOINING_ENABLED
}

Thread::Thread(const thread::Options& facade_options,
               ThreadRoutine entry,
               void* arg)
    : native_type_(nullptr) {
  // Cast the generic facade options to the backend specific option of which
  // only one type can exist at compile time.
  auto options = static_cast<const threadx::Options&>(facade_options);
  PW_DCHECK_NOTNULL(options.context(), "The Context is not optional");
  native_type_ = options.context();

  // Can't use a context more than once.
  PW_DCHECK(!native_type_->in_use());

  // Reset the state of the static context in case it was re-used.
  native_type_->set_in_use(false);
  native_type_->set_detached(false);
  native_type_->set_thread_done(false);
#if PW_THREAD_JOINING_ENABLED
  static const char* join_event_group_name = "pw::Thread";
  const UINT event_group_result =
      tx_event_flags_create(&options.context()->join_event_group(),
                            const_cast<char*>(join_event_group_name));
  PW_DCHECK_UINT_EQ(
      TX_SUCCESS, event_group_result, "Failed to create the join event group");
#endif  // PW_THREAD_JOINING_ENABLED

  // Copy over the thread name.
  native_type_->set_name(options.name());

  // In order to support functions which return and joining, a delegate is
  // deep copied into the context with a small wrapping function to actually
  // invoke the task with its arg.
  native_type_->set_thread_routine(entry, arg);

  const UINT thread_result =
      tx_thread_create(&options.context()->tcb(),
                       const_cast<char*>(native_type_->name()),
                       Context::RunThread,
                       reinterpret_cast<ULONG>(native_type_),
                       options.context()->stack().data(),
                       options.context()->stack().size_bytes(),
                       options.priority(),
                       options.preemption_threshold(),
                       options.time_slice_interval(),
                       TX_AUTO_START);
  PW_CHECK_UINT_EQ(TX_SUCCESS, thread_result, "Failed to create the thread");
}

void Thread::detach() {
  PW_CHECK(joinable());

  tx_thread_suspend(&native_type_->tcb());
  native_type_->set_detached();
  const bool thread_done = native_type_->thread_done();
  tx_thread_resume(&native_type_->tcb());

  if (thread_done) {
    // The task finished (hit end of Context::RunThread) before we invoked
    // detach, clean up the thread.
    Context::DeleteThread(*native_type_);
  } else {
    // We're detaching before the task finished, defer cleanup to the task at
    // the end of Context::RunThread.
  }

  // Update to no longer represent a thread of execution.
  native_type_ = nullptr;
}

#if PW_THREAD_JOINING_ENABLED
void Thread::join() {
  PW_CHECK(joinable());
  PW_CHECK(this_thread::get_id() != get_id());

  ULONG actual_flags = 0;
  const UINT result = tx_event_flags_get(&native_type_->join_event_group(),
                                         kThreadDoneBit,
                                         TX_OR_CLEAR,
                                         &actual_flags,
                                         TX_WAIT_FOREVER);
  PW_DCHECK_UINT_EQ(TX_SUCCESS, result, "Failed to get the join event");

  // No need for a critical section here as the thread at this point is
  // waiting to be deleted.
  Context::DeleteThread(*native_type_);

  // Update to no longer represent a thread of execution.
  native_type_ = nullptr;
}
#endif  // PW_THREAD_JOINING_ENABLED

}  // namespace pw::thread
