// 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/assert.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
