// 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(true);
  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
