/* This is the test control routine of the ThreadX kernel. All tests are dispatched from this routine. */ #define TX_THREAD_SMP_SOURCE_CODE #include "tx_api.h" #include #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" #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; TX_THREAD test_thread4; TX_THREAD test_thread5; TX_THREAD test_thread6; TX_THREAD test_thread7; TX_THREAD test_thread8; TX_THREAD test_thread9; TX_THREAD test_thread10; TX_THREAD test_thread11; TX_THREAD test_thread12; TX_THREAD test_thread13; TX_THREAD test_thread14; ULONG test_thread4_stack[256]; ULONG test_thread5_stack[256]; ULONG test_thread6_stack[256]; ULONG test_thread7_stack[256]; ULONG test_thread8_stack[256]; ULONG test_thread9_stack[256]; ULONG test_thread10_stack[256]; ULONG test_thread11_stack[256]; ULONG test_thread12_stack[256]; ULONG test_thread13_stack[256]; ULONG test_thread14_stack[256]; /* 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]; UINT mutex_priority_change_extension_selection; UINT priority_change_extension_selection; TEST_FLAG test_forced_mutex_timeout; TEST_FLAG threadx_byte_allocate_loop_test; TEST_FLAG threadx_byte_release_loop_test; TEST_FLAG threadx_mutex_suspension_put_test; TEST_FLAG threadx_mutex_suspension_priority_test; /* Define the external reference for the preempt disable flag. */ extern volatile UINT _tx_thread_preempt_disable; extern volatile ULONG _tx_thread_system_state[TX_THREAD_SMP_MAX_CORES]; /* 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_basic_max_message_size_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 threadx_smp_rebalance_exclustion_test(void *first_unused_memory); void threadx_smp_two_threads_one_core_test(void *first_unused_memory); void threadx_smp_multiple_threads_one_core_test(void *first_unused_memory); void threadx_smp_one_thread_dynamic_exclusion_test(void *first_unused_memory); void threadx_smp_non_trivial_scheduling_test(void *first_unused_memory); void threadx_smp_resume_suspend_accending_order_test(void *first_unused_memory); void threadx_smp_resume_suspend_decending_order_test(void *first_unused_memory); void threadx_smp_preemption_threshold_test(void *first_unused_memory); void threadx_smp_relinquish_test(void *first_unused_memory); void threadx_smp_time_slice_test(void *first_unused_memory); void threadx_smp_random_resume_suspend_test(void *first_unused_memory); void threadx_smp_random_resume_suspend_exclusion_test(void *first_unused_memory); void threadx_smp_random_resume_suspend_exclusion_pt_test(void *first_unused_memory); 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_smp_rebalance_exclustion_test, threadx_smp_two_threads_one_core_test, threadx_smp_multiple_threads_one_core_test, threadx_smp_one_thread_dynamic_exclusion_test, threadx_smp_non_trivial_scheduling_test, threadx_smp_resume_suspend_accending_order_test, threadx_smp_resume_suspend_decending_order_test, threadx_smp_preemption_threshold_test, threadx_smp_relinquish_test, threadx_smp_time_slice_test, threadx_smp_random_resume_suspend_test, threadx_smp_random_resume_suspend_exclusion_test, threadx_smp_random_resume_suspend_exclusion_pt_test, 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_basic_max_message_size_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[0] = 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] = 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; ULONG old_time_slice; 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; /* Create two equal priority threads. */ status = tx_thread_create(&test_thread4, "test thread 4", test_thread_entry1, 4, test_thread4_stack, sizeof(test_thread4_stack), 15, 15, TX_NO_TIME_SLICE, TX_DONT_START); status += tx_thread_create(&test_thread5, "test thread 5", test_thread_entry1, 5, test_thread5_stack, sizeof(test_thread5_stack), 15, 15, TX_NO_TIME_SLICE, TX_DONT_START); status += tx_thread_create(&test_thread6, "test thread 6", test_thread_entry1, 6, test_thread6_stack, sizeof(test_thread6_stack), 16, 16, TX_NO_TIME_SLICE, TX_DONT_START); status += tx_thread_create(&test_thread7, "test thread 7", test_thread_entry1, 7, test_thread7_stack, sizeof(test_thread7_stack), 17, 17, TX_NO_TIME_SLICE, TX_DONT_START); status += tx_thread_create(&test_thread8, "test thread 8", test_thread_entry1, 8, test_thread8_stack, sizeof(test_thread8_stack), 18, 18, TX_NO_TIME_SLICE, TX_DONT_START); status += tx_thread_create(&test_thread9, "test thread 9", test_thread_entry1, 9, test_thread9_stack, sizeof(test_thread9_stack), 19, 19, TX_NO_TIME_SLICE, TX_DONT_START); status += tx_thread_create(&test_thread10, "test thread 10", test_thread_entry1, 10, test_thread10_stack, sizeof(test_thread10_stack), 20, 20, TX_NO_TIME_SLICE, TX_DONT_START); status += tx_thread_create(&test_thread11, "test thread 11", test_thread_entry1, 11, test_thread11_stack, sizeof(test_thread11_stack), 20, 20, TX_NO_TIME_SLICE, TX_DONT_START); status += tx_thread_create(&test_thread12, "test thread 12", test_thread_entry1, 12, test_thread12_stack, sizeof(test_thread12_stack), 20, 20, TX_NO_TIME_SLICE, TX_DONT_START); status += tx_thread_create(&test_thread13, "test thread 13", test_thread_entry1, 13, test_thread13_stack, sizeof(test_thread13_stack), 20, 20, TX_NO_TIME_SLICE, TX_DONT_START); status += tx_thread_create(&test_thread14, "test thread 14", test_thread_entry1, 14, test_thread14_stack, sizeof(test_thread14_stack), 20, 20, TX_NO_TIME_SLICE, TX_DONT_START); status += tx_thread_smp_core_exclude(&test_thread4, 0xD); status += tx_thread_smp_core_exclude(&test_thread5, 0xD); status += tx_thread_resume(&test_thread4); status += tx_thread_suspend(&test_thread4); status += tx_thread_resume(&test_thread4); status += tx_thread_resume(&test_thread5); status += tx_thread_suspend(&test_thread4); status += tx_thread_suspend(&test_thread5); /* Test the fringe cases in tx_thread_system_resume to make sure the behave properly. */ status += tx_thread_smp_core_exclude(&test_thread14, 0); status += tx_thread_smp_core_exclude(&test_thread13, 0); status += tx_thread_smp_core_exclude(&test_thread12, 0); status += tx_thread_smp_core_exclude(&test_thread11, 0); status += tx_thread_smp_core_exclude(&test_thread10, 0); status += tx_thread_smp_core_exclude(&test_thread9, 0xC); status += tx_thread_smp_core_exclude(&test_thread8, 0x3); status += tx_thread_smp_core_exclude(&test_thread7, 0xE); status += tx_thread_smp_core_exclude(&test_thread6, 0xD); status += tx_thread_smp_core_exclude(&test_thread5, 0xB); status += tx_thread_smp_core_exclude(&test_thread4, 0x7); test_thread13.tx_thread_timer.tx_timer_internal_active_next = &test_thread13.tx_thread_timer; test_thread13.tx_thread_timer.tx_timer_internal_list_head = (TX_TIMER_INTERNAL **) &test_thread13.tx_thread_timer; status += tx_thread_resume(&test_thread14); status += tx_thread_resume(&test_thread13); status += tx_thread_resume(&test_thread12); status += tx_thread_resume(&test_thread11); status += tx_thread_resume(&test_thread10); status += tx_thread_resume(&test_thread9); status += tx_thread_resume(&test_thread8); status += tx_thread_resume(&test_thread7); status += tx_thread_resume(&test_thread6); status += tx_thread_resume(&test_thread5); status += tx_thread_resume(&test_thread4); status += tx_thread_suspend(&test_thread14); status += tx_thread_suspend(&test_thread13); status += tx_thread_suspend(&test_thread12); status += tx_thread_suspend(&test_thread11); status += tx_thread_suspend(&test_thread10); status += tx_thread_suspend(&test_thread9); status += tx_thread_suspend(&test_thread8); status += _tx_thread_preemption_change(&test_thread8, 17, &old_preemption); status += tx_thread_resume(&test_thread8); status += tx_thread_suspend(&test_thread8); status += tx_thread_suspend(&test_thread7); status += tx_thread_suspend(&test_thread6); status += tx_thread_suspend(&test_thread5); status += tx_thread_suspend(&test_thread4); /* 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[0] = &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[0] = 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[0]; _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[0] = &init_test_thread; _tx_thread_execute_ptr[0] = &init_test_thread; _tx_thread_entry_exit_notify(&init_test_thread, test_exit_notify); _tx_thread_shell_entry(); _tx_thread_current_ptr[0] = TX_NULL; _tx_thread_execute_ptr[0] = 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[0]; 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[0] = &init_test_thread; #ifndef TX_NOT_INTERRUPTABLE _tx_thread_preempt_disable++; #endif _tx_thread_system_suspend(&init_test_thread); _tx_thread_execute_ptr[0] = temp_thread; /* Test _tx_thread_system_resume when not current, suspending and in a COMPLETED state. */ temp_thread = _tx_thread_execute_ptr[0]; 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; #ifndef TX_NOT_INTERRUPTABLE _tx_thread_preempt_disable++; #endif _tx_thread_execute_ptr[0] = &init_test_thread; _tx_thread_system_resume(&init_test_thread); _tx_thread_execute_ptr[0] = 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[0]; 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; #ifndef TX_NOT_INTERRUPTABLE _tx_thread_preempt_disable++; #endif _tx_thread_execute_ptr[0] = &init_test_thread; _tx_thread_system_resume(&init_test_thread); _tx_thread_execute_ptr[0] = temp_thread; /* Test _tx_thread_system_resume when not current, suspending and in a TERMINATED state. */ temp_thread = _tx_thread_execute_ptr[0]; 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; #ifndef TX_NOT_INTERRUPTABLE _tx_thread_preempt_disable++; #endif _tx_thread_execute_ptr[0] = &init_test_thread; _tx_thread_system_resume(&init_test_thread); _tx_thread_execute_ptr[0] = temp_thread; /* Test tx_thread_resume to test the saved_thread_ptr being NULL. */ temp_thread = _tx_thread_execute_ptr[0]; _tx_thread_execute_ptr[0] = TX_NULL; tx_thread_resume(&test_thread1); tx_thread_suspend(&test_thread1); _tx_thread_execute_ptr[0] = 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); /* Call trace ISR enter event insert. */ tx_trace_isr_enter_insert(0); /* Call trace ISR exit event insert. */ tx_trace_isr_exit_insert(0); #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[0] = &init_test_thread; temp = _tx_thread_system_state[0]; _tx_thread_system_state[0] = 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[0] = temp; _tx_thread_current_ptr[0] = TX_NULL; /* Pickup the current core exclusion. */ tx_thread_smp_core_exclude_get(&test_thread, &temp); /* Move the test thread form core 0. */ tx_thread_smp_core_exclude(&test_thread, 0x1); /* Restore the core exclusion for the test thread. */ tx_thread_smp_core_exclude(&test_thread, temp); /* Test some code paths in the tx_thread_smp_utilities file. */ temp_thread = _tx_thread_current_ptr[3]; _tx_thread_current_ptr[3] = &init_test_thread; _tx_thread_smp_core_interrupt(&test_thread, 0, 3); _tx_thread_current_ptr[3] = temp_thread; temp_thread = _tx_thread_execute_ptr[0]; _tx_thread_execute_ptr[0] = TX_NULL; _tx_thread_smp_lowest_priority_get(); _tx_thread_execute_ptr[0] = temp_thread; _tx_thread_smp_schedule_list[0] = TX_NULL; _tx_thread_smp_remap_solution_find(&init_test_thread, 1, 1, 1); /* Test a corner case in time-slice change. */ init_test_thread.tx_thread_smp_core_mapped = TX_THREAD_SMP_MAX_CORES; _tx_thread_time_slice_change(&init_test_thread, 3, &old_time_slice); /* Test time-slice paths. */ _tx_timer_time_slice[0] = 0; _tx_timer_time_slice[1] = 1; _tx_timer_time_slice[2] = 0; _tx_timer_time_slice[3] = 0; _tx_thread_time_slice(); _tx_timer_time_slice[0] = 0; _tx_timer_time_slice[1] = 0; _tx_timer_time_slice[2] = 1; _tx_timer_time_slice[3] = 0; _tx_thread_time_slice(); _tx_timer_time_slice[0] = 0; _tx_timer_time_slice[1] = 0; _tx_timer_time_slice[2] = 0; _tx_timer_time_slice[3] = 1; _tx_thread_time_slice(); _tx_timer_time_slice[0] = 1; _tx_timer_time_slice[1] = 0; _tx_timer_time_slice[2] = 0; _tx_timer_time_slice[3] = 0; temp_thread -> tx_thread_state = TX_COMPLETED; _tx_thread_current_ptr[0] = temp_thread; _tx_thread_time_slice(); temp_thread -> tx_thread_state = TX_READY; _tx_thread_current_ptr[0] = TX_NULL; _tx_timer_time_slice[0] = 1; _tx_timer_time_slice[1] = 0; _tx_timer_time_slice[2] = 0; _tx_timer_time_slice[3] = 0; temp_thread -> tx_thread_time_slice = 0; _tx_thread_current_ptr[0] = temp_thread; _tx_thread_time_slice(); _tx_thread_current_ptr[0] = 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) { TX_INTERRUPT_SAVE_AREA UINT old_posture = TX_INT_ENABLE; fflush(stdout); /* 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. */ /* Get protection for examination of preempt disable and system state variables. */ TX_DISABLE /* 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[0]) { /* 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++; } /* Release protection. */ TX_RESTORE /* 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); #ifdef TX_NOT_INTERRUPTABLE _tx_thread_preempt_disable--; #endif } 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) { }