diff --git a/include/sta/config.hpp b/include/sta/config.hpp index c05ab9f..e759d53 100644 --- a/include/sta/config.hpp +++ b/include/sta/config.hpp @@ -8,6 +8,8 @@ #ifndef STA_CONFIG_HPP #define STA_CONFIG_HPP +#define STA_STM32_SWD_USART_IDX 2 + #include // Doesn't really do too much right now. Has to be added for successful compilation. diff --git a/include/sta/tasty/config.hpp b/include/sta/tasty/config.hpp index 86882ee..9baa6f7 100644 --- a/include/sta/tasty/config.hpp +++ b/include/sta/tasty/config.hpp @@ -2,6 +2,6 @@ #ifndef STA_TASTY_CONFIG_HPP #define STA_TASTY_CONFIG_HPP -#define TASTY_CASE_5 +#define TASTY_CASE_9 #endif // STA_TASTY_CONFIG_HPP diff --git a/run.py b/run.py index 5efa67e..d72bdf8 100644 --- a/run.py +++ b/run.py @@ -22,7 +22,7 @@ path = 'Tasty/src/cases/' for case in os.listdir(path): # Find the number of the test case. - match = re.match('case([0-9])+\.cpp', case) + match = re.match('case([0-9]+)\.cpp', case) number = match.group(1) with open('Tasty/include/sta/tasty/config.hpp', 'w') as f: diff --git a/src/cases/case10.cpp b/src/cases/case10.cpp new file mode 100644 index 0000000..3a60fbe --- /dev/null +++ b/src/cases/case10.cpp @@ -0,0 +1,118 @@ +/* + * case10.cpp + * + * Created on: Feb 7, 2024 + * Author: Dario + */ + +/** + * A sleeping thread is not restarted by the watchdog. Additionally, using blocking() also prevents a restart. + */ +#include +#ifdef TASTY_CASE_10 + +#include +#include +#include +#include + +namespace sta +{ + namespace tasty + { + RtosSignal * signal; + + class ThreadA : public tacos::TacosThread + { + public: + ThreadA() + : tacos::TacosThread{"A", osPriorityNormal} + { + + } + + void pointless_expensive_computation() + { + uint32_t ticks = osKernelGetSysTimerCount(); + uint32_t freq = osKernelGetSysTimerCount(); + uint64_t dummyCounter = 0; + + while (osKernelGetSysTimerCount() <= ticks + 2 * freq) + { + dummyCounter++; + } + } + + void func() override + { + this->sleep(3000); + + signal->notify(); + + // This should notify the watchdog that this thread should not be monitored. + blocking( + pointless_expensive_computation(); + ) + + signal->notify(); + + pointless_expensive_computation(); + + } + }; + + std::shared_ptr thread_A; + + class Observer : public tacos::TacosThread + { + public: + Observer() + : tacos::TacosThread{"Observer", osPriorityNormal} + { + + } + + + + void func() override + { + uint16_t restarts = tacos::Watchdog::instance()->getNumRestarts(); + + // Wait for thread A to finish sleeping. + blocking( + signal->wait(); + ) + + // Thread A shouldn't have been restarted because sleep() sets the thread's status to WAITING. + STA_TASTY_ASSERT(tacos::Watchdog::instance()->getNumRestarts() == restarts); + + blocking( + signal->wait(); + ) + + // Thread A shouldn't have been restarted because the computationally expensive computation was wrapped in blocking() + STA_TASTY_ASSERT(tacos::Watchdog::instance()->getNumRestarts() == restarts); + + this->sleep(2500); + + STA_TASTY_ASSERT(tacos::Watchdog::instance()->getNumRestarts() == restarts + 1); + + STA_TASTY_TERMINATE(); + } + }; + + void onTastyInit() + { + signal = new RtosSignal(2); + + thread_A = tacos::addThread({0}); + tacos::addThread({0, 1}); + } + } // namespace tasty +} + +#endif // TASTY_CASE_10 + + + + diff --git a/src/cases/case11.cpp b/src/cases/case11.cpp new file mode 100644 index 0000000..f8e27a9 --- /dev/null +++ b/src/cases/case11.cpp @@ -0,0 +1,77 @@ +/* + * case11.cpp + * + * Created on: Feb 7, 2024 + * Author: Dario + */ + +/** + * Tests if a thread with IGNORED status is properly ignored. + */ +#include +#ifdef TASTY_CASE_11 + +#include +#include +#include +#include + +namespace sta +{ + namespace tasty + { + class ThreadA : public tacos::TacosThread + { + public: + ThreadA() + : tacos::TacosThread{"A", osPriorityNormal} + { + + } + + void init() override + { + // Tells the watchdog to ignore this thread. + watchdogIgnore(); + } + + void func() override + { + // Thread is stuck in infinite loop + while (true) + { + osThreadYield(); + } + } + }; + + class Observer : public tacos::TacosThread + { + public: + Observer() + : tacos::TacosThread{"Observer", osPriorityNormal} + { + + } + + + void func() override + { + this->sleep(2000); + + // The watchdog shouldn't have restarted thread A. + STA_TASTY_ASSERT(tacos::Watchdog::instance()->getNumRestarts() == 0); + + STA_TASTY_TERMINATE(); + } + }; + + void onTastyInit() + { + tacos::addThread({0}); + tacos::addThread({0, 1}); + } + } // namespace tasty +} + +#endif // TASTY_CASE_11 diff --git a/src/cases/case5.cpp b/src/cases/case5.cpp index 76e3793..1df1372 100644 --- a/src/cases/case5.cpp +++ b/src/cases/case5.cpp @@ -1,5 +1,7 @@ /** - * + * Timed state transitions can be overwritten by timed state transitions with later deadline. + * + * TODO: Implement the correct requirement. */ #include #ifdef TASTY_CASE_5 @@ -13,8 +15,6 @@ namespace sta { class DummyThread : public tacos::TacosThread { - private: - /* data */ public: DummyThread() : tacos::TacosThread{"Dummy", osPriorityNormal} diff --git a/src/cases/case6.cpp b/src/cases/case6.cpp new file mode 100644 index 0000000..744cfb9 --- /dev/null +++ b/src/cases/case6.cpp @@ -0,0 +1,85 @@ +/** + * Tests if killing tasks works correctly and the memory is correctly freed. + */ +#include +#ifdef TASTY_CASE_6 + +#include +#include +#include + +#include +#include + +namespace sta +{ + namespace tasty + { + static uint8_t victim_alive_flag; + + + class Victim : public tacos::TacosThread + { + public: + Victim() + : tacos::TacosThread{"Dummy", osPriorityNormal} + {} + + void func() override + { + victim_alive_flag = 1; + osThreadYield(); + } + }; + + + class ViciousMurderer : public tacos::TacosThread + { + public: + ViciousMurderer(std::shared_ptr victim_ptr) + : tacos::TacosThread{"Dummy", osPriorityNormal}, + victim_ptr_{victim_ptr} + {} + + void func() override + { + // Kill the thread and set it's heartbeat flag to 0. + victim_ptr_->kill(); + victim_alive_flag = 0; + + uint8_t frees = sta::rtos::getNumFrees(); + + // Skip a tick + osThreadYield(); + + // The killed threat shouldn't have set the heartbeat flag. + STA_TASTY_ASSERT(victim_alive_flag == 0); + + // Wait for 100 ticks. + this->sleep(100); + + // After waiting 100 ticks, the flag should still be 0 because the thread doesn't run. + STA_TASTY_ASSERT(victim_alive_flag == 0); + + // Also, there should be two more frees: + STA_TASTY_ASSERT(sta::rtos::getNumFrees() - frees == 2); + + STA_TASTY_TERMINATE(); + } + private: + std::shared_ptr victim_ptr_; + }; + + void onTastyInit() + { + std::shared_ptr victim_ptr = tacos::addThread({0}); + tacos::addThread({0}, victim_ptr); + } + } // namespace tasty +} // namespace sta + +#endif // TASTY_CASE_6/* + + + + diff --git a/src/cases/case7.cpp b/src/cases/case7.cpp new file mode 100644 index 0000000..5f9b70e --- /dev/null +++ b/src/cases/case7.cpp @@ -0,0 +1,86 @@ +/* + * case7.cpp + * + * Created on: Jan 24, 2024 + * Author: Dario + */ + +/** + * A thread gets stuck in an infinite loop and the watchdog restarts it. + */ +#include +#ifdef TASTY_CASE_7 + +#include +#include +#include + +namespace sta +{ + namespace tasty + { + static uint8_t alive_flag = 0; + + class Dummy : public tacos::TacosThread + { + public: + Dummy() + : tacos::TacosThread{"Dummy", osPriorityNormal} + { + + } + + void init() override + { + alive_flag = 1; + } + + void func() override + { + this->sleep(100); + + // Thread is stuck in infinite loop + while (true) + { + osThreadYield(); + } + } + }; + + class Observer : public tacos::TacosThread + { + public: + Observer() + : tacos::TacosThread{"Observer", osPriorityNormal} + { + + } + + void func() override + { + this->sleep(10); + STA_TASTY_ASSERT(alive_flag == 1); + + this->sleep(110); + alive_flag = 0; + + // After at most 1000 ticks, the watchdog should have revived the thread. + this->sleep(2000); + STA_TASTY_ASSERT(alive_flag == 1); + STA_TASTY_ASSERT(tacos::Watchdog::instance()->getNumRestarts() == 1); + + STA_TASTY_TERMINATE(); + } + }; + + void onTastyInit() + { + tacos::addThread({0}); + tacos::addThread({0}); + } + } // namespace tasty +} + +#endif // TASTY_CASE_7 + + diff --git a/src/cases/case8.cpp b/src/cases/case8.cpp new file mode 100644 index 0000000..7c7e643 --- /dev/null +++ b/src/cases/case8.cpp @@ -0,0 +1,97 @@ +/* + * case8.cpp + * + * Created on: Jan 24, 2024 + * Author: Dario + */ + +/** + * Two threads get stuck in a deadlock and are restarted. + */ +#include +#ifdef TASTY_CASE_8 + +#include +#include +#include +#include + +namespace sta +{ + namespace tasty + { + static RtosMutex * mutexA; + static RtosMutex * mutexB; + + class ThreadA : public tacos::TacosThread + { + public: + ThreadA() + : tacos::TacosThread{"A", osPriorityNormal} + { + + } + + void func() override + { + mutexA->acquire(); + + this->sleep(10); + + mutexB->acquire(); + } + }; + + class ThreadB : public tacos::TacosThread + { + public: + ThreadB() + : tacos::TacosThread{"B", osPriorityNormal} + { + + } + + void func() override + { + mutexB->acquire(); + + this->sleep(10); + + mutexA->acquire(); + } + }; + + class Observer : public tacos::TacosThread + { + public: + Observer() + : tacos::TacosThread{"Observer", osPriorityNormal} + { + + } + + void func() override + { + this->sleep(2000); + + STA_TASTY_ASSERT(tacos::Watchdog::instance()->getNumRestarts() == 2); + + STA_TASTY_TERMINATE(); + } + }; + + void onTastyInit() + { + mutexA = new RtosMutex("MutA"); + mutexB = new RtosMutex("MutB"); + + tacos::addThread({0}); + tacos::addThread({0}); + tacos::addThread({0}); + } + } // namespace tasty +} + +#endif // TASTY_CASE_8 + + diff --git a/src/cases/case9.cpp b/src/cases/case9.cpp new file mode 100644 index 0000000..6c23e87 --- /dev/null +++ b/src/cases/case9.cpp @@ -0,0 +1,114 @@ +/* + * case8.cpp + * + * Created on: Jan 24, 2024 + * Author: Dario + */ + +/** + * Tests if threads are properly terminated and started because of state transitions. The thread status is updated accordingly and no memory leaks occur. + */ +#include +#ifdef TASTY_CASE_9 + +#include +#include +#include + +namespace sta +{ + namespace tasty + { + class ThreadA : public tacos::TacosThread + { + public: + ThreadA() + : tacos::TacosThread{"A", osPriorityNormal} + { + + } + + void func() override + { + osThreadYield(); + } + }; + + class ThreadB : public tacos::TacosThread + { + public: + ThreadB() + : tacos::TacosThread{"B", osPriorityNormal} + { + + } + + void func() override + { + osThreadYield(); + } + }; + + + std::shared_ptr thread_A; + std::shared_ptr thread_B; + + + class Observer : public tacos::TacosThread + { + public: + Observer() + : tacos::TacosThread{"Observer", osPriorityNormal} + { + + } + + void func() override + { + size_t mallocs = sta::rtos::getNumAllocs(); + + STA_TASTY_ASSERT(thread_A->isRunning()); + STA_TASTY_ASSERT(!thread_B->isRunning()); + STA_TASTY_ASSERT(thread_B->getStatus() == tacos::ThreadStatus::STOPPED); + + this->sleep(20); + + tacos::setState(0, 1); + + this->sleep(5); + + STA_TASTY_ASSERT(!thread_A->isRunning()); + STA_TASTY_ASSERT(thread_B->isRunning()); + STA_TASTY_ASSERT(thread_A->getStatus() == tacos::ThreadStatus::STOPPED); + STA_TASTY_ASSERT(sta::rtos::getNumAllocs() == mallocs + 2); + + tacos::setState(1, 0); + + this->sleep(5); + + STA_TASTY_ASSERT(thread_A->isRunning()); + STA_TASTY_ASSERT(!thread_B->isRunning()); + STA_TASTY_ASSERT(thread_B->getStatus() == tacos::ThreadStatus::STOPPED); + STA_TASTY_ASSERT(sta::rtos::getNumAllocs() == mallocs + 2); + + tacos::setState(0, 1); + + STA_TASTY_ASSERT(!thread_A->isRunning()); + STA_TASTY_ASSERT(thread_B->isRunning()); + STA_TASTY_ASSERT(thread_A->getStatus() == tacos::ThreadStatus::STOPPED); + STA_TASTY_ASSERT(sta::rtos::getNumAllocs() == mallocs + 2); + + STA_TASTY_TERMINATE(); + } + }; + + void onTastyInit() + { + thread_A = tacos::addThread({0}); + thread_B = tacos::addThread({1}); + tacos::addThread({0, 1}); + } + } // namespace tasty +} + +#endif // TASTY_CASE_9 diff --git a/src/tasks/supervisor.cpp b/src/tasks/supervisor.cpp index da6e6be..6ac0b4d 100644 --- a/src/tasks/supervisor.cpp +++ b/src/tasks/supervisor.cpp @@ -18,9 +18,9 @@ namespace sta { for (TastyCheck check : checks_) { - blocking( + /*blocking( check(); - ); + );*/ } } } // namespace tasty diff --git a/src/tasks/toggle.cpp b/src/tasks/toggle.cpp index 6ac2863..1e9d835 100644 --- a/src/tasks/toggle.cpp +++ b/src/tasks/toggle.cpp @@ -29,6 +29,7 @@ namespace sta void ToggleThread::func() { + /** blocking( this->sleep(ticks_); ) @@ -37,6 +38,7 @@ namespace sta uint16_t next = 1 - state; sta::tacos::setState(state, next, lockout_); + */ } } // namespace tasty } // namespace sta diff --git a/src/utils.cpp b/src/utils.cpp index 6335b34..01010af 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -16,6 +16,8 @@ namespace sta void test_terminate() { STA_DEBUG_PRINTLN("[T]"); + + while (true) {} } } // namespace tasty } // namespace sta