1
0
mirror of https://github.com/azure-rtos/threadx synced 2025-02-06 08:08:27 +08:00
threadx/test/tx/regression/testcontrol.c
Xiuwen Cai 6b8ece0ff2
Add random number stack filling option. (#257)
Co-authored-by: TiejunZhou <50469179+TiejunMS@users.noreply.github.com>
2023-05-12 10:13:42 +08:00

1424 lines
58 KiB
C

/* This is the test control routine of the ThreadX kernel. All tests are dispatched from this routine. */
#include "tx_api.h"
#include <stdio.h>
#include "tx_initialize.h"
#include "tx_timer.h"
#include "tx_thread.h"
#include "tx_semaphore.h"
#include "tx_queue.h"
#include "tx_mutex.h"
#include "tx_block_pool.h"
#include "tx_byte_pool.h"
#include "tx_event_flags.h"
/* Version check. */
#ifndef EL_PRODUCT_THREADX
#error "EL_PRODUCT_THREADX is not defined."
#endif
#if defined(EXPECTED_MAJOR_VERSION) && ( !defined(THREADX_MAJOR_VERSION) || THREADX_MAJOR_VERSION != EXPECTED_MAJOR_VERSION)
#error "THREADX_MAJOR_VERSION"
#endif /* Check THREADX_MAJOR_VERSION */
#if defined(EXPECTED_MINOR_VERSION) && ( !defined(THREADX_MINOR_VERSION) || THREADX_MINOR_VERSION != EXPECTED_MINOR_VERSION)
#error "THREADX_MINOR_VERSION"
#endif /* Check THREADX_MINOR_VERSION */
#define TEST_STACK_SIZE 6144
/* Define the test control ThreadX objects... */
TX_THREAD test_control_thread;
TX_THREAD test_thread;
TX_THREAD test_thread1;
TX_THREAD test_thread2;
TX_THREAD test_thread3;
ULONG test_thread3_stack[256];
TX_QUEUE test_queue;
ULONG test_thread2_stack[256];
TX_TIMER test_timer;
TX_MUTEX init_mutex;
TX_MUTEX init_mutex_inherit;
TX_MUTEX cleanup_mutex;
TX_EVENT_FLAGS_GROUP cleanup_event_flags;
TX_BLOCK_POOL cleanup_block_pool;
TX_BYTE_POOL cleanup_byte_pool;
TX_QUEUE cleanup_queue;
TX_SEMAPHORE cleanup_semaphore;
TX_SEMAPHORE init_semaphore;
ULONG init_queue_area[20];
TX_QUEUE init_queue;
TX_BYTE_POOL init_byte_pool;
ULONG init_byte_pool_area[50];
TX_BLOCK_POOL init_block_pool;
ULONG init_block_pool_area[50];
TX_EVENT_FLAGS_GROUP init_event_flags;
TX_TIMER init_timer;
TX_THREAD init_test_thread;
TX_THREAD second_test_thread;
#ifndef TX_TIMER_PROCESS_IN_ISR
TEST_FLAG threadx_delete_timer_thread;
#endif
TX_TIMER_INTERNAL **_timer_list_start_backup;
TEST_FLAG test_stack_analyze_flag;
TEST_FLAG test_initialize_flag;
TX_BLOCK_POOL fake_block_pool;
TX_BYTE_POOL fake_byte_pool;
TX_EVENT_FLAGS_GROUP fake_event_flags;
TX_MUTEX fake_mutex;
TX_QUEUE fake_queue;
TX_SEMAPHORE fake_semaphore;
TEST_FLAG test_forced_mutex_timeout;
TEST_FLAG threadx_mutex_suspension_put_test;
TEST_FLAG threadx_mutex_suspension_priority_test;
TEST_FLAG threadx_byte_allocate_loop_test;
TEST_FLAG threadx_byte_release_loop_test;
/* Define the test control global variables. */
ULONG test_control_return_status;
ULONG test_control_successful_tests;
ULONG test_control_failed_tests;
ULONG test_control_system_errors;
UINT test_mutex_from_init;
UINT test_semaphore_from_init;
UINT test_queue_from_init;
UINT test_event_flags_from_init;
UINT test_byte_pool_create_init;
UINT test_block_pool_create_init;
UINT test_timer_create_init;
/* Remember the start of free memory. */
UCHAR *test_free_memory_ptr;
/* Define the function pointer for ISR dispatch. */
VOID (*test_isr_dispatch)(void);
UCHAR test_control_memory[0x60000];
UCHAR tests_memory[0x60000];
/* Define the external reference for the preempt disable flag. */
extern volatile UINT _tx_thread_preempt_disable;
extern volatile ULONG _tx_thread_system_state;
/* Define test entry pointer type. */
typedef struct TEST_ENTRY_STRUCT
{
VOID (*test_entry)(void *);
} TEST_ENTRY;
/* Define the prototypes for the test entry points. */
void threadx_block_memory_basic_application_define(void *);
void threadx_block_memory_error_detection_application_define(void *);
void threadx_block_memory_suspension_application_define(void *);
void threadx_block_memory_suspension_timeout_application_define(void *);
void threadx_block_memory_thread_terminate_application_define(void *);
void threadx_block_memory_prioritize_application_define(void *);
void threadx_block_memory_information_application_define(void *);
void threadx_byte_memory_basic_application_define(void *);
void threadx_byte_memory_thread_contention_application_define(void *);
void threadx_byte_memory_suspension_application_define(void *);
void threadx_byte_memory_suspension_timeout_application_define(void *);
void threadx_byte_memory_thread_terminate_application_define(void *);
void threadx_byte_memory_prioritize_application_define(void *);
void threadx_byte_memory_information_application_define(void *);
void threadx_event_flag_basic_application_define(void *);
void threadx_event_flag_suspension_application_define(void *);
void threadx_event_flag_suspension_consume_application_define(void *);
void threadx_event_flag_suspension_different_bits_application_define(void *);
void threadx_event_flag_suspension_different_bits_consume_application_define(void *);
void threadx_event_flag_suspension_timeout_application_define(void *);
void threadx_event_flag_thread_terminate_application_define(void *);
void threadx_event_flag_single_thread_terminate_application_define(void *);
void threadx_event_flag_isr_set_clear_application_define(void *);
void threadx_event_flag_isr_wait_abort_application_define(void *);
void threadx_event_flag_information_application_define(void *);
void threadx_interrupt_control_application_define(void *);
void threadx_mutex_basic_application_define(void *);
void threadx_mutex_delete_application_define(void *);
void threadx_mutex_preemption_application_define(void *);
void threadx_mutext_no_preemption_application_define(void *);
void threadx_mutex_suspension_timeout_application_define(void *);
void threadx_mutex_thread_terminate_application_define(void *);
void threadx_mutex_priority_inheritance_application_define(void *);
void threadx_mutex_nested_priority_inheritance_application_define(void *);
void threadx_mutex_prioritize_application_define(void *);
void threadx_mutex_information_application_define(void *);
void threadx_queue_basic_application_define(void *);
void threadx_queue_basic_two_word_application_define(void *);
void threadx_queue_basic_four_word_application_define(void *);
void threadx_queue_basic_eight_word_application_define(void *);
void threadx_queue_basic_sixteen_word_application_define(void *);
void threadx_queue_empty_suspension_application_define(void *);
void threadx_queue_full_suspension_application_define(void *);
void threadx_queue_suspension_timeout_application_define(void *);
void threadx_queue_thread_terminate_application_define(void *);
void threadx_queue_flush_application_define(void *);
void threadx_queue_flush_no_suspension_application_define(void *);
void threadx_queue_front_send_application_define(void *);
void threadx_queue_prioritize_application_define(void *);
void threadx_queue_information_application_define(void *);
void threadx_semaphore_basic_application_define(void *);
void threadx_semaphore_delete_application_define(void *);
void threadx_semaphore_preemption_application_define(void *);
void threadx_semaphore_non_preemption_application_define(void *);
void threadx_semaphore_timeout_application_define(void *);
void threadx_semaphore_thread_terminate_application_define(void *);
void threadx_semaphore_prioritize_application_define(void *);
void threadx_semaphore_ceiling_put_application_define(void *);
void threadx_semaphore_information_application_define(void *);
void threadx_thread_basic_execution_application_define(void *);
void threadx_thread_completed_application_define(void *);
void threadx_thread_relinquish_application_define(void *);
void threadx_thread_simple_supsend_application_define(void *);
void threadx_thread_multiple_suspension_application_define(void *);
void threadx_thread_multiple_non_current_suspension_application_define(void *);
void threadx_thread_multi_level_preemption_threshold_application_define(void *);
void threadx_thread_preemptable_suspension_application_define(void *);
void threadx_thread_basic_time_slice_application_define(void *);
void threadx_thread_multiple_time_slice_application_define(void *);
void threadx_thread_simple_sleep_application_define(void *);
void threadx_thread_simple_sleep_non_clear_application_define(void *);
void threadx_thread_sleep_for_100ticks_application_define(void *);
void threadx_thread_multiple_sleep_application_define(void *);
void threadx_thread_terminate_delete_application_define(void *);
void threadx_thread_preemption_change_application_define(void *);
void threadx_thread_priority_change_application_define(void *);
void threadx_thread_time_slice_change_application_define(void *);
void threadx_thread_sleep_terminate_application_define(void *);
void threadx_thread_delayed_suspension_application_define(void *);
void threadx_thread_wait_abort_application_define(void *);
void threadx_thread_wait_abort_and_isr_application_define(void *);
void threadx_thread_create_preemption_threshold_application_define(void *);
void threadx_thread_information_application_define(void *);
void threadx_thread_reset_application_define(void *);
void threadx_thread_stack_checking_application_define(void *);
void threadx_time_get_set_application_define(void *);
void threadx_timer_simple_application_define(void *);
void threadx_timer_activate_deactivate_application_define(void *);
void threadx_timer_deactivate_accuracy_application_define(void *);
void threadx_timer_large_timer_accuracy_application_define(void *);
void threadx_timer_multiple_application_define(void *);
void threadx_timer_multiple_accuracy_application_define(void *);
void threadx_timer_information_application_define(void *);
void threadx_trace_basic_application_define(void *);
void test_application_define(void *first_unused_memory);
/* Define the array of test entry points. */
TEST_ENTRY test_control_tests[] =
{
#if CTEST
test_application_define,
#else
threadx_block_memory_basic_application_define,
threadx_block_memory_error_detection_application_define,
threadx_block_memory_prioritize_application_define,
threadx_block_memory_suspension_application_define,
threadx_block_memory_suspension_timeout_application_define,
threadx_block_memory_thread_terminate_application_define,
threadx_block_memory_information_application_define,
threadx_byte_memory_basic_application_define,
threadx_byte_memory_suspension_application_define,
threadx_byte_memory_suspension_timeout_application_define,
threadx_byte_memory_thread_terminate_application_define,
threadx_byte_memory_prioritize_application_define,
threadx_byte_memory_thread_contention_application_define,
threadx_byte_memory_information_application_define,
threadx_event_flag_basic_application_define,
threadx_event_flag_suspension_application_define,
threadx_event_flag_suspension_consume_application_define,
threadx_event_flag_suspension_different_bits_application_define,
threadx_event_flag_suspension_different_bits_consume_application_define,
threadx_event_flag_suspension_timeout_application_define,
threadx_event_flag_thread_terminate_application_define,
threadx_event_flag_single_thread_terminate_application_define,
threadx_event_flag_isr_set_clear_application_define,
threadx_event_flag_isr_wait_abort_application_define,
threadx_event_flag_information_application_define,
threadx_interrupt_control_application_define,
threadx_mutex_basic_application_define,
threadx_mutex_delete_application_define,
threadx_mutex_preemption_application_define,
threadx_mutext_no_preemption_application_define,
threadx_mutex_suspension_timeout_application_define,
threadx_mutex_thread_terminate_application_define,
threadx_mutex_priority_inheritance_application_define,
threadx_mutex_prioritize_application_define,
threadx_mutex_nested_priority_inheritance_application_define,
threadx_mutex_information_application_define,
threadx_queue_basic_application_define,
threadx_queue_basic_two_word_application_define,
threadx_queue_basic_four_word_application_define,
threadx_queue_basic_eight_word_application_define,
threadx_queue_basic_sixteen_word_application_define,
threadx_queue_empty_suspension_application_define,
threadx_queue_full_suspension_application_define,
threadx_queue_suspension_timeout_application_define,
threadx_queue_thread_terminate_application_define,
threadx_queue_flush_application_define,
threadx_queue_flush_no_suspension_application_define,
threadx_queue_front_send_application_define,
threadx_queue_prioritize_application_define,
threadx_queue_information_application_define,
threadx_semaphore_basic_application_define,
threadx_semaphore_delete_application_define,
threadx_semaphore_preemption_application_define,
threadx_semaphore_non_preemption_application_define,
threadx_semaphore_timeout_application_define,
threadx_semaphore_thread_terminate_application_define,
threadx_semaphore_prioritize_application_define,
threadx_semaphore_ceiling_put_application_define,
threadx_semaphore_information_application_define,
threadx_thread_basic_execution_application_define,
threadx_thread_completed_application_define,
threadx_thread_relinquish_application_define,
threadx_thread_simple_supsend_application_define,
threadx_thread_multiple_suspension_application_define,
threadx_thread_multiple_non_current_suspension_application_define,
threadx_thread_multi_level_preemption_threshold_application_define,
threadx_thread_preemptable_suspension_application_define,
threadx_thread_basic_time_slice_application_define,
threadx_thread_multiple_time_slice_application_define,
threadx_thread_simple_sleep_application_define,
threadx_thread_simple_sleep_non_clear_application_define,
threadx_thread_sleep_for_100ticks_application_define,
threadx_thread_multiple_sleep_application_define,
threadx_thread_terminate_delete_application_define,
threadx_thread_priority_change_application_define,
threadx_thread_time_slice_change_application_define,
threadx_thread_sleep_terminate_application_define,
threadx_thread_delayed_suspension_application_define,
threadx_thread_wait_abort_application_define,
threadx_thread_wait_abort_and_isr_application_define,
threadx_thread_create_preemption_threshold_application_define,
threadx_thread_preemption_change_application_define,
threadx_thread_information_application_define,
threadx_thread_reset_application_define,
threadx_thread_stack_checking_application_define,
threadx_time_get_set_application_define,
threadx_timer_simple_application_define,
threadx_timer_activate_deactivate_application_define,
threadx_timer_deactivate_accuracy_application_define,
threadx_timer_large_timer_accuracy_application_define,
threadx_timer_multiple_application_define,
threadx_timer_multiple_accuracy_application_define,
threadx_timer_information_application_define,
threadx_trace_basic_application_define,
#endif
TX_NULL,
};
/* Define thread prototypes. */
void test_control_thread_entry(ULONG thread_input);
void test_thread_entry(ULONG thread_input);
void test_thread_entry1(ULONG thread_input);
void test_control_return(UINT status);
void test_control_cleanup(void);
void test_exit_notify(TX_THREAD *thread_ptr, UINT type);
/* Define necessary exernal references. */
#ifdef __ghs
extern TX_MUTEX __ghLockMutex;
#endif
extern TX_TIMER *_tx_timer_created_ptr;
extern ULONG _tx_timer_created_count;
#ifndef TX_TIMER_PROCESS_IN_ISR
extern TX_THREAD _tx_timer_thread;
#endif
extern TX_THREAD *_tx_thread_created_ptr;
extern ULONG _tx_thread_created_count;
extern TX_SEMAPHORE *_tx_semaphore_created_ptr;
extern ULONG _tx_semaphore_created_count;
extern TX_QUEUE *_tx_queue_created_ptr;
extern ULONG _tx_queue_created_count;
extern TX_MUTEX *_tx_mutex_created_ptr;
extern ULONG _tx_mutex_created_count;
extern TX_EVENT_FLAGS_GROUP *_tx_event_flags_created_ptr;
extern ULONG _tx_event_flags_created_count;
extern TX_BYTE_POOL *_tx_byte_pool_created_ptr;
extern ULONG _tx_byte_pool_created_count;
extern TX_BLOCK_POOL *_tx_block_pool_created_ptr;
extern ULONG _tx_block_pool_created_count;
#ifdef EXTERNAL_EXIT
void external_exit(UINT code);
#endif
/* Define the interrupt processing dispatcher. The individual tests will set this up when they desire
asynchrouns processing for testing purposes. */
void test_interrupt_dispatch(void)
{
#ifndef TX_DISABLE_ERROR_CHECKING
/* Test calling tx_thread_relinquish from ISR to see if the error checking throws it out. */
tx_thread_relinquish();
#endif
/* Check for something to run... */
if (test_isr_dispatch)
{
(test_isr_dispatch)();
}
}
/* Define init timer entry. */
static void init_timer_entry(ULONG timer_input)
{
}
#ifndef TX_TIMER_PROCESS_IN_ISR
/* Define the deletion of the system timer thread. */
void delete_timer_thread(void)
{
_tx_thread_terminate(&_tx_timer_thread);
_tx_thread_delete(&_tx_timer_thread);
}
#endif
/* Define main entry point. */
#ifndef EXTERNAL_MAIN
void main()
{
#ifndef TX_MISRA_ENABLE
#ifndef TX_MANUAL_TEST
/* Test the pre-initialize path through _tx_initialize_kernel_enter. */
_tx_thread_system_state = TX_INITIALIZE_ALMOST_DONE;
test_initialize_flag = 1;
/* Call the internal kernel enter function to exercise two paths. */
_tx_initialize_kernel_enter();
_tx_thread_system_state = 0;
#ifndef TX_TIMER_PROCESS_IN_ISR
threadx_delete_timer_thread = 1;
#endif
#endif
#endif
/* Enter the ThreadX kernel. */
tx_kernel_enter();
}
#endif
/* Define what the initial system looks like. */
void tx_application_define(void *first_unused_memory)
{
UCHAR *pointer;
VOID (*temp_mutex_release)(TX_THREAD *thread_ptr);
TX_THREAD *temp_thread;
UINT old_preemption;
UINT status;
ULONG flags;
ULONG temp;
UINT i, j;
#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING)
TX_THREAD *thread_ptr;
#endif
/* Initialize the test error/success counters. */
test_control_successful_tests = 0;
test_control_failed_tests = 0;
test_control_system_errors = 0;
/* Setup a pointer to the first unused memory. */
pointer = (UCHAR *) &test_control_memory[0]; //first_unused_memory;
/* Create the test control thread. */
tx_thread_create(&test_control_thread, "test control thread", test_control_thread_entry, 0,
pointer, TEST_STACK_SIZE,
17, 15, TX_NO_TIME_SLICE, TX_AUTO_START);
pointer = pointer + TEST_STACK_SIZE;
/* Create the test thread. */
tx_thread_create(&test_thread, "test thread", test_thread_entry, 0,
pointer, TEST_STACK_SIZE,
15, 15, TX_NO_TIME_SLICE, TX_AUTO_START);
pointer = pointer + TEST_STACK_SIZE;
/* Create the second test thread. */
tx_thread_create(&test_thread1, "test thread 1", test_thread_entry1, 0,
pointer, TEST_STACK_SIZE,
15, 15, TX_NO_TIME_SLICE, TX_DONT_START);
pointer = pointer + TEST_STACK_SIZE;
/* Suspend the test thread temporarily. */
tx_thread_suspend(&test_thread);
/* Resume the test thread again to exercise the resume code fully. */
tx_thread_resume(&test_thread);
/* Timer change just to exercise the code... an error from initialization! */
test_timer.tx_timer_id = TX_TIMER_ID;
tx_timer_change(&test_timer, 1, 1);
/* Test mutex created and used in initialization. */
test_mutex_from_init = tx_mutex_create(&init_mutex, "init mutex", TX_INHERIT);
test_mutex_from_init += tx_mutex_get(&init_mutex, TX_NO_WAIT);
test_mutex_from_init += tx_mutex_get(&init_mutex, TX_NO_WAIT);
test_mutex_from_init += tx_mutex_put(&init_mutex);
test_mutex_from_init += tx_mutex_put(&init_mutex);
test_mutex_from_init = tx_mutex_create(&init_mutex_inherit, "init mutex", TX_INHERIT);
test_mutex_from_init += tx_mutex_get(&init_mutex_inherit, TX_NO_WAIT);
test_mutex_from_init += tx_mutex_get(&init_mutex_inherit, TX_NO_WAIT);
test_mutex_from_init += tx_mutex_put(&init_mutex_inherit);
test_mutex_from_init += tx_mutex_put(&init_mutex_inherit);
#ifndef TX_DISABLE_ERROR_CHECKING
/* Test timer create from initialization. */
test_block_pool_create_init = tx_block_pool_create(&init_block_pool, "init block pool", 10, init_block_pool_area, sizeof(init_block_pool_area));
/* Test byte pool create from initialization. */
test_byte_pool_create_init = tx_byte_pool_create(&init_byte_pool, "init byte pool", init_byte_pool_area, sizeof(init_byte_pool_area));
test_byte_pool_create_init += tx_byte_allocate(&init_byte_pool, (VOID **) &pointer, 20, TX_NO_WAIT);
test_byte_pool_create_init += tx_byte_release(pointer);
/* Test event flag create from initialization. */
test_event_flags_from_init = tx_event_flags_create(&init_event_flags, "init events");
/* Test queue create from initialization. */
test_queue_from_init = tx_queue_create(&init_queue, "init queue", TX_1_ULONG, init_queue_area, sizeof(init_queue_area));
/* Test semaphore create from initialization. */
test_semaphore_from_init = tx_semaphore_create(&init_semaphore, "init semaphore", 0);
/* Test timer creat from initialization. */
test_timer_create_init = tx_timer_create(&init_timer, "init timer", init_timer_entry, 0x5678,
100, 200, TX_AUTO_ACTIVATE);
/* Test calling tx_thread_relinquish to see if the error checking throws it out. */
tx_thread_relinquish();
#endif
/* Remember the free memory pointer. */
test_free_memory_ptr = &tests_memory[0]; //pointer;
/* Clear the ISR dispatch. */
test_isr_dispatch = TX_NULL;
/* Ensure that _tx_thread_time_slice can handle NULL thread, note that current thread pointer is NULL at this point. */
_tx_thread_time_slice();
/* Test to make sure _tx_thread_time_slice can handle a none-ready thread. */
init_test_thread.tx_thread_state = TX_IO_DRIVER;
init_test_thread.tx_thread_new_time_slice = 0;
init_test_thread.tx_thread_suspend_cleanup = TX_NULL;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_suspending = TX_TRUE;
_tx_thread_current_ptr = &init_test_thread;
_tx_thread_time_slice();
/* Test to make sure _tx_thread_time_slice can handle preemption-threshold set. */
init_test_thread.tx_thread_state = TX_READY;
init_test_thread.tx_thread_new_time_slice = 0;
init_test_thread.tx_thread_priority = 10;
init_test_thread.tx_thread_preempt_threshold = 9;
init_test_thread.tx_thread_ready_next = &init_test_thread;
init_test_thread.tx_thread_ready_previous = &init_test_thread;
_tx_thread_time_slice();
_tx_thread_current_ptr = TX_NULL;
/* Test to make sure _tx_thread_shell_entry can handle a NULL mutex release function pointer. */
temp_mutex_release = _tx_thread_mutex_release;
temp_thread = _tx_thread_execute_ptr;
_tx_thread_mutex_release = TX_NULL;
init_test_thread.tx_thread_state = TX_READY;
init_test_thread.tx_thread_suspend_cleanup = TX_NULL;
init_test_thread.tx_thread_new_time_slice = 0;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_suspending = TX_FALSE;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_entry = test_thread_entry1;
_tx_thread_current_ptr = &init_test_thread;
_tx_thread_execute_ptr = &init_test_thread;
_tx_thread_entry_exit_notify(&init_test_thread, test_exit_notify);
_tx_thread_shell_entry();
_tx_thread_current_ptr = TX_NULL;
_tx_thread_execute_ptr = temp_thread;
_tx_thread_mutex_release = temp_mutex_release; /* Recover Mutex release pointer. */
/* Test _tx_thread_system_suspend when not current, preemption is needed but disabled. */
temp_thread = _tx_thread_execute_ptr;
init_test_thread.tx_thread_state = TX_READY;
init_test_thread.tx_thread_suspend_cleanup = TX_NULL;
init_test_thread.tx_thread_new_time_slice = 0;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_suspending = TX_FALSE;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_entry = test_thread_entry1;
_tx_thread_execute_ptr = &init_test_thread;
#ifndef TX_NOT_INTERRUPTABLE
_tx_thread_preempt_disable++;
#endif
_tx_thread_system_suspend(&init_test_thread);
_tx_thread_execute_ptr = temp_thread;
/* Test _tx_thread_system_resume when not current, suspending and in a COMPLETED state. */
temp_thread = _tx_thread_execute_ptr;
init_test_thread.tx_thread_state = TX_COMPLETED;
init_test_thread.tx_thread_suspend_cleanup = TX_NULL;
init_test_thread.tx_thread_new_time_slice = 0;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_suspending = TX_TRUE;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_entry = test_thread_entry1;
_tx_thread_preempt_disable++;
_tx_thread_execute_ptr = &init_test_thread;
_tx_thread_system_resume(&init_test_thread);
_tx_thread_execute_ptr = temp_thread;
/* Test _tx_thread_system_resume when not current, not suspending and already in a TX_READY state. */
temp_thread = _tx_thread_execute_ptr;
init_test_thread.tx_thread_state = TX_READY;
init_test_thread.tx_thread_suspend_cleanup = TX_NULL;
init_test_thread.tx_thread_new_time_slice = 0;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_suspending = TX_FALSE;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_entry = test_thread_entry1;
_tx_thread_preempt_disable++;
_tx_thread_execute_ptr = &init_test_thread;
_tx_thread_system_resume(&init_test_thread);
_tx_thread_execute_ptr = temp_thread;
/* Test _tx_thread_system_resume when not current, suspending and in a TERMINATED state. */
temp_thread = _tx_thread_execute_ptr;
init_test_thread.tx_thread_state = TX_TERMINATED;
init_test_thread.tx_thread_suspend_cleanup = TX_NULL;
init_test_thread.tx_thread_new_time_slice = 0;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_suspending = TX_TRUE;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_entry = test_thread_entry1;
_tx_thread_preempt_disable++;
_tx_thread_execute_ptr = &init_test_thread;
_tx_thread_system_resume(&init_test_thread);
_tx_thread_execute_ptr = temp_thread;
/* Test tx_thread_resume to test the saved_thread_ptr being NULL. */
temp_thread = _tx_thread_execute_ptr;
_tx_thread_execute_ptr = TX_NULL;
tx_thread_resume(&test_thread1);
tx_thread_suspend(&test_thread1);
_tx_thread_execute_ptr = temp_thread;
/* Test preemption change when the new priority is the same as the threshold. */
init_test_thread.tx_thread_state = TX_SUSPENDED;
init_test_thread.tx_thread_suspend_cleanup = TX_NULL;
init_test_thread.tx_thread_new_time_slice = 0;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_suspending = TX_FALSE;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_user_priority = 10;
init_test_thread.tx_thread_user_preempt_threshold = 10;
init_test_thread.tx_thread_priority = 10;
init_test_thread.tx_thread_preempt_threshold = 10;
init_test_thread.tx_thread_entry = test_thread_entry1;
_tx_thread_preemption_change(&init_test_thread, 10, &old_preemption);
#ifndef TX_NOT_INTERRUPTABLE
/* Test semaphore cleanup with an invalid semaphore ID. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_semaphore;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_semaphore_cleanup);
cleanup_semaphore.tx_semaphore_id = 0;
cleanup_semaphore.tx_semaphore_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_semaphore_cleanup(&init_test_thread, 0);
/* Test semaphore cleanup with an invalid suspension sequence. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_semaphore;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_semaphore_cleanup);
cleanup_semaphore.tx_semaphore_id = 0;
cleanup_semaphore.tx_semaphore_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_semaphore_cleanup(&init_test_thread, 1);
/* Test semaphore cleanup with a NULL semaphore pointer. */
init_test_thread.tx_thread_suspend_control_block = TX_NULL;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_semaphore_cleanup);
cleanup_semaphore.tx_semaphore_id = TX_SEMAPHORE_ID;
cleanup_semaphore.tx_semaphore_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_semaphore_cleanup(&init_test_thread, 0);
/* Test semaphore cleanup with an valid semaphore ID but a suspension count of 0. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_semaphore;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_semaphore_cleanup);
cleanup_semaphore.tx_semaphore_id = TX_SEMAPHORE_ID;
cleanup_semaphore.tx_semaphore_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_semaphore_cleanup(&init_test_thread, 0);
/* Test queue cleanup with a NULL cleanup pointer. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_queue;
init_test_thread.tx_thread_suspend_cleanup = TX_NULL;
cleanup_queue.tx_queue_id = 0;
cleanup_queue.tx_queue_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_queue_cleanup(&init_test_thread, 0);
/* Test queue cleanup with a NULL queue pointer. */
init_test_thread.tx_thread_suspend_control_block = TX_NULL;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_queue_cleanup);
cleanup_queue.tx_queue_id = 0;
cleanup_queue.tx_queue_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_queue_cleanup(&init_test_thread, 0);
/* Test queue cleanup with an invalid queue ID. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_queue;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_queue_cleanup);
cleanup_queue.tx_queue_id = 0;
cleanup_queue.tx_queue_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_queue_cleanup(&init_test_thread, 0);
/* Test queue cleanup with an invalid suspension sequence. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_queue;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_queue_cleanup);
cleanup_queue.tx_queue_id = 0;
cleanup_queue.tx_queue_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_queue_cleanup(&init_test_thread, 1);
/* Test queue cleanup with an valid queue ID but a suspension count of 0. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_queue;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_queue_cleanup);
cleanup_queue.tx_queue_id = TX_QUEUE_ID;
cleanup_queue.tx_queue_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_queue_cleanup(&init_test_thread, 0);
/* Test mutex cleanup with a NULL cleanup pointer. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_mutex;
init_test_thread.tx_thread_suspend_cleanup = TX_NULL;
cleanup_mutex.tx_mutex_id = 0;
cleanup_mutex.tx_mutex_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_mutex_cleanup(&init_test_thread, 0);
/* Test mutex cleanup with a NULL mutex pointer. */
init_test_thread.tx_thread_suspend_control_block = TX_NULL;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_mutex_cleanup);
cleanup_mutex.tx_mutex_id = 0;
cleanup_mutex.tx_mutex_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_mutex_cleanup(&init_test_thread, 0);
/* Test mutex cleanup with an invalid mutex ID. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_mutex;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_mutex_cleanup);
cleanup_mutex.tx_mutex_id = 0;
cleanup_mutex.tx_mutex_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_mutex_cleanup(&init_test_thread, 0);
/* Test mutex cleanup with an invalid suspension sequence. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_mutex;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_mutex_cleanup);
cleanup_mutex.tx_mutex_id = 0;
cleanup_mutex.tx_mutex_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_mutex_cleanup(&init_test_thread, 1);
/* Test mutex cleanup with an valid mutex ID but a suspension count of 0. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_mutex;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_mutex_cleanup);
cleanup_mutex.tx_mutex_id = TX_MUTEX_ID;
cleanup_mutex.tx_mutex_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_mutex_cleanup(&init_test_thread, 0);
/* Test event flag cleanup with a NULL cleanup pointer. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_event_flags;
init_test_thread.tx_thread_suspend_cleanup = TX_NULL;
cleanup_event_flags.tx_event_flags_group_id = 0;
cleanup_event_flags.tx_event_flags_group_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_event_flags_cleanup(&init_test_thread, 0);
/* Test event flag cleanup with a NULL event flag pointer. */
init_test_thread.tx_thread_suspend_control_block = TX_NULL;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_event_flags_cleanup);
cleanup_event_flags.tx_event_flags_group_id = 0;
cleanup_event_flags.tx_event_flags_group_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_event_flags_cleanup(&init_test_thread, 0);
/* Test event flag cleanup with an invalid ID. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_event_flags;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_event_flags_cleanup);
cleanup_event_flags.tx_event_flags_group_id = 0;
cleanup_event_flags.tx_event_flags_group_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_event_flags_cleanup(&init_test_thread, 0);
/* Test event flag cleanup with an invalid suspension sequence. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_event_flags;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_event_flags_cleanup);
cleanup_event_flags.tx_event_flags_group_id = 0;
cleanup_event_flags.tx_event_flags_group_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_event_flags_cleanup(&init_test_thread, 1);
/* Test event flag cleanup with an valid ID but a suspension count of 0. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_event_flags;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_event_flags_cleanup);
cleanup_event_flags.tx_event_flags_group_id = TX_EVENT_FLAGS_ID;
cleanup_event_flags.tx_event_flags_group_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_event_flags_cleanup(&init_test_thread, 0);
/* Test block pool cleanup with a NULL cleanup pointer. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_block_pool;
init_test_thread.tx_thread_suspend_cleanup = TX_NULL;
cleanup_block_pool.tx_block_pool_id = 0;
cleanup_block_pool.tx_block_pool_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_block_pool_cleanup(&init_test_thread, 0);
/* Test block pool cleanup with a NULL block pool pointer. */
init_test_thread.tx_thread_suspend_control_block = TX_NULL;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_block_pool_cleanup);
cleanup_block_pool.tx_block_pool_id = 0;
cleanup_block_pool.tx_block_pool_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_block_pool_cleanup(&init_test_thread, 0);
/* Test block pool cleanup with an invalid ID. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_block_pool;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_block_pool_cleanup);
cleanup_block_pool.tx_block_pool_id = 0;
cleanup_block_pool.tx_block_pool_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_block_pool_cleanup(&init_test_thread, 0);
/* Test block pool cleanup with an invalid suspension sequence. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_block_pool;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_block_pool_cleanup);
cleanup_block_pool.tx_block_pool_id = 0;
cleanup_block_pool.tx_block_pool_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_block_pool_cleanup(&init_test_thread, 1);
/* Test block pool cleanup with an valid ID but a suspension count of 0. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_block_pool;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_block_pool_cleanup);
cleanup_block_pool.tx_block_pool_id = TX_BLOCK_POOL_ID;
cleanup_block_pool.tx_block_pool_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_block_pool_cleanup(&init_test_thread, 0);
/* Test byte pool cleanup with a NULL cleanup pointer. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_byte_pool;
init_test_thread.tx_thread_suspend_cleanup = TX_NULL;
cleanup_byte_pool.tx_byte_pool_id = 0;
cleanup_byte_pool.tx_byte_pool_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_byte_pool_cleanup(&init_test_thread, 0);
/* Test byte pool cleanup with a NULL byte pool pointer. */
init_test_thread.tx_thread_suspend_control_block = TX_NULL;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_byte_pool_cleanup);
cleanup_byte_pool.tx_byte_pool_id = 0;
cleanup_byte_pool.tx_byte_pool_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_byte_pool_cleanup(&init_test_thread, 0);
/* Test byte pool cleanup with an invalid ID. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_byte_pool;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_byte_pool_cleanup);
cleanup_byte_pool.tx_byte_pool_id = 0;
cleanup_byte_pool.tx_byte_pool_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_byte_pool_cleanup(&init_test_thread, 0);
/* Test byte pool cleanup with an invalid suspension sequence. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_byte_pool;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_byte_pool_cleanup);
cleanup_byte_pool.tx_byte_pool_id = 0;
cleanup_byte_pool.tx_byte_pool_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_byte_pool_cleanup(&init_test_thread, 1);
/* Test byte pool cleanup with an valid ID but a suspension count of 0. */
init_test_thread.tx_thread_suspend_control_block = (VOID *) &cleanup_byte_pool;
init_test_thread.tx_thread_suspend_cleanup = &(_tx_byte_pool_cleanup);
cleanup_byte_pool.tx_byte_pool_id = TX_BYTE_POOL_ID;
cleanup_byte_pool.tx_byte_pool_suspended_count = 0;
init_test_thread.tx_thread_suspension_sequence = 0;
_tx_byte_pool_cleanup(&init_test_thread, 0);
#endif
#ifndef TX_ENABLE_EVENT_TRACE
/* Call ISR trace events when trace is not enabled. */
/* Call trace ISR enter event insert. */
tx_trace_isr_enter_insert(1);
/* Call trace ISR exit event insert. */
tx_trace_isr_exit_insert(1);
#endif
/* Test the list start path in timer info get and timer deactivate. */
test_timer.tx_timer_id = 0;
_tx_timer_create(&test_timer, "init timer", init_timer_entry, 0x5678, 100, 200, TX_AUTO_ACTIVATE);
_timer_list_start_backup = _tx_timer_list_start;
_tx_timer_list_start = _tx_timer_list_end;
_tx_timer_info_get(&test_timer, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL);
_tx_timer_deactivate(&test_timer);
_tx_timer_list_start = _timer_list_start_backup;
_tx_timer_deactivate(&test_timer);
_tx_timer_delete(&test_timer);
/* Test the stack analyze function with a dummy thread. */
/* Clear the test stack analyze flag. */
test_stack_analyze_flag = 0;
/* Make a fake thread with a fake stack. */
test_thread2.tx_thread_id = TX_THREAD_ID;
#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING)
/* Set the thread pointer. */
thread_ptr = &(test_thread2);
/* Initialize the stack fill value. */
thread_ptr -> tx_thread_stack_fill_value = (0xFEFEFEFEUL);
#endif
for (i = 0; i < (sizeof(test_thread2_stack)/sizeof(ULONG)); i++)
{
/* Set the fake thread stack to the fill pattern. */
test_thread2_stack[i] = TX_STACK_FILL;
}
/* Setup index to last point. */
i = (sizeof(test_thread2_stack)/sizeof(ULONG)) - 1;
/* Setup the stack start and end pointers. */
test_thread2.tx_thread_stack_start = &(test_thread2_stack[0]);
test_thread2.tx_thread_stack_end = &(test_thread2_stack[i]);
test_thread2.tx_thread_stack_size = sizeof(test_thread2_stack);
test_thread2.tx_thread_stack_highest_ptr = test_thread2.tx_thread_stack_end;
test_thread2.tx_thread_stack_ptr = test_thread2.tx_thread_stack_start;
/* Fill 20 words of stack. */
for (j = 0; j < 20; j++)
{
/* Fill the stack with 0s. */
test_thread2_stack[i--] = 0;
}
/* Call the analyze stack function. */
_tx_thread_stack_analyze(&test_thread2);
/* Call it again for no change coverage. */
_tx_thread_stack_analyze(&test_thread2);
/* Fill 99 words of stack. */
for (j = 0; j < 99; j++)
{
/* Fill the stack with 1s. */
test_thread2_stack[i--] = 1;
}
/* Call the analyze stack function. */
_tx_thread_stack_analyze(&test_thread2);
/* Call it again for no change coverage. */
_tx_thread_stack_analyze(&test_thread2);
#ifndef TX_MANUAL_TEST
/* Now set the flag to 1 to cause the thread ID to be cleared. */
test_stack_analyze_flag = 1;
/* Call stack analyze with an ID that is cleared in the middle. */
_tx_thread_stack_analyze(&test_thread2);
/* Restore the ID. */
test_thread2.tx_thread_id = TX_THREAD_ID;
/* Now set the flag to 2 to cause the stack ptr to be equal to the start of the stack. */
test_stack_analyze_flag = 2;
/* Call stack analyze with an ID that is cleared in the middle. */
_tx_thread_stack_analyze(&test_thread2);
test_thread2.tx_thread_stack_highest_ptr = test_thread2.tx_thread_stack_end;
/* Now set the flag to 3 to cause the stack pointer to not have the fill pattern. */
test_stack_analyze_flag = 3;
/* Call stack analyze with an ID that is cleared in the middle. */
_tx_thread_stack_analyze(&test_thread2);
#endif
/* Test error condition on _tx_queue_flush. */
test_queue.tx_queue_enqueued = 1;
test_queue.tx_queue_suspended_count = 1;
test_queue.tx_queue_suspension_list = TX_NULL;
/* Call _tx_queue_flush to test the thread NULL check. */
_tx_queue_flush(&test_queue);
#ifndef TX_NOT_INTERRUPTABLE
/* Make sure the suspension cancelled path is exercised in tx_thread_system_resume... This normally happens,
however, sometimes on less real-time platforms the timing is not guaranteed. */
/* Increment the preempt disable flag. */
_tx_thread_preempt_disable++;
/* Build a thread control block with fake info. */
test_thread3.tx_thread_suspending = TX_TRUE;
test_thread3.tx_thread_state = TX_SUSPENDED;
test_thread3.tx_thread_delayed_suspend = TX_FALSE;
test_thread3.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
test_thread3.tx_thread_stack_start = (VOID *) &test_thread2_stack[0];
test_thread3.tx_thread_stack_end = (VOID *) &test_thread2_stack[255];
test_thread3.tx_thread_stack_ptr = (VOID *) &test_thread2_stack[255];
/* Call the system resume function directly to insure the suspension cancel works properly. */
_tx_thread_system_resume(&test_thread3);
#endif
/* Test preempt-disable safeguard. */
/* Increment the preempt disable flag. */
_tx_thread_preempt_disable++;
/* Test block pool suspenson safeguard. */
fake_block_pool.tx_block_pool_available = 0;
status = _tx_block_allocate(&fake_block_pool, (VOID **) &pointer, TX_WAIT_FOREVER);
if (status != TX_NO_MEMORY)
test_control_system_errors++;
/* Test byte pool suspension safeguard. */
fake_byte_pool.tx_byte_pool_fragments = 2;
fake_byte_pool.tx_byte_pool_available = 0;
status = _tx_byte_allocate(&fake_byte_pool, (VOID **) &pointer, 1000, TX_WAIT_FOREVER);
if (status != TX_NO_MEMORY)
test_control_system_errors++;
/* Test event flags suspension safeguard. */
fake_event_flags.tx_event_flags_group_current = 0;
status = _tx_event_flags_get(&fake_event_flags, 1, TX_AND, &flags, TX_WAIT_FOREVER);
if (status != TX_NO_EVENTS)
test_control_system_errors++;
/* Test mutex suspension safeguard. */
fake_mutex.tx_mutex_ownership_count = 1;
fake_mutex.tx_mutex_inherit = 0;
fake_mutex.tx_mutex_owner = &init_test_thread;
status = _tx_mutex_get(&fake_mutex, TX_WAIT_FOREVER);
if (status != TX_NOT_AVAILABLE)
test_control_system_errors++;
/* Test queue front send suspension safeguard. */
fake_queue.tx_queue_available_storage = 0;
status = _tx_queue_front_send(&fake_queue, (VOID *) pointer, TX_WAIT_FOREVER);
if (status != TX_QUEUE_FULL)
test_control_system_errors++;
/* Test queue receive suspension safeguard. */
fake_queue.tx_queue_enqueued = 0;
status = _tx_queue_receive(&fake_queue, (VOID **) &pointer, TX_WAIT_FOREVER);
if (status != TX_QUEUE_EMPTY)
test_control_system_errors++;
/* Test queue send suspension safeguard. */
fake_queue.tx_queue_available_storage = 0;
status = _tx_queue_send(&fake_queue, (VOID *) pointer, TX_WAIT_FOREVER);
if (status != TX_QUEUE_FULL)
test_control_system_errors++;
/* Test semaphore suspension safeguard. */
fake_semaphore.tx_semaphore_count = 0;
status = _tx_semaphore_get(&fake_semaphore, TX_WAIT_FOREVER);
if (status != TX_NO_INSTANCE)
test_control_system_errors++;
/* Test thread sleep suspension safeguard. */
_tx_thread_current_ptr = &init_test_thread;
temp = _tx_thread_system_state;
_tx_thread_system_state = 0;
status = _tx_thread_sleep(10);
if (status != TX_CALLER_ERROR)
test_control_system_errors++;
/* Test thread suspend suspension safeguard. */
init_test_thread.tx_thread_state = TX_READY;
status = _tx_thread_suspend(&init_test_thread);
if (status != TX_SUSPEND_ERROR)
test_control_system_errors++;
_tx_thread_system_state = temp;
_tx_thread_current_ptr = TX_NULL;
/* Decrement the preempt disable flag. */
_tx_thread_preempt_disable--;
}
/* Define the test control thread. This thread is responsible for dispatching all of the
tests in the ThreadX test suite. */
void test_control_thread_entry(ULONG thread_input)
{
UINT i;
/* Raise the priority of the control thread to 0. */
tx_thread_priority_change(&test_control_thread, 0, &i);
#ifdef CTEST
test_control_cleanup();
#endif
/* Print out banner. */
printf("********************** ThreadX Validation/Regression Test Suite *********************************\n\n");
/* Print version id. */
printf("Version: %s\n\n", _tx_version_id);
/* Print out the tests... */
printf("Running validation/regression test:\n\n");
/* Loop to process all tests... */
i = 0;
while (test_control_tests[i].test_entry != TX_NULL)
{
/* Clear the ISR dispatch. */
test_isr_dispatch = TX_NULL;
/* Dispatch the test. */
(test_control_tests[i++].test_entry)(test_free_memory_ptr);
/* Clear the ISR dispatch. */
test_isr_dispatch = TX_NULL;
/* Suspend control test to allow test to run. */
tx_thread_suspend(&test_control_thread);
/* Test finished, cleanup in preparation for the next test. */
test_control_cleanup();
}
/* Finished with all tests, print results and return! */
printf("**** Testing Complete ****\n");
printf("**** Test Summary: Tests Passed: %lu Tests Failed: %lu System Errors: %lu\n", test_control_successful_tests, test_control_failed_tests, test_control_system_errors);
#ifndef EXTERNAL_EXIT
exit(test_control_failed_tests + test_control_system_errors);
#else
external_exit(test_control_failed_tests + test_control_system_errors);
#endif
}
void test_control_return(UINT status)
{
UINT old_posture = TX_INT_ENABLE;
/* Save the status in a global. */
test_control_return_status = status;
/* Ensure interrupts are enabled. */
old_posture = tx_interrupt_control(TX_INT_ENABLE);
/* Determine if it was successful or not. */
if (status)
test_control_failed_tests++;
else
test_control_successful_tests++;
/* Now check for system errors. */
/* Is preempt disable flag set? */
if (_tx_thread_preempt_disable)
{
/* System error - preempt disable should never be set inside of a thread! */
printf(" ***** SYSTEM ERROR ***** _tx_thread_preempt_disable is non-zero!\n");
test_control_system_errors++;
}
/* Is system state set? */
if (_tx_thread_system_state)
{
/* System error - system state should never be set inside of a thread! */
printf(" ***** SYSTEM ERROR ***** _tx_thread_system_state is non-zero!\n");
test_control_system_errors++;
}
/* Are interrupts disabled? */
if (old_posture == TX_INT_DISABLE)
{
/* System error - interrupts should alwasy be enabled in our test threads! */
printf(" ***** SYSTEM ERROR ***** test returned with interrupts disabled!\n");
test_control_system_errors++;
}
/* Resume the control thread to fully exit the test. */
tx_thread_resume(&test_control_thread);
}
void test_control_cleanup(void)
{
TX_MUTEX *mutex_ptr;
TX_THREAD *thread_ptr;
/* Delete all queues. */
while(_tx_queue_created_ptr)
{
/* Delete queue. */
tx_queue_delete(_tx_queue_created_ptr);
}
/* Delete all semaphores. */
while(_tx_semaphore_created_ptr)
{
/* Delete semaphore. */
tx_semaphore_delete(_tx_semaphore_created_ptr);
}
/* Delete all event flag groups. */
while(_tx_event_flags_created_ptr)
{
/* Delete event flag group. */
tx_event_flags_delete(_tx_event_flags_created_ptr);
}
/* Delete all byte pools. */
while(_tx_byte_pool_created_ptr)
{
/* Delete byte pool. */
tx_byte_pool_delete(_tx_byte_pool_created_ptr);
}
/* Delete all block pools. */
while(_tx_block_pool_created_ptr)
{
/* Delete block pool. */
tx_block_pool_delete(_tx_block_pool_created_ptr);
}
/* Delete all timers. */
while(_tx_timer_created_ptr)
{
/* Deactivate timer. */
tx_timer_deactivate(_tx_timer_created_ptr);
/* Delete timer. */
tx_timer_delete(_tx_timer_created_ptr);
}
/* Delete all mutexes (except for system mutex). */
while(_tx_mutex_created_ptr)
{
/* Setup working mutex pointer. */
mutex_ptr = _tx_mutex_created_ptr;
#ifdef __ghs
/* Determine if the mutex is the GHS system mutex. If so, don't delete! */
if (mutex_ptr == &__ghLockMutex)
{
/* Move to next mutex. */
mutex_ptr = mutex_ptr -> tx_mutex_created_next;
}
/* Determine if there are no more mutexes to delete. */
if (_tx_mutex_created_count == 1)
break;
#endif
/* Delete mutex. */
tx_mutex_delete(mutex_ptr);
}
/* Delete all threads, except for timer thread, and test control thread. */
while (_tx_thread_created_ptr)
{
/* Setup working pointer. */
thread_ptr = _tx_thread_created_ptr;
#ifdef TX_TIMER_PROCESS_IN_ISR
/* Determine if there are more threads to delete. */
if (_tx_thread_created_count == 1)
break;
/* Determine if this thread is the test control thread. */
if (thread_ptr == &test_control_thread)
{
/* Move to the next thread pointer. */
thread_ptr = thread_ptr -> tx_thread_created_next;
}
#else
/* Determine if there are more threads to delete. */
if (_tx_thread_created_count == 2)
break;
/* Move to the thread not protected. */
while ((thread_ptr == &_tx_timer_thread) || (thread_ptr == &test_control_thread))
{
/* Yes, move to the next thread. */
thread_ptr = thread_ptr -> tx_thread_created_next;
}
#endif
/* First terminate the thread to ensure it is ready for deletion. */
tx_thread_terminate(thread_ptr);
/* Delete the thread. */
tx_thread_delete(thread_ptr);
}
/* At this point, only the test control thread and the system timer thread and/or mutex should still be
in the system. */
}
void test_thread_entry(ULONG thread_input)
{
/* Resume the next test thread. */
tx_thread_resume(&test_thread1);
/* Suspend this thread but with preemption disabled, so we will actually return. */
_tx_thread_preempt_disable++;
tx_thread_suspend(&test_thread);
/* Now perform a fake thread resume to cause preemption and exercise the path in _tx_thread_system_resume that returns to the scheduler. */
init_test_thread.tx_thread_state = TX_TERMINATED;
init_test_thread.tx_thread_suspend_cleanup = TX_NULL;
init_test_thread.tx_thread_new_time_slice = 0;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_suspending = TX_TRUE;
init_test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL;
init_test_thread.tx_thread_entry = test_thread_entry1;
_tx_thread_system_resume(&init_test_thread);
/* We should not get back here! */
}
void test_thread_entry1(ULONG thread_input)
{
/* Do nothing, just return! */
}
void test_exit_notify(TX_THREAD *thread_ptr, UINT type)
{
/* Clear the suspending flag to short-circuit the suspension. */
thread_ptr -> tx_thread_suspending = TX_FALSE;
}
__attribute__((weak)) void abort_all_threads_suspended_on_mutex(void)
{
}
__attribute__((weak)) void suspend_lowest_priority(void)
{
}
__attribute__((weak)) void abort_and_resume_byte_allocating_thread(void)
{
}