blob: 0cf222b56243746a51ade26067d3391da09cb6fa [file] [log] [blame]
Ewout van Bekkumf4da4892021-03-05 15:05:37 -08001// Copyright 2021 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15#include "pw_thread/test_threads.h"
16
17#include <chrono>
18
19#include "pw_assert/check.h"
20#include "pw_chrono/system_clock.h"
21#include "pw_log/log.h"
22#include "pw_thread/sleep.h"
23#include "pw_thread_threadx/context.h"
24#include "pw_thread_threadx/options.h"
25
26namespace pw::thread::test {
27namespace {
28
29std::array<threadx::ContextWithStack<>, 2> thread_contexts;
30
31} // namespace
32
33const Options& TestOptionsThread0() {
34 static constexpr threadx::Options thread_0_options =
35 threadx::Options()
36 .set_name("pw::TestThread0")
37 .set_context(thread_contexts[0]);
38 return thread_0_options;
39}
40
41const Options& TestOptionsThread1() {
42 static constexpr threadx::Options thread_1_options =
43 threadx::Options()
44 .set_name("pw::TestThread1")
45 .set_context(thread_contexts[1]);
46 return thread_1_options;
47}
48
49void WaitUntilDetachedThreadsCleanedUp() {
50 // ThreadX does not permit the running thread to delete itself, which means
51 // we have to do this to re-use a TCB as otherwise we will be leaking stale
52 // references in the kernel.
53 for (auto& context : thread_contexts) {
54 if (context.tcb().tx_thread_id != TX_THREAD_ID) {
55 // The TCB was either not used or was already deleted. Note that
56 // tx_thread_terminate does NOT clear this state by design.
57 continue;
58 }
59
60 // If the thread was created but has not been deleted, it means that the
61 // thread was detached before it finished. Wait until it is completed.
62 while (context.tcb().tx_thread_state != TX_COMPLETED) {
63 pw::this_thread::sleep_for(
64 chrono::SystemClock::for_at_least(std::chrono::milliseconds(1)));
65 }
66
67 const UINT result = tx_thread_delete(&context.tcb());
68 PW_CHECK_UINT_EQ(TX_SUCCESS, result, "Failed to delete thread");
69 }
70}
71
72} // namespace pw::thread::test