diff options
| author | TiejunZhou <[email protected]> | 2023-04-13 16:57:35 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-04-13 16:57:35 +0800 |
| commit | 487ca45752ba350733f09ebce512c89544e190ec (patch) | |
| tree | f5d38d89810821bcf049803fd5150b823fd8c664 /test/tx | |
| parent | ac3b6b326cd7dac0373282c6f557d0d51764e34a (diff) | |
| parent | 5f430f22e2c00f2c079c91f48c9e2a0fc0bbbf47 (diff) | |
Merge pull request #244 from azure-rtos/tizho/test
Release ThreadX regression system
Diffstat (limited to 'test/tx')
103 files changed, 36592 insertions, 0 deletions
diff --git a/test/tx/cmake/CMakeLists.txt b/test/tx/cmake/CMakeLists.txt new file mode 100644 index 00000000..02e2a41b --- /dev/null +++ b/test/tx/cmake/CMakeLists.txt @@ -0,0 +1,73 @@ +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) +cmake_policy(SET CMP0054 NEW) +cmake_policy(SET CMP0057 NEW) + +project(threadx_test LANGUAGES C) + +# Set build configurations +set(BUILD_CONFIGURATIONS default_build_coverage disable_notify_callbacks_build + stack_checking_build trace_build) +set(CMAKE_CONFIGURATION_TYPES + ${BUILD_CONFIGURATIONS} + CACHE STRING "list of supported configuration types" FORCE) +set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + ${CMAKE_CONFIGURATION_TYPES}) +list(GET CMAKE_CONFIGURATION_TYPES 0 BUILD_TYPE) +if((NOT CMAKE_BUILD_TYPE) OR (NOT ("${CMAKE_BUILD_TYPE}" IN_LIST + CMAKE_CONFIGURATION_TYPES))) + set(CMAKE_BUILD_TYPE + "${BUILD_TYPE}" + CACHE STRING "Build Type of the project" FORCE) +endif() + +message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") +message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}.") +set(default_build_coverage "") +set(disable_notify_callbacks_build -DTX_DISABLE_NOTIFY_CALLBACKS) +set(stack_checking_build -DTX_ENABLE_STACK_CHECKING) +set(trace_build -DTX_ENABLE_EVENT_TRACE) + +add_compile_options( + -m32 + -std=c99 + -ggdb + -g3 + -gdwarf-2 + -fdiagnostics-color + -Werror + -DTX_REGRESSION_TEST + -DTEST_STACK_SIZE_PRINTF=4096 + ${${CMAKE_BUILD_TYPE}}) +add_link_options(-m32) + +enable_testing() + +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../../.. threadx) +add_subdirectory(regression) +add_subdirectory(samples) + +# Coverage +if(CMAKE_BUILD_TYPE MATCHES ".*_coverage") + target_compile_options(threadx PRIVATE -fprofile-arcs -ftest-coverage) + target_link_options(threadx PRIVATE -fprofile-arcs -ftest-coverage) +endif() + +target_compile_options( + threadx + PRIVATE -Werror + -Wall + -Wextra + -pedantic + -fmessage-length=0 + -fsigned-char + -ffunction-sections + -fdata-sections + -Wunused + -Wuninitialized + -Wmissing-declarations + -Wconversion + -Wpointer-arith + # -Wshadow + -Wlogical-op + -Waggregate-return + -Wfloat-equal) diff --git a/test/tx/cmake/coverage.sh b/test/tx/cmake/coverage.sh new file mode 100755 index 00000000..ae2c7a4b --- /dev/null +++ b/test/tx/cmake/coverage.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -e + +cd $(dirname $0) +mkdir -p coverage_report/$1 +gcovr --object-directory=build/$1/threadx/CMakeFiles/threadx.dir/common/src -r build/$1 -f ../../../common/src --xml-pretty --output coverage_report/$1.xml +gcovr --object-directory=build/$1/threadx/CMakeFiles/threadx.dir/common/src -r build/$1 -f ../../../common/src --html --html-details --output coverage_report/$1/index.html diff --git a/test/tx/cmake/regression/CMakeLists.txt b/test/tx/cmake/regression/CMakeLists.txt new file mode 100644 index 00000000..160f9e29 --- /dev/null +++ b/test/tx/cmake/regression/CMakeLists.txt @@ -0,0 +1,121 @@ +cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR) +cmake_policy(SET CMP0057 NEW) + +project(regression_test LANGUAGES C) + +set(SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../regression) + +set(regression_test_cases + ${SOURCE_DIR}/threadx_block_memory_basic_test.c + ${SOURCE_DIR}/threadx_block_memory_error_detection_test.c + ${SOURCE_DIR}/threadx_block_memory_information_test.c + ${SOURCE_DIR}/threadx_block_memory_prioritize_test.c + ${SOURCE_DIR}/threadx_block_memory_suspension_test.c + ${SOURCE_DIR}/threadx_block_memory_suspension_timeout_test.c + ${SOURCE_DIR}/threadx_block_memory_thread_terminate_test.c + ${SOURCE_DIR}/threadx_byte_memory_basic_test.c + ${SOURCE_DIR}/threadx_byte_memory_information_test.c + ${SOURCE_DIR}/threadx_byte_memory_prioritize_test.c + ${SOURCE_DIR}/threadx_byte_memory_suspension_test.c + ${SOURCE_DIR}/threadx_byte_memory_suspension_timeout_test.c + ${SOURCE_DIR}/threadx_byte_memory_thread_contention_test.c + ${SOURCE_DIR}/threadx_byte_memory_thread_terminate_test.c + ${SOURCE_DIR}/threadx_event_flag_basic_test.c + ${SOURCE_DIR}/threadx_event_flag_information_test.c + ${SOURCE_DIR}/threadx_event_flag_isr_set_clear_test.c + ${SOURCE_DIR}/threadx_event_flag_isr_wait_abort_test.c + ${SOURCE_DIR}/threadx_event_flag_single_thread_terminate_test.c + ${SOURCE_DIR}/threadx_event_flag_suspension_consume_test.c + ${SOURCE_DIR}/threadx_event_flag_suspension_different_bits_consume_test.c + ${SOURCE_DIR}/threadx_event_flag_suspension_different_bits_test.c + ${SOURCE_DIR}/threadx_event_flag_suspension_test.c + ${SOURCE_DIR}/threadx_event_flag_suspension_timeout_test.c + ${SOURCE_DIR}/threadx_event_flag_thread_terminate_test.c + ${SOURCE_DIR}/threadx_interrupt_control_test.c + ${SOURCE_DIR}/threadx_mutex_basic_test.c + ${SOURCE_DIR}/threadx_mutex_delete_test.c + ${SOURCE_DIR}/threadx_mutex_information_test.c + ${SOURCE_DIR}/threadx_mutex_nested_priority_inheritance_test.c + ${SOURCE_DIR}/threadx_mutex_no_preemption_test.c + ${SOURCE_DIR}/threadx_mutex_preemption_test.c + ${SOURCE_DIR}/threadx_mutex_priority_inheritance_test.c + ${SOURCE_DIR}/threadx_mutex_proritize_test.c + ${SOURCE_DIR}/threadx_mutex_suspension_timeout_test.c + ${SOURCE_DIR}/threadx_mutex_thread_terminate_test.c + ${SOURCE_DIR}/threadx_queue_basic_eight_word_test.c + ${SOURCE_DIR}/threadx_queue_basic_four_word_test.c + ${SOURCE_DIR}/threadx_queue_basic_one_word_test.c + ${SOURCE_DIR}/threadx_queue_basic_sixteen_word_test.c + ${SOURCE_DIR}/threadx_queue_basic_two_word_test.c + ${SOURCE_DIR}/threadx_queue_empty_suspension_test.c + ${SOURCE_DIR}/threadx_queue_flush_no_suspension_test.c + ${SOURCE_DIR}/threadx_queue_flush_test.c + ${SOURCE_DIR}/threadx_queue_front_send_test.c + ${SOURCE_DIR}/threadx_queue_full_suspension_test.c + ${SOURCE_DIR}/threadx_queue_information_test.c + ${SOURCE_DIR}/threadx_queue_prioritize.c + ${SOURCE_DIR}/threadx_queue_suspension_timeout_test.c + ${SOURCE_DIR}/threadx_queue_thread_terminate_test.c + ${SOURCE_DIR}/threadx_semaphore_basic_test.c + ${SOURCE_DIR}/threadx_semaphore_ceiling_put_test.c + ${SOURCE_DIR}/threadx_semaphore_delete_test.c + ${SOURCE_DIR}/threadx_semaphore_information_test.c + ${SOURCE_DIR}/threadx_semaphore_non_preemption_test.c + ${SOURCE_DIR}/threadx_semaphore_preemption_test.c + ${SOURCE_DIR}/threadx_semaphore_prioritize.c + ${SOURCE_DIR}/threadx_semaphore_thread_terminate_test.c + ${SOURCE_DIR}/threadx_semaphore_timeout_test.c + ${SOURCE_DIR}/threadx_thread_basic_execution_test.c + ${SOURCE_DIR}/threadx_thread_basic_time_slice_test.c + ${SOURCE_DIR}/threadx_thread_completed_test.c + ${SOURCE_DIR}/threadx_thread_create_preemption_threshold_test.c + ${SOURCE_DIR}/threadx_thread_delayed_suspension_test.c + ${SOURCE_DIR}/threadx_thread_information_test.c + ${SOURCE_DIR}/threadx_thread_multi_level_preemption_threshold_test.c + ${SOURCE_DIR}/threadx_thread_multiple_non_current_test.c + ${SOURCE_DIR}/threadx_thread_multiple_sleep_test.c + ${SOURCE_DIR}/threadx_thread_multiple_suspension_test.c + ${SOURCE_DIR}/threadx_thread_multiple_time_slice_test.c + ${SOURCE_DIR}/threadx_thread_preemptable_suspension_test.c + ${SOURCE_DIR}/threadx_thread_preemption_change_test.c + ${SOURCE_DIR}/threadx_thread_priority_change.c + ${SOURCE_DIR}/threadx_thread_relinquish_test.c + ${SOURCE_DIR}/threadx_thread_reset_test.c + ${SOURCE_DIR}/threadx_thread_simple_sleep_non_clear_test.c + ${SOURCE_DIR}/threadx_thread_simple_sleep_test.c + ${SOURCE_DIR}/threadx_thread_simple_suspend_test.c + ${SOURCE_DIR}/threadx_thread_sleep_for_100ticks_test.c + ${SOURCE_DIR}/threadx_thread_sleep_terminate_test.c + ${SOURCE_DIR}/threadx_thread_stack_checking_test.c + ${SOURCE_DIR}/threadx_thread_terminate_delete_test.c + ${SOURCE_DIR}/threadx_thread_time_slice_change_test.c + ${SOURCE_DIR}/threadx_thread_wait_abort_and_isr_test.c + ${SOURCE_DIR}/threadx_thread_wait_abort_test.c + ${SOURCE_DIR}/threadx_time_get_set_test.c + ${SOURCE_DIR}/threadx_timer_activate_deactivate_test.c + ${SOURCE_DIR}/threadx_timer_deactivate_accuracy_test.c + ${SOURCE_DIR}/threadx_timer_information_test.c + ${SOURCE_DIR}/threadx_timer_large_timer_accuracy_test.c + ${SOURCE_DIR}/threadx_timer_multiple_accuracy_test.c + ${SOURCE_DIR}/threadx_timer_multiple_test.c + ${SOURCE_DIR}/threadx_timer_simple_test.c + ${SOURCE_DIR}/threadx_trace_basic_test.c + ${SOURCE_DIR}/threadx_initialize_kernel_setup_test.c) + +add_custom_command( + OUTPUT ${SOURCE_DIR}/tx_initialize_low_level.c + COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/generate_test_file.sh + COMMENT "Generating tx_initialize_low_level.c for test") + +add_library(test_utility ${SOURCE_DIR}/tx_initialize_low_level.c + ${SOURCE_DIR}/testcontrol.c) +target_link_libraries(test_utility PUBLIC azrtos::threadx) +target_compile_definitions(test_utility PUBLIC CTEST BATCH_TEST + TEST_STACK_SIZE_PRINTF=4096) + +foreach(test_case ${regression_test_cases}) + get_filename_component(test_name ${test_case} NAME_WE) + add_executable(${test_name} ${test_case}) + target_link_libraries(${test_name} PRIVATE test_utility) + add_test(${CMAKE_BUILD_TYPE}::${test_name} ${test_name}) +endforeach() diff --git a/test/tx/cmake/regression/generate_test_file.sh b/test/tx/cmake/regression/generate_test_file.sh new file mode 100755 index 00000000..ac0a70fa --- /dev/null +++ b/test/tx/cmake/regression/generate_test_file.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +dst=$(dirname $0)/../../regression/tx_initialize_low_level.c +src=$(dirname $0)/../../../../ports/linux/gnu/src/tx_initialize_low_level.c + +line=`sed -n '/_tx_linux_timer_interrupt/=' $src | tail -n 1` +sed "${line}iVOID test_interrupt_dispatch(VOID);" $src > tmp1 +line=`sed -n '/_tx_timer_interrupt/=' $src | tail -n 1` +sed "${line}itest_interrupt_dispatch();" tmp1 > $dst +rm tmp1
\ No newline at end of file diff --git a/test/tx/cmake/run.sh b/test/tx/cmake/run.sh new file mode 120000 index 00000000..429ff2bd --- /dev/null +++ b/test/tx/cmake/run.sh @@ -0,0 +1 @@ +../../../scripts/cmake_bootstrap.sh
\ No newline at end of file diff --git a/test/tx/cmake/samples/CMakeLists.txt b/test/tx/cmake/samples/CMakeLists.txt new file mode 100644 index 00000000..2915ed22 --- /dev/null +++ b/test/tx/cmake/samples/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR) +cmake_policy(SET CMP0057 NEW) + +project(samples LANGUAGES C) + +set(SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../../ports/linux/gnu/example_build) + +set(sample_files + ${SOURCE_DIR}/sample_threadx.c) + +foreach(sample_file ${sample_files}) + get_filename_component(sample_file_name ${sample_file} NAME_WE) + add_executable(${sample_file_name} ${sample_file} ${CMAKE_CURRENT_LIST_DIR}/fake.c) + target_link_libraries(${sample_file_name} PRIVATE azrtos::threadx) +endforeach() diff --git a/test/tx/cmake/samples/fake.c b/test/tx/cmake/samples/fake.c new file mode 100644 index 00000000..199f257e --- /dev/null +++ b/test/tx/cmake/samples/fake.c @@ -0,0 +1,20 @@ +#include "tx_api.h" + +typedef unsigned int TEST_FLAG; +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; +#ifndef TX_TIMER_PROCESS_IN_ISR +TEST_FLAG threadx_delete_timer_thread; +#endif + +void abort_and_resume_byte_allocating_thread(void){} +void abort_all_threads_suspended_on_mutex(void){} +void suspend_lowest_priority(void){} +#ifndef TX_TIMER_PROCESS_IN_ISR +void delete_timer_thread(void){} +#endif +TEST_FLAG test_stack_analyze_flag; +TEST_FLAG test_initialize_flag; +TEST_FLAG test_forced_mutex_timeout;
\ No newline at end of file diff --git a/test/tx/regression/testcontrol.c b/test/tx/regression/testcontrol.c new file mode 100644 index 00000000..ff257ca1 --- /dev/null +++ b/test/tx/regression/testcontrol.c @@ -0,0 +1,1411 @@ +/* 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; + + + /* 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; + 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) +{ +} diff --git a/test/tx/regression/threadx_block_memory_basic_test.c b/test/tx/regression/threadx_block_memory_basic_test.c new file mode 100644 index 00000000..5f2afa01 --- /dev/null +++ b/test/tx/regression/threadx_block_memory_basic_test.c @@ -0,0 +1,568 @@ +/* This test is designed to test simple memory block pool creation, deletion, and + allocates and releases. */ + +#include <stdio.h> +#include "tx_api.h" + +typedef struct BLOCK_MEMORY_TEST_STRUCT +{ + ULONG first; + ULONG second; + TX_BLOCK_POOL pool; + ULONG first_middle; + ULONG second_middle; + ULONG pool_area[2048/sizeof(ULONG)]; + ULONG next_to_last; + ULONG last; + +} BLOCK_MEMORY_TEST; + +static BLOCK_MEMORY_TEST block_memory; + + +/* Define external reference for status of block pool create from initialization. */ + +extern UINT test_block_pool_create_init; + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +static TX_THREAD thread_0; +static TX_THREAD thread_1; + + +static TX_BLOCK_POOL pool_0; +static TX_BLOCK_POOL pool_1; +static TX_BLOCK_POOL pool_2; +static TX_BLOCK_POOL pool_3; + +static TX_TIMER timer_0; + + +static unsigned long error = 0; +static unsigned long timer_executed = 0; +static unsigned long isr_executed = 0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Prototype direct call to block pool core service. */ + +UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, + VOID *pool_start, ULONG pool_size); + + + +/* Define the timer for this test. */ + +static void timer_entry(ULONG i) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +UINT status; +CHAR *pointer; + + + /* Determine if calling block pool create from initialization was successful. */ + if (test_block_pool_create_init != TX_SUCCESS) + { + + /* Error! */ + error++; + } + + /* Attempt to create a block pool from a timer. */ + pointer = (CHAR *) 0x30000; + status = tx_block_pool_create(&pool_3, "pool 3", 100, pointer, 320); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to delete a block pool. */ + status = tx_block_pool_delete(&pool_0); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + timer_executed = 1; + + /* Attempt to allocate a block with suspension from a timer. */ + status = tx_block_allocate(&pool_0, (void **) &pointer, 10); + + /* Check status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + +#endif +} + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +CHAR *pointer; +UINT status; + + + /* Attempt to Allocate block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to create a block pool from an ISR. */ + status = tx_block_pool_create(&pool_3, "pool 3", 100, (void *) 0x100000, 320); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to delete a pool from an ISR. */ + status = tx_block_pool_delete(&pool_0); + + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + isr_executed = 1; +#endif +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_block_memory_basic_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Basic Functionality Test....................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Basic Functionality Test....................... ERROR #2\n"); + test_control_return(1); + } + + /* Create block pools 0 and 1. */ + status = tx_block_pool_create(&pool_0, "pool 0", 100, pointer, 320); + pointer = pointer + 320; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Basic Functionality Test....................... ERROR #3\n"); + test_control_return(1); + } + + status = tx_block_pool_create(&pool_1, "pool 1", 100, pointer, 320); + pointer = pointer + 320; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Basic Functionality Test....................... ERROR #4\n"); + test_control_return(1); + } + + /* Check the no-blocks path. */ + status = _tx_block_pool_create(&pool_2, "pool 2", 100, pointer, 50); + pointer = pointer + 320; + + /* Check status. */ + if (status != TX_SIZE_ERROR) + { + + printf("Running Block Memory Basic Functionality Test....................... ERROR #5\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer_1; +CHAR *pointer_2; +CHAR *pointer_3; +CHAR *pointer_4; +INT i; +unsigned long fake_block[20]; + + + /* Inform user. */ + printf("Running Block Memory Basic Functionality Test....................... "); + + /* Perform block memory test. */ + block_memory.first = 0x11223344; + block_memory.second = 0x55667788; + block_memory.first_middle = 0x21314151; + block_memory.second_middle= 0x61718191; + block_memory.next_to_last = 0x99aabbcc; + block_memory.last = 0xddeeff00; + + /* Create the block pool. */ + status = tx_block_pool_create(&block_memory.pool, "pool memory", 16, &block_memory.pool_area[0], (2048*sizeof(ULONG))/sizeof(ULONG)); + tx_block_pool_delete(&block_memory.pool); + + /* Check for status. */ + if ((status != TX_SUCCESS) || + (block_memory.first != 0x11223344) || + (block_memory.second != 0x55667788) || + (block_memory.first_middle != 0x21314151) || + (block_memory.second_middle != 0x61718191) || + (block_memory.next_to_last != 0x99aabbcc) || + (block_memory.last != 0xddeeff00)) + { + + /* Block memory error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Try to release a non-block. */ + fake_block[0] = 0; + fake_block[1] = 0; + status = tx_block_release(&fake_block[2]); + + /* Check status. */ + if (status != TX_PTR_ERROR) + { + + /* Block memory error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Try to release a block that points to a non-pool. */ + fake_block[0] = 0; + fake_block[1] = (unsigned long) &fake_block[0]; + status = tx_block_release(&fake_block[2]); + + /* Check status. */ + if (status != TX_PTR_ERROR) + { + + /* Block memory error. */ + printf("ERROR #8\n"); + test_control_return(1); + } +#endif + + /* Allocate first block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_1, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_1, (CHAR) 0xEF, 100); + + /* Allocate second block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_2, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_2, (CHAR) 0xEF, 100); + + /* Allocate third block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_3, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_3, (CHAR) 0xEF, 100); + + /* Attempt to allocate fourth block from the pool. This should fail because + there should be no more blocks in the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_4, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_MEMORY) + { + + /* Block memory error. */ + printf("ERROR ##12\n"); + test_control_return(1); + } + + /* Set the memory of all of the allocated blocks. */ + for (i =0; i < 100; i++) + { + pointer_1[i] = (CHAR) 0xFF; + pointer_2[i] = (CHAR) 0xFF; + pointer_3[i] = (CHAR) 0xFF; + } + + /* Now release each of the blocks. */ + status = tx_block_release(pointer_1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Release the second block. */ + status = tx_block_release(pointer_2); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Release the third block. */ + status = tx_block_release(pointer_3); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Allocate each block again to make sure everything still + works. The block addresses should come out in reverse + order, because a released block is placed at the head of + the list. */ + + /* Allocate first block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_1, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_1, (CHAR) 0xEF, 100); + + /* Allocate second block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_2, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_2, (CHAR) 0xEF, 100); + + /* Allocate third block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_3, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_3, (CHAR) 0xEF, 100); + + /* Attempt to allocate fourth block from the pool. This should fail because + there should be no more blocks in the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_4, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_MEMORY) + { + + /* Block memory error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Create a timer for the test. */ + tx_timer_create(&timer_0, "timer 0", timer_entry, 0, 1, 1, TX_AUTO_ACTIVATE); + + /* Setup the ISR. */ + test_isr_dispatch = test_isr; + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Now resume the background thread. */ + tx_thread_resume(&thread_1); + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Clear the ISR. */ + test_isr_dispatch = TX_NULL; + + /* Test for error. */ + if ((error) || (timer_executed != 1) || (isr_executed != 1)) + { + + /* Block memory error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + +#endif + + /* Delete both block pools. */ + status = tx_block_pool_delete(&pool_0); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + status = tx_block_pool_delete(&pool_1); + + /* Check status. */ + if ((status != TX_SUCCESS) || (error)) + { + + /* Block memory error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + + while(1) + { + + tx_thread_relinquish(); + } +} diff --git a/test/tx/regression/threadx_block_memory_error_detection_test.c b/test/tx/regression/threadx_block_memory_error_detection_test.c new file mode 100644 index 00000000..de28012f --- /dev/null +++ b/test/tx/regression/threadx_block_memory_error_detection_test.c @@ -0,0 +1,387 @@ +/* This test is designed to test error detection for simple memory block operations. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + + +static TX_BLOCK_POOL pool_0; +static TX_BLOCK_POOL pool_1; +static TX_BLOCK_POOL pool_2; +static CHAR *pointer; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + +UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, + VOID *pool_start, ULONG pool_size, UINT pool_control_block_size); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_block_memory_error_detection_application_define(void *first_unused_memory) +#endif +{ + +INT status; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Create block pool 0. */ + status = tx_block_pool_create(&pool_0, "pool 0", 100, pointer, 320); + pointer = pointer + 320; + +#ifndef TX_DISABLE_ERROR_CHECKING /* skip this test and pretend it passed */ + + /* Create block pool again to get pool_ptr error. */ + status = tx_block_pool_create(&pool_0, "pool 0", 100, pointer, 320); + if (status != TX_POOL_ERROR) + return; + + /* Create block pool with NULL pointer. */ + status = tx_block_pool_create(TX_NULL, "pool 0", 100, pointer, 320); + if (status != TX_POOL_ERROR) + { + + printf("Running Block Memory Error Detection Test........................... ERROR #1\n"); + test_control_return(1); + } + + /* Create block pool pointer if NULL start. */ + status = tx_block_pool_create(&pool_1, "pool 0", 100, NULL, 320); + if (status != TX_PTR_ERROR) + { + + printf("Running Block Memory Error Detection Test........................... ERROR #2\n"); + test_control_return(1); + } + + /* Create block pool pointer with invalid size. */ + status = tx_block_pool_create(&pool_1, "pool 0", 100, pointer, 100); + if (status != TX_SIZE_ERROR) + { + + printf("Running Block Memory Error Detection Test........................... ERROR #3\n"); + test_control_return(1); + } + + /* Attempt of allocate block with NULL dest. */ + status = tx_block_allocate(&pool_0, (VOID **) TX_NULL, TX_NO_WAIT); + if (status != TX_PTR_ERROR) + { + + printf("Running Block Memory Error Detection Test........................... ERROR #4\n"); + test_control_return(1); + } + + /* Delete null pointer. */ + status = tx_block_pool_delete(TX_NULL); + if (status != TX_POOL_ERROR) + { + + printf("Running Block Memory Error Detection Test........................... ERROR #5\n"); + test_control_return(1); + } + +#endif /* TX_DISABLE_ERROR_CHECKING */ +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING +UINT status; +CHAR *pointer_1; +CHAR *pointer_2; +CHAR *pointer_3; +CHAR *pointer_4; +INT i; +#endif + + /* Inform user. */ + printf("Running Block Memory Error Detection Test........................... "); + +#ifndef TX_DISABLE_ERROR_CHECKING /* skip this test and pretend it passed */ + + status = tx_block_pool_create(&pool_1, "pool 1", 100, pointer, 320); + pointer = pointer + 320; + + /* Attempt to create a pool with an invalid size. */ + status = _txe_block_pool_create(&pool_2, "pool 2", 100, pointer, 320, 777777); + if (status != TX_POOL_ERROR) + { + + /* Error! */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Allocate with a NULL destination pointer. */ + status = tx_block_allocate(&pool_0, (VOID **) TX_NULL, TX_NO_WAIT); + if (status != TX_PTR_ERROR) + { + + /* Error! */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Allocate with a NULL pool pointer. */ + status = tx_block_allocate(TX_NULL, (VOID **) TX_NULL, TX_NO_WAIT); + if (status != TX_POOL_ERROR) + { + + /* Error! */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Allocate with bad pool pointer. */ + pool_2.tx_block_pool_id = 0; + status = tx_block_allocate(&pool_2, (VOID **) TX_NULL, TX_NO_WAIT); + if (status != TX_POOL_ERROR) + { + + /* Error! */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Release bad pool ptr. */ + status = tx_block_release(TX_NULL); + if (status != TX_PTR_ERROR) + { + + /* Error! */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Allocate first block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_1, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Error! */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_1, (CHAR) 0xEF, 100); + + /* Allocate second block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_2, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Error! */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_2, (CHAR) 0xEF, 100); + + /* Allocate third block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_3, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Error! */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_3, (CHAR) 0xEF, 100); + + /* Attempt to allocate fourth block from the pool. This should fail because + there should be no more blocks in the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_4, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_MEMORY) + { + + /* Error! */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Set the memory of all of the allocated blocks. */ + for (i =0; i < 100; i++) + { + pointer_1[i] = (CHAR) 0xFF; + pointer_2[i] = (CHAR) 0xFF; + pointer_3[i] = (CHAR) 0xFF; + } + + /* Now release each of the blocks. */ + status = tx_block_release(pointer_1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Error! */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Release the second block. */ + status = tx_block_release(pointer_2); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Error! */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Release the third block. */ + status = tx_block_release(pointer_3); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Error! */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Allocate each block again to make sure everything still + works. The block addresses should come out in reverse + order, because a released block is placed at the head of + the list. */ + + /* Allocate first block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_1, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Error! */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_1, (CHAR) 0xEF, 100); + + /* Allocate second block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_2, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Error! */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_2, (CHAR) 0xEF, 100); + + /* Allocate third block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_3, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Error! */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_3, (CHAR) 0xEF, 100); + + /* Attempt to allocate fourth block from the pool. This should fail because + there should be no more blocks in the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_4, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_MEMORY) + { + + /* Error! */ + printf("ERROR #21\n"); + test_control_return(1); + } + + /* Delete both block pools. */ + status = tx_block_pool_delete(&pool_0); + if (status != TX_SUCCESS) + { + + /* Error! */ + printf("ERROR #22\n"); + test_control_return(1); + } + + status = tx_block_pool_delete(&pool_1); + if (status != TX_SUCCESS) + { + + /* Error! */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Attempt to delete again. */ + status = tx_block_pool_delete(&pool_1); + if (status != TX_POOL_ERROR) + { + + /* Error! */ + printf("ERROR #24\n"); + test_control_return(1); + } + + thread_0_counter++; + +#endif /* TX_DISABLE_ERROR_CHECKING */ + + /* All is good! */ + printf("SUCCESS!\n"); + test_control_return(0); +} + diff --git a/test/tx/regression/threadx_block_memory_information_test.c b/test/tx/regression/threadx_block_memory_information_test.c new file mode 100644 index 00000000..d6416bc2 --- /dev/null +++ b/test/tx/regression/threadx_block_memory_information_test.c @@ -0,0 +1,713 @@ +/* This test is designed to test block memory information services. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_block_pool.h" + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +/* Define the external reference for the preempt disable flag. */ + +extern volatile UINT _tx_thread_preempt_disable; + + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + +static unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; + +static unsigned long thread_5_counter = 0; +static TX_THREAD thread_5; + +static unsigned long thread_6_counter = 0; +static TX_THREAD thread_6; + +static TX_BLOCK_POOL block_pool_0; +static TX_BLOCK_POOL block_pool_2; +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO +static TX_BLOCK_POOL block_pool_1; +#endif + +static int test_status; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +static void thread_5_entry(ULONG thread_input); +static void thread_6_entry(ULONG thread_input); + +/* Direct core function to bypass the error checking shell. */ +UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, + ULONG *total_blocks, TX_THREAD **first_suspended, + ULONG *suspended_count, TX_BLOCK_POOL **next_pool); + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + + /* Determine if the test case we are looking for is present. */ + if ((_tx_thread_preempt_disable) && (test_status == 1)) + { + + /* Abort the wait of thread 3. */ + tx_thread_wait_abort(&thread_3); + + /* End the ISR processing. */ + test_status = 2; + test_isr_dispatch = TX_NULL; + } +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_block_memory_information_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Information Test............................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Information Test............................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Information Test............................... ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 3, 3, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Information Test............................... ERROR #4\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 4, 4, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Information Test............................... ERROR #5\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, + pointer, TEST_STACK_SIZE_PRINTF, + 5, 5, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Information Test............................... ERROR #6\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_6, "thread 6", thread_6_entry, 6, + pointer, TEST_STACK_SIZE_PRINTF, + 6, 6, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Information Test............................... ERROR #7\n"); + test_control_return(1); + } + + /* Create the block_pool with one block. */ + status = tx_block_pool_create(&block_pool_0, "block_pool 0", 30, pointer, 40); + pointer = pointer + 40; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Information Test............................... ERROR #8\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; +CHAR *name; +ULONG available; +ULONG total_blocks; +TX_THREAD *first_suspended; +ULONG suspended_count; +TX_BLOCK_POOL *next_pool; +ULONG allocates; +ULONG releases; +ULONG suspensions; +ULONG timeouts; + + + /* Inform user. */ + printf("Running Block Memory Information Test............................... "); + + /* Allocate the one block. */ + tx_block_allocate(&block_pool_0, &pointer, TX_NO_WAIT); + + /* Nothing to do here, but check prioritization with no suspended threads. */ + status = tx_block_pool_prioritize(&block_pool_0); + + /* Check for an error condition. */ + if (status != TX_SUCCESS) + { + + /* Block Pool error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Get both threads suspended. */ + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + + /* Increment the thread counter. */ + thread_0_counter++; + + /* Make sure thread 1 and 2 are suspended on the block_pool. */ + if ((thread_1.tx_thread_state != TX_BLOCK_MEMORY) || (thread_2.tx_thread_state != TX_BLOCK_MEMORY) || + (block_pool_0.tx_block_pool_suspension_list != &thread_1)) + { + + /* Block Pool error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Prioritize the block pool suspension list. */ + status = tx_block_pool_prioritize(&block_pool_0); + + /* Check status and make sure thread 1 is terminated. */ + if ((status != TX_SUCCESS) || (block_pool_0.tx_block_pool_suspension_list != &thread_2)) + { + + /* Block Pool error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* At this point we are going to get more than 2 threads suspended. */ + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + tx_thread_resume(&thread_3); + tx_thread_resume(&thread_4); + tx_thread_resume(&thread_5); + tx_thread_resume(&thread_6); + + /* Prioritize the block pool suspension list. */ + status = tx_block_pool_prioritize(&block_pool_0); + + /* Check status and make sure thread 3 is at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (block_pool_0.tx_block_pool_suspension_list != &thread_3)) + { + + /* Block Pool error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Now loop to test the interrupt of the prioritize loop logic. */ + test_status = 1; + test_isr_dispatch = test_isr; + do + { + + /* Prioritize the block pool suspension list. */ + status = tx_block_pool_prioritize(&block_pool_0); + + /* Check status and make sure thread 1 is terminated. */ + if (status != TX_SUCCESS) + { + + /* Block Pool error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + } while (test_status == 1); + + /* Now determine if thread 4 is at the front of the list... It should be! */ + if (block_pool_0.tx_block_pool_suspension_list != &thread_4) + { + + /* Block Pool error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Test the NULL pointer on the info get call. */ + status = tx_block_pool_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for the proper error code. */ + if (status != TX_POOL_ERROR) + { + + /* Block Pool error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Test the non-thread pointer on the info get call. */ + block_pool_2.tx_block_pool_id = 0; + status = tx_block_pool_info_get(&block_pool_2, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for the proper error code. */ + if (status != TX_POOL_ERROR) + { + + /* Block Pool error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + +#endif + + /* Now use the information services in order to test them. */ + status = tx_block_pool_info_get(&block_pool_0, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_block_pool_info_get(&block_pool_0, &name, &available, &total_blocks, &first_suspended, &suspended_count, &next_pool); + + /* Check for an error condition. */ + if ((status) || (available != block_pool_0.tx_block_pool_available) || (total_blocks != block_pool_0.tx_block_pool_total) || + (first_suspended != &thread_4) || (suspended_count != block_pool_0.tx_block_pool_suspended_count) || (next_pool != &block_pool_0)) + { + + /* Block Pool error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO + + /* Call the core block pool info get function with a NULL pointer. */ + status = _tx_block_pool_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for the proper error code. */ + if (status != TX_PTR_ERROR) + { + + /* Block Pool error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Call the core block pool info get function with a non-initialized pool. */ + status = _tx_block_pool_performance_info_get(&block_pool_1, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for the proper error code. */ + if (status != TX_PTR_ERROR) + { + + /* Block Pool error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Now get the pool performance information. */ + status = tx_block_pool_performance_info_get(&block_pool_0, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_block_pool_performance_info_get(&block_pool_0, &allocates, &releases, &suspensions, &timeouts); + + /* Check for an error condition. */ + if ((status) || (allocates != block_pool_0.tx_block_pool_performance_allocate_count) || + (releases != block_pool_0.tx_block_pool_performance_release_count) || + (suspensions != block_pool_0.tx_block_pool_performance_suspension_count) || + (timeouts != block_pool_0.tx_block_pool_performance_timeout_count)) + { + + /* Block Pool error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Now get the system pool performance information. */ + status = tx_block_pool_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_block_pool_performance_system_info_get(&allocates, &releases, &suspensions, &timeouts); + + /* Check for an error condition. */ + if ((status) || (allocates != _tx_block_pool_performance_allocate_count) || (releases != _tx_block_pool_performance_release_count) || + (suspensions != _tx_block_pool_performance_suspension_count) || (timeouts != _tx_block_pool_performance_timeout_count)) + { + + /* Block Pool error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +#else + + /* Call the block pool performance info get function. */ + status = tx_block_pool_performance_info_get(&block_pool_0, &allocates, &releases, &suspensions, &timeouts); + + /* Check for the proper error code. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Block Pool error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + /* Call the block pool performance info get function. */ + status = tx_block_pool_performance_info_get(TX_NULL, &allocates, &releases, &suspensions, &timeouts); + + /* Check for the proper error code. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Block Pool error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Call the block pool performance info get function. */ + status = tx_block_pool_performance_info_get(TX_NULL, TX_NULL, &releases, &suspensions, &timeouts); + + /* Check for the proper error code. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Block Pool error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Call the block pool performance info get function. */ + status = tx_block_pool_performance_info_get(TX_NULL, TX_NULL, TX_NULL, &suspensions, &timeouts); + + /* Check for the proper error code. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Block Pool error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + + /* Call the block pool performance info get function. */ + status = tx_block_pool_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, &timeouts); + + /* Check for the proper error code. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Block Pool error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + /* Call the block pool performance info get function. */ + status = tx_block_pool_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for the proper error code. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Block Pool error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Now get the system pool performance information. */ + status = tx_block_pool_performance_system_info_get(&allocates, &releases, &suspensions, &timeouts); + + /* Check for the proper error code. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Block Pool error. */ + printf("ERROR #28\n"); + test_control_return(1); + } + + /* Now get the system pool performance information. */ + status = tx_block_pool_performance_system_info_get(TX_NULL, &releases, &suspensions, &timeouts); + + /* Check for the proper error code. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Block Pool error. */ + printf("ERROR #29\n"); + test_control_return(1); + } + + /* Now get the system pool performance information. */ + status = tx_block_pool_performance_system_info_get(TX_NULL, TX_NULL, &suspensions, &timeouts); + + /* Check for the proper error code. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Block Pool error. */ + printf("ERROR #30\n"); + test_control_return(1); + } + + /* Now get the system pool performance information. */ + status = tx_block_pool_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, &timeouts); + + /* Check for the proper error code. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Block Pool error. */ + printf("ERROR #31\n"); + test_control_return(1); + } + + /* Now get the system pool performance information. */ + status = tx_block_pool_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for the proper error code. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Block Pool error. */ + printf("ERROR #32\n"); + test_control_return(1); + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +#endif +} + + +static void thread_1_entry(ULONG thread_input) +{ +UINT status; +VOID *pointer; + + /* Loop forever! */ + while(1) + { + + + /* Get block from pool. */ + status = tx_block_allocate(&block_pool_0, &pointer, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get block from pool. */ + status = tx_block_allocate(&block_pool_0, &pointer, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_2_counter++; + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get block from pool. */ + status = tx_block_allocate(&block_pool_0, &pointer, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_3_counter++; + } +} + + +static void thread_4_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get block from pool. */ + status = tx_block_allocate(&block_pool_0, &pointer, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_4_counter++; + } +} + + +static void thread_5_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get block from pool. */ + status = tx_block_allocate(&block_pool_0, &pointer, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_5_counter++; + } +} + + +static void thread_6_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get block from pool. */ + status = tx_block_allocate(&block_pool_0, &pointer, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_6_counter++; + } +} + diff --git a/test/tx/regression/threadx_block_memory_prioritize_test.c b/test/tx/regression/threadx_block_memory_prioritize_test.c new file mode 100644 index 00000000..274daa01 --- /dev/null +++ b/test/tx/regression/threadx_block_memory_prioritize_test.c @@ -0,0 +1,500 @@ +/* This test is designed to test block memory pool prioritize. */ + +#include <stdio.h> +#include "tx_api.h" + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +/* Define the external reference for the preempt disable flag. */ + +extern volatile UINT _tx_thread_preempt_disable; + + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + +static unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; + +static unsigned long thread_5_counter = 0; +static TX_THREAD thread_5; + +static unsigned long thread_6_counter = 0; +static TX_THREAD thread_6; + +static TX_BLOCK_POOL block_pool_0; +static TX_BLOCK_POOL block_pool_1; + + +static int test_status; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +static void thread_5_entry(ULONG thread_input); +static void thread_6_entry(ULONG thread_input); + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + + /* Determine if the test case we are looking for is present. */ + if ((_tx_thread_preempt_disable) && (test_status == 1)) + { + + /* Determine if thread 3 is at the front of the suspension list. */ + if (block_pool_0.tx_block_pool_suspension_list == &thread_3) + { + + /* Abort the wait of thread 3. */ + tx_thread_wait_abort(&thread_3); + } + else + { + + /* Abort the wait of thread 5. */ + tx_thread_wait_abort(&thread_5); + + /* End the ISR processing. */ + test_status = 2; + test_isr_dispatch = TX_NULL; + } + } +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_block_memory_prioritize_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Prioritize Test................................ ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Prioritize Test................................ ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Prioritize Test................................ ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 3, 3, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Prioritize Test................................ ERROR #4\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 4, 4, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Prioritize Test................................ ERROR #5\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, + pointer, TEST_STACK_SIZE_PRINTF, + 5, 5, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Prioritize Test................................ ERROR #6\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_6, "thread 6", thread_6_entry, 6, + pointer, TEST_STACK_SIZE_PRINTF, + 6, 6, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Prioritize Test................................ ERROR #7\n"); + test_control_return(1); + } + + /* Create the block_pool with one block. */ + status = tx_block_pool_create(&block_pool_0, "block_pool 0", 30, pointer, 40); + pointer = pointer + 40; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Prioritize Test................................ ERROR #8\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Inform user. */ + printf("Running Block Memory Prioritize Test................................ "); + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to prioritize with a NULL pointer. */ + status = tx_block_pool_prioritize(TX_NULL); + + /* Check for an error condition. */ + if (status != TX_POOL_ERROR) + { + + /* Block Pool error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to prioritize with a bad pool pointer. */ + block_pool_1.tx_block_pool_id = 0; + status = tx_block_pool_prioritize(&block_pool_1); + + /* Check for an error condition. */ + if (status != TX_POOL_ERROR) + { + + /* Block Pool error. */ + printf("ERROR #10\n"); + test_control_return(1); + } +#endif + + /* Allocate the one block. */ + tx_block_allocate(&block_pool_0, &pointer, TX_NO_WAIT); + + /* Nothing to do here, but check prioritization with no suspended threads. */ + status = tx_block_pool_prioritize(&block_pool_0); + + /* Check for an error condition. */ + if (status != TX_SUCCESS) + { + + /* Block Pool error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Get both threads suspended. */ + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + + /* Increment the thread counter. */ + thread_0_counter++; + + /* Make sure thread 1 and 2 are suspended on the block_pool. */ + if ((thread_1.tx_thread_state != TX_BLOCK_MEMORY) || (thread_2.tx_thread_state != TX_BLOCK_MEMORY) || + (block_pool_0.tx_block_pool_suspension_list != &thread_1)) + { + + /* Block Pool error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Prioritize the block pool suspension list. */ + status = tx_block_pool_prioritize(&block_pool_0); + + /* Check status and make sure thread 2 is at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (block_pool_0.tx_block_pool_suspension_list != &thread_2)) + { + + /* Block Pool error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Call block pool prioritize again to test the don't-do-anything path in tx_block_pool_prioritize. */ + status += tx_block_pool_prioritize(&block_pool_0); + + /* At this point we are going to get more than 2 threads suspended. */ + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + tx_thread_resume(&thread_3); + tx_thread_resume(&thread_4); + tx_thread_resume(&thread_5); + tx_thread_resume(&thread_6); + + /* Prioritize the block pool suspension list. */ + status = tx_block_pool_prioritize(&block_pool_0); + + /* Check status and make sure thread 3 is at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (block_pool_0.tx_block_pool_suspension_list != &thread_3)) + { + + /* Block Pool error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Now loop to test the interrupt of the prioritize loop logic. */ + test_status = 1; + test_isr_dispatch = test_isr; + do + { + + /* Prioritize the block pool suspension list. */ + status = tx_block_pool_prioritize(&block_pool_0); + + /* Check status and make sure thread 1 is terminated. */ + if (status != TX_SUCCESS) + { + + /* Block Pool error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + } while (test_status == 1); + + /* Now determine if thread 4 is at the front of the list... It should be! */ + if (block_pool_0.tx_block_pool_suspension_list != &thread_4) + { + + /* Block Pool error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ +UINT status; +VOID *pointer; + + /* Loop forever! */ + while(1) + { + + + /* Get block from pool. */ + status = tx_block_allocate(&block_pool_0, &pointer, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get block from pool. */ + status = tx_block_allocate(&block_pool_0, &pointer, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_2_counter++; + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get block from pool. */ + status = tx_block_allocate(&block_pool_0, &pointer, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_3_counter++; + } +} + + +static void thread_4_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get block from pool. */ + status = tx_block_allocate(&block_pool_0, &pointer, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_4_counter++; + } +} + + +static void thread_5_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get block from pool. */ + status = tx_block_allocate(&block_pool_0, &pointer, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_5_counter++; + } +} + + +static void thread_6_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get block from pool. */ + status = tx_block_allocate(&block_pool_0, &pointer, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_6_counter++; + } +} diff --git a/test/tx/regression/threadx_block_memory_suspension_test.c b/test/tx/regression/threadx_block_memory_suspension_test.c new file mode 100644 index 00000000..6f2d635c --- /dev/null +++ b/test/tx/regression/threadx_block_memory_suspension_test.c @@ -0,0 +1,311 @@ +/* This test is designed to test suspension on memory block pools. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static TX_BLOCK_POOL pool_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_block_memory_suspension_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Suspension Test................................ ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Suspension Test................................ ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Suspension Test................................ ERROR #3\n"); + test_control_return(1); + } + + /* Create block pool. */ + status = tx_block_pool_create(&pool_0, "pool 0", 100, pointer, 320); + pointer = pointer + 320; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Suspension Test................................ ERROR #4\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer_1; +CHAR *pointer_2; +CHAR *pointer_3; + + + /* Inform user. */ + printf("Running Block Memory Suspension Test................................ "); + + /* Increment the run counter. */ + thread_0_counter++; + + /* Allocate all blocks from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_1, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_1, (CHAR) 0xEF, 100); + + status = tx_block_allocate(&pool_0, (VOID **) &pointer_2, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_2, (CHAR) 0xEF, 100); + + /* Get the last block. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_3, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_3, (CHAR) 0xEF, 100); + + /* Let the other thread suspend on the pool. */ + tx_thread_relinquish(); + + /* Now release the block to lift the suspension on the other thread. */ + status = tx_block_release(pointer_3); + + /* Check status and run counter. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 0)) + { + + /* Block memory error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Let the other thread run again. */ + tx_thread_relinquish(); + + /* Check the run counter of the other thread. */ + if (thread_1_counter != 1) + { + + /* Block memory error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* At this point the other thread has run and there is one block free. */ + + /* Get the last block again. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_3, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_3, (CHAR) 0xEF, 100); + + /* Resume the second thread. */ + tx_thread_resume(&thread_2); + + /* Let both threads suspend on the block pool via relinquish. */ + tx_thread_relinquish(); + + /* Now release the block. */ + status = tx_block_release(pointer_3); + + /* Check status and run counter. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 0)) + { + + /* Block memory error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Let thread 1 release the block. */ + tx_thread_relinquish(); + + /* Let thread 2 get the block and release the block. */ + tx_thread_relinquish(); + + /* Check status and run counter. */ + if ((thread_1_counter != 3) || (thread_2_counter != 1)) + { + + /* Block memory error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + else + { + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer_1; + + + /* Attempt to get a block from the pool. */ + while(1) + { + + /* Allocate a block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_1, TX_WAIT_FOREVER); + + /* Determine if the allocate was successful. */ + if (status != TX_SUCCESS) + return; + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_1, (CHAR) 0xEF, 100); + + /* Increment the thread counter. */ + thread_1_counter++; + + /* Release the block. */ + tx_block_release(pointer_1); + + /* Switch back to other thread. */ + tx_thread_relinquish(); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer_1; + + + /* Attempt to get a block from the pool. */ + while(1) + { + + /* Allocate a block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_1, TX_WAIT_FOREVER); + + /* Determine if the allocate was successful. */ + if (status != TX_SUCCESS) + return; + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_1, (CHAR) 0xEF, 100); + + /* Increment the thread counter. */ + thread_2_counter++; + + /* Release the block. */ + tx_block_release(pointer_1); + + /* Switch back to other thread. */ + tx_thread_relinquish(); + } +} + + diff --git a/test/tx/regression/threadx_block_memory_suspension_timeout_test.c b/test/tx/regression/threadx_block_memory_suspension_timeout_test.c new file mode 100644 index 00000000..f290f01a --- /dev/null +++ b/test/tx/regression/threadx_block_memory_suspension_timeout_test.c @@ -0,0 +1,212 @@ +/* This test is designed to test timeouts on suspension on memory block pools. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + + +static TX_BLOCK_POOL pool_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_block_memory_suspension_timeout_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Suspension Timeout Test........................ ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Suspension Timeout Test........................ ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Suspension Timeout Test........................ ERROR #3\n"); + test_control_return(1); + } + + /* Create block pool. */ + status = tx_block_pool_create(&pool_0, "pool 0", 100, pointer, 320); + pointer = pointer + 320; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Suspension Timeout Test........................ ERROR #4\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer_1; +CHAR *pointer_2; +CHAR *pointer_3; + + + /* Inform user. */ + printf("Running Block Memory Suspension Timeout Test........................ "); + + /* Allocate all blocks from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_1, TX_NO_WAIT); + status += tx_block_allocate(&pool_0, (VOID **) &pointer_2, TX_NO_WAIT); + status += tx_block_allocate(&pool_0, (VOID **) &pointer_3, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_1, (CHAR) 0xEF, 100); + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_2, (CHAR) 0xEF, 100); + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_3, (CHAR) 0xEF, 100); + + /* Sleep for 64 ticks to allow the other thread 6 timeouts on the block + pool. */ + tx_thread_sleep(64); + + /* Incrment the run counter. */ + thread_0_counter++; + + /* Check the counter of the other thread. */ + if ((thread_1_counter != 6) || (thread_2_counter != 3)) + { + + /* Block memory error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer_1; + + + /* Attempt to get a block from the pool. */ + while(1) + { + + /* Allocate a block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_1, 10); + + /* Determine if the allocate was successful. */ + if (status != TX_NO_MEMORY) + return; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer_1; + + + /* Delay so we get some single suspension timeouts as well. */ + tx_thread_sleep(32); + + /* Attempt to get a block from the pool. */ + while(1) + { + + /* Allocate a block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_1, 10); + + /* Determine if the allocate was successful. */ + if (status != TX_NO_MEMORY) + return; + + /* Increment the thread counter. */ + thread_2_counter++; + } +} + diff --git a/test/tx/regression/threadx_block_memory_thread_terminate_test.c b/test/tx/regression/threadx_block_memory_thread_terminate_test.c new file mode 100644 index 00000000..c9221af9 --- /dev/null +++ b/test/tx/regression/threadx_block_memory_thread_terminate_test.c @@ -0,0 +1,185 @@ +/* This test is designed to test thread termination on a thread suspended on a block + memory pool. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + + +static TX_BLOCK_POOL pool_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_block_memory_thread_terminate_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Thread Terminate Test.......................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Thread Terminate Test.......................... ERROR #2\n"); + test_control_return(1); + } + + /* Create block pool. */ + status = tx_block_pool_create(&pool_0, "pool 0", 100, pointer, 320); + pointer = pointer + 320; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Block Memory Thread Terminate Test.......................... ERROR #3\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer_1; +CHAR *pointer_2; +CHAR *pointer_3; + + + /* Inform user. */ + printf("Running Block Memory Thread Terminate Test.......................... "); + + /* Allocate all blocks from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_1, TX_NO_WAIT); + status += tx_block_allocate(&pool_0, (VOID **) &pointer_2, TX_NO_WAIT); + status += tx_block_allocate(&pool_0, (VOID **) &pointer_3, TX_NO_WAIT); + + /* Increment the run counter. */ + thread_0_counter++; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Block memory error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_1, (CHAR) 0xEF, 100); + TX_MEMSET(pointer_2, (CHAR) 0xEF, 100); + TX_MEMSET(pointer_3, (CHAR) 0xEF, 100); + + + /* Let other thread suspend on block pool. */ + tx_thread_relinquish(); + + /* Terminate the other thread. */ + status = tx_thread_terminate(&thread_1); + + /* Check status. */ + if ((status != TX_SUCCESS) || (thread_1.tx_thread_state != TX_TERMINATED) || + (thread_1_counter != 0)) + { + + /* Block memory error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Release all the blocks. */ + status = tx_block_release(pointer_1); + status += tx_block_release(pointer_2); + status += tx_block_release(pointer_3); + + /* Check status. */ + if ((status != TX_SUCCESS) || (thread_1.tx_thread_state != TX_TERMINATED) || + (thread_1_counter != 0)) + { + + /* Block memory error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer_1; + + + /* Attempt to get a block from the pool. */ + while(1) + { + + /* Allocate a block from the pool. */ + status = tx_block_allocate(&pool_0, (VOID **) &pointer_1, 10); + + /* Determine if the allocate was successful. */ + if (status != TX_NO_MEMORY) + return; + + /* Set all the memory of the blocks. */ + TX_MEMSET(pointer_1, (CHAR) 0xEF, 100); + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + diff --git a/test/tx/regression/threadx_byte_memory_basic_test.c b/test/tx/regression/threadx_byte_memory_basic_test.c new file mode 100644 index 00000000..9fffc840 --- /dev/null +++ b/test/tx/regression/threadx_byte_memory_basic_test.c @@ -0,0 +1,1064 @@ +/* This test is designed to test simple memory byte pool creation, deletion, and + allocates and releases. */ + +#include <stdio.h> +#include "tx_api.h" + +typedef struct BYTE_MEMORY_TEST_STRUCT +{ + ULONG first; + ULONG second; + TX_BYTE_POOL pool; + ULONG first_middle; + ULONG second_middle; + ULONG pool_area[2048/sizeof(ULONG)]; + ULONG next_to_last; + ULONG last; + +} BYTE_MEMORY_TEST; + +static BYTE_MEMORY_TEST byte_memory; + + +/* Define external reference to byte pool creation status. */ + +extern UINT test_byte_pool_create_init; + + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + +UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, + ULONG pool_size, UINT pool_control_block_size); + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + + +static TX_BYTE_POOL pool_0; +static TX_BYTE_POOL pool_1; +static TX_BYTE_POOL pool_2; +static TX_BYTE_POOL pool_3; + +static TX_BYTE_POOL pool_4; +static UCHAR *search_ptr_1; +static UCHAR *block_0; +static UCHAR *block_1; +static UCHAR *block_2; +static UCHAR *block_3; +static UCHAR *block_4; +static CHAR *pool_4_memory; +static TX_TIMER timer_0; + + +static unsigned long error = 0; +static unsigned long timer_executed = 0; +static unsigned long isr_executed = 0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +UINT _tx_byte_release(VOID *memory_ptr); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define the timer for this test. */ + +static void timer_entry(ULONG i) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +UINT status; +CHAR *pointer; + + + /* Determine if calling byte pool create from initialization was successful. */ + if (test_byte_pool_create_init != TX_SUCCESS) + { + + /* Error! */ + error++; + } + + /* Attempt to create a byte pool from a timer. */ + pointer = (CHAR *) 0x30000; + status = tx_byte_pool_create(&pool_2, "pool 2", pointer, 108); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to create a byte pool with an invalid size. */ + status = _txe_byte_pool_create(&pool_3, "pool 3", pointer, + 108, (sizeof(TX_BYTE_POOL)+1)); + + /* Check status. */ + if (status != TX_POOL_ERROR) + { + + /* Error! */ + error++; + } + + /* Allocate memory from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Try to delete a byte pool from a timer. */ + status = tx_byte_pool_delete(&pool_0); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to release byte memory from timer. */ + pointer = (CHAR *) 0x30000; + status = tx_byte_release(pointer); + + /* Check for error status! */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + timer_executed = 1; +#endif +} + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +CHAR *pointer; +UINT status; + + + /* Allocate memory from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 24, 100); + + /* Check status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + /* Allocate memory from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + + /* Attempt to create a byte pool from an ISR. */ + status = tx_byte_pool_create(&pool_2, "pool 0", (void *) 0x100000, 108); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to deleate a pool from an ISR. */ + status = tx_byte_pool_delete(&pool_0); + + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to release byte memory from ISR. */ + pointer = (CHAR *) 0x30000; + status = tx_byte_release(pointer); + + /* Check for error status! */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + isr_executed = 1; +#endif +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_byte_memory_basic_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Basic Test...................................... ERROR #1\n"); + test_control_return(1); + } + + /* Create byte pools 0 and 1. */ + status = tx_byte_pool_create(&pool_0, "pool 0", pointer, 108); + pointer = pointer + 108; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Basic Test...................................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_byte_pool_create(&pool_1, "pool 1", pointer, 200); + pointer = pointer + 200; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Basic Test...................................... ERROR #3\n"); + test_control_return(1); + } + + /* Test for search pointer issue on wrapped seach with prior block to search pointer merged. */ + status = tx_byte_pool_create(&pool_4, "pool 4", pointer, 300); + pool_4_memory = pointer; + pointer = pointer + 300; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Basic Test...................................... ERROR #3a\n"); + test_control_return(1); + } + + /* Allocate first block. */ + status += tx_byte_allocate(&pool_4, (VOID **) &block_0, 80, TX_NO_WAIT); + + /* Save next search pointer. */ + search_ptr_1 = pool_4.tx_byte_pool_search; + + /* Clear the allocatged memory. */ + TX_MEMSET(block_0, 0, 80); + + /* Allocate another block. */ + status += tx_byte_allocate(&pool_4, (VOID **) &block_1, 80, TX_NO_WAIT); + + /* Clear the allocated block. */ + TX_MEMSET(block_1, 0, 80); + + /* Allocate the third and final block. */ + status += tx_byte_allocate(&pool_4, (VOID **) &block_2, 80, TX_NO_WAIT); + + /* Clear the allocated block. */ + TX_MEMSET(block_2, 0, 80); + + /* Release the first block. */ + status += tx_byte_release(block_0); + + /* Release the second block. */ + status += tx_byte_release(block_1); + + /* Manually move the search pointer to create the case where the search wraps and a merge happens on the search pointer + necessitating its update. */ + pool_4.tx_byte_pool_search = search_ptr_1; /* Point to the middle block. */ + + /* Allocate a larger block that will wrap the search and require moving as well as an update of the search pointer. */ + status += tx_byte_allocate(&pool_4, (VOID **) &block_3, 120, TX_NO_WAIT); + + /* Clear the newly allocated block. */ + TX_MEMSET(block_3, 0, 120); + + /* At this point, verify the search pointer was properly updated in the previous allocation. */ + status += tx_byte_allocate(&pool_4, (VOID **) &block_4, 40, TX_NO_WAIT); /* Should fail since search pointer is now invalid! */ + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Basic Test...................................... ERROR #3b\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer_1; +CHAR *pointer_2; +CHAR *pointer_3; +CHAR *pointer_4; +INT i; +ULONG array[20]; +UCHAR *save_search; + + + /* Inform user. */ + printf("Running Byte Memory Basic Test...................................... "); + + /* Perform byte memory test. */ + byte_memory.first = 0x11223344; + byte_memory.second = 0x55667788; + byte_memory.first_middle = 0x21314151; + byte_memory.second_middle= 0x61718191; + byte_memory.next_to_last = 0x99aabbcc; + byte_memory.last = 0xddeeff00; + + /* Create the byte pool. */ + status = tx_byte_pool_create(&byte_memory.pool, "pool memory", &byte_memory.pool_area[0], (2048*sizeof(ULONG))/sizeof(ULONG)); + tx_byte_pool_delete(&byte_memory.pool); + + /* Check for status. */ + if ((status != TX_SUCCESS) || + (byte_memory.first != 0x11223344) || + (byte_memory.second != 0x55667788) || + (byte_memory.first_middle != 0x21314151) || + (byte_memory.second_middle != 0x61718191) || + (byte_memory.next_to_last != 0x99aabbcc) || + (byte_memory.last != 0xddeeff00)) + { + + /* Byte memory error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Increment the run counter. */ + thread_0_counter++; + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Try to create a NULL pool. */ + pointer_1 = (CHAR *) 0x30000; + status = tx_byte_pool_create(TX_NULL, "pool 0", pointer_1, 108); + + /* Check status. */ + if (status != TX_POOL_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Try to create the same pool. */ + status = tx_byte_pool_create(&pool_0, "pool 0", pointer_1, 108); + + /* Check status. */ + if (status != TX_POOL_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Try to create a pool with a NULL start address. */ + status = tx_byte_pool_create(&pool_2, "pool 2", TX_NULL, 108); + + /* Check status. */ + if (status != TX_PTR_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Try to create a pool with a a bad size. */ + status = tx_byte_pool_create(&pool_2, "pool 2", pointer_1, 1); + + /* Check status. */ + if (status != TX_SIZE_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Try to delete a byte pool with a NULL pointer. */ + status = tx_byte_pool_delete(TX_NULL); + + /* Check status. */ + if (status != TX_POOL_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Try to delete a byte pool that hasn't been created. */ + pool_2.tx_byte_pool_id = 0; + status = tx_byte_pool_delete(&pool_2); + + /* Check status. */ + if (status != TX_POOL_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Test NULL pool pointer. */ + status = tx_byte_allocate(TX_NULL, (VOID **) &pointer_1, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_POOL_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Test non-created pool pointer. */ + pool_2.tx_byte_pool_id = 0; + status = tx_byte_allocate(&pool_2, (VOID **) &pointer_1, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_POOL_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Test NULL memory pointer. */ + status = tx_byte_allocate(&pool_0, (VOID **) TX_NULL, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_PTR_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Test extreme size. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_1, 240000, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SIZE_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Test size of 0. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_1, 0, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SIZE_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #15\n"); + test_control_return(1); + } +#endif + + /* Test NULL pointer release. */ + status = tx_byte_release(TX_NULL); + + /* Check for error status! */ + if (status != TX_PTR_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Allocate memory from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_1, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Allocate memory from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_2, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Allocate memory from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_3, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Attempt to allocate fourth area from the pool. This should fail because + there should be not enough bytes in the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_4, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_MEMORY) + { + + /* Byte memory error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Set the memory of all of the allocated memory. */ + for (i =0; i < 24; i++) + { + pointer_1[i] = (CHAR) 0xFF; + pointer_2[i] = (CHAR) 0xFF; + pointer_3[i] = (CHAR) 0xFF; + } + + /* Test the byte release with a bad block pointer. */ + status = _tx_byte_release(TX_NULL); + + /* Check for error status! */ + if (status != TX_PTR_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + /* Test another bad block release... no pool pointer! */ + array[0] = 0; + array[1] = 0; + array[2] = 0; + status = _tx_byte_release(&array[2]); + + /* Check for error status! */ + if (status != TX_PTR_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + /* Test another bad block release.... pool pointer is not a valid pool! */ + array[0] = 0; + array[1] = (ULONG) &array[3]; + array[2] = 0; + array[3] = 0; + status = _tx_byte_release(&array[2]); + + /* Check for error status! */ + if (status != TX_PTR_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + /* Now release each of the blocks. */ + status = tx_byte_release(pointer_1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Now release the same block again. */ + status = tx_byte_release(pointer_1); + + /* Check for status. */ + if (status != TX_PTR_ERROR) + { + + /* Byte memory error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Release the second memory area. */ + status = tx_byte_release(pointer_2); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + + /* Release the third memory area. */ + status = tx_byte_release(pointer_3); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + /* Allocate each block again to make sure everything still + works. */ + + /* Allocate memory from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_1, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Allocate second memory area from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_2, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #28\n"); + test_control_return(1); + } + + /* Allocate third memory area from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_3, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #29\n"); + test_control_return(1); + } + + /* Attempt to allocate fourth memory area from the pool. This should fail because + there should be not enough bytes in the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_4, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_MEMORY) + { + + /* Byte memory error. */ + printf("ERROR #30\n"); + test_control_return(1); + } + + /* Now release each of the blocks. */ + status = tx_byte_release(pointer_1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #31\n"); + test_control_return(1); + } + + /* Release the second memory area. */ + status = tx_byte_release(pointer_2); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #32\n"); + test_control_return(1); + } + + /* Release the third memory area. */ + status = tx_byte_release(pointer_3); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #33\n"); + test_control_return(1); + } + + /* Now allocate a block that should cause all of the blocks to merge + together. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_3, 88, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #34\n"); + test_control_return(1); + } + + /* Attempt to allocate fourth memory area from the pool. This should fail because + there should be not enough bytes in the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_4, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_MEMORY) + { + + /* Byte memory error. */ + printf("ERROR #35\n"); + test_control_return(1); + } + + /* Release the block. */ + status = tx_byte_release(pointer_3); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #36\n"); + test_control_return(1); + } + + /* Now ensure the search pointer update in the byte search algorithm is updated. */ + + /* Allocate memory from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_1, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #37\n"); + test_control_return(1); + } + + /* Allocate second memory area from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_2, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #38\n"); + test_control_return(1); + } + + /* Allocate third memory area from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_3, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #39\n"); + test_control_return(1); + } + + /* Release the middle block. */ + status = tx_byte_release(pointer_2); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #40\n"); + test_control_return(1); + } + + /* Move the search pointer to the third block to exercise that code in the byte search algorithm. */ + pool_0.tx_byte_pool_search = (UCHAR *) pointer_3-8; + + /* Now allocate the block again. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_2, 24, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #41\n"); + test_control_return(1); + } + + /* Now release the blocks are test the merge with the update of the search pointer. */ + status = tx_byte_release(pointer_3); + status += tx_byte_release(pointer_2); + status += tx_byte_release(pointer_1); + + /* Move the search pointer to the third block to exercise that code in the byte search algorithm. */ + pool_0.tx_byte_pool_search = (UCHAR *) pointer_3-8; + + /* Allocate a large block to force the search pointer update. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer_3, 88, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #42\n"); + test_control_return(1); + } + + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Create a timer for the test. */ + tx_timer_create(&timer_0, "timer 0", timer_entry, 0, 1, 1, TX_AUTO_ACTIVATE); + + /* Setup the ISR. */ + test_isr_dispatch = test_isr; + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Clear the ISR. */ + test_isr_dispatch = TX_NULL; + + /* Test for error. */ + if ((error) || (timer_executed != 1) || (isr_executed != 1)) + { + + /* Byte memory error. */ + printf("ERROR #43\n"); + test_control_return(1); + } + +#endif + + /* Delete both byte pools. */ + status = tx_byte_pool_delete(&pool_0); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #44\n"); + test_control_return(1); + } + + status = tx_byte_pool_delete(&pool_1); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #45\n"); + test_control_return(1); + } + + /* Delete pool 4. */ + status = tx_byte_pool_delete(&pool_4); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #46\n"); + test_control_return(1); + } + + /* Create pool 4. */ + status = tx_byte_pool_create(&pool_4, "pool 4", pool_4_memory, 300); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #47\n"); + test_control_return(1); + } + + /* Allocate three blocks... */ + status = tx_byte_allocate(&pool_4, (VOID **) &pointer_1, 84, TX_NO_WAIT); + status += tx_byte_allocate(&pool_4, (VOID **) &pointer_2, 84, TX_NO_WAIT); + status += tx_byte_allocate(&pool_4, (VOID **) &pointer_3, 84, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #48\n"); + test_control_return(1); + } + + /* At this point, there should be three allocated blocks and the reserved block at the end. */ + + /* Now release all the blocks in reverse order. This should leave the search pointer at the last block. */ + status = tx_byte_release(pointer_3); + save_search = pool_4.tx_byte_pool_search; + status += tx_byte_release(pointer_2); + status += tx_byte_release(pointer_1); + + /* Move the search pointer back to the last block. */ + pool_4.tx_byte_pool_search = save_search; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #49\n"); + test_control_return(1); + } + + /* Now attempt to allocate a block that requires a merge, which should exercise the branch in byte search that does not + result in a search pointer change. */ + status = tx_byte_allocate(&pool_4, (VOID **) &pointer_1, 168, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #50\n"); + test_control_return(1); + } + + /* Release the last block. */ + status = tx_byte_release(pointer_1); + + /* Allocate all the blocks. */ + status = tx_byte_allocate(&pool_4, (VOID **) &pointer_1, 84, TX_NO_WAIT); + status += tx_byte_allocate(&pool_4, (VOID **) &pointer_2, 84, TX_NO_WAIT); + status += tx_byte_allocate(&pool_4, (VOID **) &pointer_3, 84, TX_NO_WAIT); + + /* Release all of the blocks in order. */ + status += tx_byte_release(pointer_1); + status += tx_byte_release(pointer_2); + status += tx_byte_release(pointer_3); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #50\n"); + test_control_return(1); + } + + /* Now setup a special test to exercise the examine blocks equal to 0 path in the byte pool search. */ + pool_4.tx_byte_pool_search = save_search; + pool_4.tx_byte_pool_fragments = (UINT) (-1); + + /* Call byte allocate to execise the examine blocks equal to 0 path on non-merge block condition. */ + status = tx_byte_allocate(&pool_4, (VOID **) &pointer_1, 168, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_MEMORY) + { + + /* Byte memory error. */ + printf("ERROR #51\n"); + test_control_return(1); + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + diff --git a/test/tx/regression/threadx_byte_memory_information_test.c b/test/tx/regression/threadx_byte_memory_information_test.c new file mode 100644 index 00000000..2d1c20bc --- /dev/null +++ b/test/tx/regression/threadx_byte_memory_information_test.c @@ -0,0 +1,784 @@ +/* This test is designed to test byte memory information. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_byte_pool.h" + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +/* Define the external reference for the preempt disable flag. */ + +extern volatile UINT _tx_thread_preempt_disable; + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + +static unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; + +static unsigned long thread_5_counter = 0; +static TX_THREAD thread_5; + +static unsigned long thread_6_counter = 0; +static TX_THREAD thread_6; + +static TX_BYTE_POOL byte_pool_0; +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO +static TX_BYTE_POOL byte_pool_1; +#endif +static TX_BYTE_POOL byte_pool_2; + +static int test_status; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +static void thread_5_entry(ULONG thread_input); +static void thread_6_entry(ULONG thread_input); + +UINT _tx_byte_pool_performance_info_get(TX_BYTE_POOL *pool_ptr, ULONG *allocates, ULONG *releases, + ULONG *fragments_searched, ULONG *merges, ULONG *splits, ULONG *suspensions, ULONG *timeouts); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + + /* Determine if the test case we are looking for is present. */ + if ((_tx_thread_preempt_disable) && (test_status == 1)) + { + + /* Abort the wait of thread 3. */ + tx_thread_wait_abort(&thread_3); + + /* End the ISR processing. */ + test_status = 2; + test_isr_dispatch = TX_NULL; + } +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_byte_memory_information_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Information Test................................ ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Information Test................................ ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Information Test................................ ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 3, 3, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Information Test................................ ERROR #4\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 4, 4, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Information Test................................ ERROR #5\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, + pointer, TEST_STACK_SIZE_PRINTF, + 5, 5, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Information Test................................ ERROR #6\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_6, "thread 6", thread_6_entry, 6, + pointer, TEST_STACK_SIZE_PRINTF, + 6, 6, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Information Test................................ ERROR #7\n"); + test_control_return(1); + } + + /* Create the byte_pool with one byte. */ + status = tx_byte_pool_create(&byte_pool_0, "byte_pool 0", pointer, 100); + pointer = pointer + 100; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Information Test................................ ERROR #8\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; +CHAR *name; +ULONG available; +ULONG fragments; +TX_THREAD *first_suspended; +ULONG suspended_count; +TX_BYTE_POOL *next_pool; +ULONG allocates; +ULONG releases; +ULONG fragments_searched; +ULONG merges; +ULONG splits; +ULONG suspensions; +ULONG timeouts; + + + /* Inform user. */ + printf("Running Byte Memory Information Test................................ "); + + /* Allocate the one byte. */ + tx_byte_allocate(&byte_pool_0, &pointer, 80, TX_NO_WAIT); + + /* Nothing to do here, but check prioritization with no suspended threads. */ + status = tx_byte_pool_prioritize(&byte_pool_0); + + /* Check status and make sure thread 1 is terminated. */ + if (status != TX_SUCCESS) + { + + /* Byte Pool error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + + /* Increment the thread counter. */ + thread_0_counter++; + + /* Make sure thread 1 and 2 are suspended on the byte_pool. */ + if ((thread_1.tx_thread_state != TX_BYTE_MEMORY) || (thread_2.tx_thread_state != TX_BYTE_MEMORY) || + (byte_pool_0.tx_byte_pool_suspension_list != &thread_1)) + { + + /* Byte Pool error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Prioritize the byte pool suspension list. */ + status = tx_byte_pool_prioritize(&byte_pool_0); + + /* Check status and make sure thread 2 is now at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (byte_pool_0.tx_byte_pool_suspension_list != &thread_2)) + { + + /* Byte Pool error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* At this point we are going to get more than 2 threads suspended. */ + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + tx_thread_resume(&thread_3); + tx_thread_resume(&thread_4); + tx_thread_resume(&thread_5); + tx_thread_resume(&thread_6); + + /* Prioritize the byte pool suspension list. */ + status = tx_byte_pool_prioritize(&byte_pool_0); + + /* Check status and make sure thread 3 is now at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (byte_pool_0.tx_byte_pool_suspension_list != &thread_3)) + { + + /* Byte Pool error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Now loop to test the interrupt of the prioritize loop logic. */ + test_status = 1; + test_isr_dispatch = test_isr; + do + { + + /* Prioritize the byte pool suspension list. */ + status = tx_byte_pool_prioritize(&byte_pool_0); + + /* Check status and make sure thread 1 is terminated. */ + if (status != TX_SUCCESS) + { + + /* Byte Pool error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + } while (test_status == 1); + + /* Check status and make sure thread 3 is now at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (byte_pool_0.tx_byte_pool_suspension_list != &thread_4)) + { + + /* Byte Pool error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Call byte pool info with a NULL pointer. */ + status = tx_byte_pool_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for error. */ + if (status != TX_POOL_ERROR) + { + + /* Byte Pool error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Call byte pool info with an non-created pool pointer. */ + byte_pool_2.tx_byte_pool_id = 0; + status = tx_byte_pool_info_get(&byte_pool_2, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for error. */ + if (status != TX_POOL_ERROR) + { + + /* Byte Pool error. */ + printf("ERROR #16\n"); + test_control_return(1); + } +#endif + + /* Get the byte pool information. */ + status = tx_byte_pool_info_get(&byte_pool_0, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_byte_pool_info_get(&byte_pool_0, &name, &available, &fragments, &first_suspended, &suspended_count, &next_pool); + + /* Check the status. */ + if ((status != TX_SUCCESS) || (available != byte_pool_0.tx_byte_pool_available) || (fragments != byte_pool_0.tx_byte_pool_fragments) || + (first_suspended != &thread_4) || (suspended_count != byte_pool_0.tx_byte_pool_suspended_count) || (next_pool != &byte_pool_0)) + { + + /* Byte Pool error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + + /* Get the byte pool performance information. */ + status = tx_byte_pool_performance_info_get(TX_NULL, &allocates, &releases, &fragments_searched, &merges, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_PTR_ERROR) + { + + /* Byte Pool error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Get the byte pool performance information. */ + status = tx_byte_pool_performance_info_get(&byte_pool_1, &allocates, &releases, &fragments_searched, &merges, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_PTR_ERROR) + { + + /* Byte Pool error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Get the byte pool performance information. */ + status = tx_byte_pool_performance_info_get(&byte_pool_0, &allocates, &releases, &fragments_searched, &merges, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if ((status != TX_SUCCESS) || (allocates != byte_pool_0.tx_byte_pool_performance_allocate_count) || (releases != byte_pool_0.tx_byte_pool_performance_release_count) || + (fragments_searched != byte_pool_0.tx_byte_pool_performance_search_count) || (merges != byte_pool_0.tx_byte_pool_performance_merge_count) || + (splits != byte_pool_0.tx_byte_pool_performance_split_count) || (suspensions != byte_pool_0.tx_byte_pool_performance_suspension_count) || + (timeouts != byte_pool_0.tx_byte_pool_performance_timeout_count)) + { + + /* Byte Pool error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Get the byte pool system performance information. */ + status = tx_byte_pool_performance_system_info_get(&allocates, &releases, &fragments_searched, &merges, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if ((status != TX_SUCCESS) || (allocates != _tx_byte_pool_performance_allocate_count) || (releases != _tx_byte_pool_performance_release_count) || + (fragments_searched != _tx_byte_pool_performance_search_count) || (merges != _tx_byte_pool_performance_merge_count) || + (splits != _tx_byte_pool_performance_split_count) || (suspensions != _tx_byte_pool_performance_suspension_count) || + (timeouts != _tx_byte_pool_performance_timeout_count)) + { + + /* Byte Pool error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +#else + + /* Get the byte pool performance information. */ + status = tx_byte_pool_performance_info_get(&byte_pool_0, &allocates, &releases, &fragments_searched, &merges, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + /* Get the byte pool performance information. */ + status = tx_byte_pool_performance_info_get(TX_NULL, &allocates, &releases, &fragments_searched, &merges, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Get the byte pool performance information. */ + status = tx_byte_pool_performance_info_get(TX_NULL, TX_NULL, &releases, &fragments_searched, &merges, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Get the byte pool performance information. */ + status = tx_byte_pool_performance_info_get(TX_NULL, TX_NULL, TX_NULL, &fragments_searched, &merges, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + + /* Get the byte pool performance information. */ + status = tx_byte_pool_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, &merges, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + /* Get the byte pool performance information. */ + status = tx_byte_pool_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Get the byte pool performance information. */ + status = tx_byte_pool_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #28\n"); + test_control_return(1); + } + + /* Get the byte pool performance information. */ + status = tx_byte_pool_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #29\n"); + test_control_return(1); + } + + /* Get the byte pool performance information. */ + status = tx_byte_pool_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #30\n"); + test_control_return(1); + } + + /* Get the byte pool system performance information. */ + status = tx_byte_pool_performance_system_info_get(&allocates, &releases, &fragments_searched, &merges, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #31\n"); + test_control_return(1); + } + + /* Get the byte pool system performance information. */ + status = tx_byte_pool_performance_system_info_get(TX_NULL, &releases, &fragments_searched, &merges, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #32\n"); + test_control_return(1); + } + + /* Get the byte pool system performance information. */ + status = tx_byte_pool_performance_system_info_get(TX_NULL, TX_NULL, &fragments_searched, &merges, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #33\n"); + test_control_return(1); + } + + /* Get the byte pool system performance information. */ + status = tx_byte_pool_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, &merges, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #34\n"); + test_control_return(1); + } + + /* Get the byte pool system performance information. */ + status = tx_byte_pool_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, &splits, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #35\n"); + test_control_return(1); + } + + /* Get the byte pool system performance information. */ + status = tx_byte_pool_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #36\n"); + test_control_return(1); + } + + /* Get the byte pool system performance information. */ + status = tx_byte_pool_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #37\n"); + test_control_return(1); + } + + /* Get the byte pool system performance information. */ + status = tx_byte_pool_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Byte Pool error. */ + printf("ERROR #38\n"); + test_control_return(1); + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +#endif +} + + +static void thread_1_entry(ULONG thread_input) +{ +UINT status; +VOID *pointer; + + /* Loop forever! */ + while(1) + { + + + /* Get byte from pool. */ + status = tx_byte_allocate(&byte_pool_0, &pointer, 25, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get byte from pool. */ + status = tx_byte_allocate(&byte_pool_0, &pointer, 25, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_2_counter++; + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get byte from pool. */ + status = tx_byte_allocate(&byte_pool_0, &pointer, 25, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_3_counter++; + } +} + + +static void thread_4_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get byte from pool. */ + status = tx_byte_allocate(&byte_pool_0, &pointer, 25, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_4_counter++; + } +} + + +static void thread_5_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get byte from pool. */ + status = tx_byte_allocate(&byte_pool_0, &pointer, 25, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_5_counter++; + } +} + + +static void thread_6_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get byte from pool. */ + status = tx_byte_allocate(&byte_pool_0, &pointer, 25, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_6_counter++; + } +} diff --git a/test/tx/regression/threadx_byte_memory_prioritize_test.c b/test/tx/regression/threadx_byte_memory_prioritize_test.c new file mode 100644 index 00000000..f06d5cd3 --- /dev/null +++ b/test/tx/regression/threadx_byte_memory_prioritize_test.c @@ -0,0 +1,498 @@ +/* This test is designed to test byte memory prioritize. */ + +#include <stdio.h> +#include "tx_api.h" + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +/* Define the external reference for the preempt disable flag. */ + +extern volatile UINT _tx_thread_preempt_disable; + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + +static unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; + +static unsigned long thread_5_counter = 0; +static TX_THREAD thread_5; + +static unsigned long thread_6_counter = 0; +static TX_THREAD thread_6; + +static TX_BYTE_POOL byte_pool_0; +static TX_BYTE_POOL byte_pool_1; + +static int test_status; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +static void thread_5_entry(ULONG thread_input); +static void thread_6_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + + /* Determine if the test case we are looking for is present. */ + if ((_tx_thread_preempt_disable) && (test_status == 1)) + { + + /* Determine if thread 3 is at the front of the suspension list. */ + if (byte_pool_0.tx_byte_pool_suspension_list == &thread_3) + { + + /* Abort the wait of thread 3. */ + tx_thread_wait_abort(&thread_3); + } + else + { + + /* Abort the wait of thread 5. */ + tx_thread_wait_abort(&thread_5); + + /* End the ISR processing. */ + test_status = 2; + test_isr_dispatch = TX_NULL; + } + } +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_byte_memory_prioritize_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Prioritize Test................................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Prioritize Test................................. ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Prioritize Test................................. ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 3, 3, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Prioritize Test................................. ERROR #4\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 4, 4, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Prioritize Test................................. ERROR #5\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, + pointer, TEST_STACK_SIZE_PRINTF, + 5, 5, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Prioritize Test................................. ERROR #6\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_6, "thread 6", thread_6_entry, 6, + pointer, TEST_STACK_SIZE_PRINTF, + 6, 6, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Prioritize Test................................. ERROR #7\n"); + test_control_return(1); + } + + /* Create the byte_pool with one byte. */ + status = tx_byte_pool_create(&byte_pool_0, "byte_pool 0", pointer, 100); + pointer = pointer + 100; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Prioritize Test................................. ERROR #8\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Inform user. */ + printf("Running Byte Memory Prioritize Test................................. "); + + /* Allocate the one byte. */ + tx_byte_allocate(&byte_pool_0, &pointer, 80, TX_NO_WAIT); + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Call byte pool prioritize with a NULL pointer. */ + status = tx_byte_pool_prioritize(TX_NULL); + + /* Check for error. */ + if (status != TX_POOL_ERROR) + { + + /* Byte Pool error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Call byte pool info with an non-created pool pointer. */ + byte_pool_1.tx_byte_pool_id = 0; + status = tx_byte_pool_prioritize(&byte_pool_1); + + /* Check for error. */ + if (status != TX_POOL_ERROR) + { + + /* Byte Pool error. */ + printf("ERROR #10\n"); + test_control_return(1); + } +#endif + + /* Nothing to do here, but check prioritization with no suspended threads. */ + status = tx_byte_pool_prioritize(&byte_pool_0); + + /* Check status and make sure thread 1 is terminated. */ + if (status != TX_SUCCESS) + { + + /* Byte Pool error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + + /* Increment the thread counter. */ + thread_0_counter++; + + /* Make sure thread 1 and 2 are suspended on the byte_pool. */ + if ((thread_1.tx_thread_state != TX_BYTE_MEMORY) || (thread_2.tx_thread_state != TX_BYTE_MEMORY) || + (byte_pool_0.tx_byte_pool_suspension_list != &thread_1)) + { + + /* Byte Pool error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Prioritize the byte pool suspension list. */ + status = tx_byte_pool_prioritize(&byte_pool_0); + + /* Check status and make sure thread 2 is now at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (byte_pool_0.tx_byte_pool_suspension_list != &thread_2)) + { + + /* Byte Pool error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Call byte pool prioritize again to test the don't-do-anything path in tx_byte_pool_prioritize. */ + status += tx_byte_pool_prioritize(&byte_pool_0); + + /* At this point we are going to get more than 2 threads suspended. */ + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + tx_thread_resume(&thread_3); + tx_thread_resume(&thread_4); + tx_thread_resume(&thread_5); + tx_thread_resume(&thread_6); + + /* Prioritize the byte pool suspension list. */ + status = tx_byte_pool_prioritize(&byte_pool_0); + + /* Check status and make sure thread 3 is now at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (byte_pool_0.tx_byte_pool_suspension_list != &thread_3)) + { + + /* Byte Pool error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Now loop to test the interrupt of the prioritize loop logic. */ + test_status = 1; + test_isr_dispatch = test_isr; + do + { + + /* Prioritize the byte pool suspension list. */ + status = tx_byte_pool_prioritize(&byte_pool_0); + + /* Check status and make sure thread 1 is terminated. */ + if (status != TX_SUCCESS) + { + + /* Block Pool error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + } while (test_status == 1); + + /* Check status and make sure thread 3 is now at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (byte_pool_0.tx_byte_pool_suspension_list != &thread_4)) + { + + /* Byte Pool error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ +UINT status; +VOID *pointer; + + /* Loop forever! */ + while(1) + { + + + /* Get byte from pool. */ + status = tx_byte_allocate(&byte_pool_0, &pointer, 25, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get byte from pool. */ + status = tx_byte_allocate(&byte_pool_0, &pointer, 25, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_2_counter++; + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get byte from pool. */ + status = tx_byte_allocate(&byte_pool_0, &pointer, 25, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_3_counter++; + } +} + + +static void thread_4_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get byte from pool. */ + status = tx_byte_allocate(&byte_pool_0, &pointer, 25, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_4_counter++; + } +} + + +static void thread_5_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get byte from pool. */ + status = tx_byte_allocate(&byte_pool_0, &pointer, 25, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_5_counter++; + } +} + + +static void thread_6_entry(ULONG thread_input) +{ + +UINT status; +VOID *pointer; + + + /* Loop forever! */ + while(1) + { + + + /* Get byte from pool. */ + status = tx_byte_allocate(&byte_pool_0, &pointer, 25, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_6_counter++; + } +} + diff --git a/test/tx/regression/threadx_byte_memory_suspension_test.c b/test/tx/regression/threadx_byte_memory_suspension_test.c new file mode 100644 index 00000000..069410c5 --- /dev/null +++ b/test/tx/regression/threadx_byte_memory_suspension_test.c @@ -0,0 +1,391 @@ +/* This test is designed to test suspension on a memory byte pool. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + + +static TX_BYTE_POOL pool_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); + + + +#ifndef TX_MANUAL_TEST + +/* Define test flags for automated test. */ + +extern TEST_FLAG threadx_byte_allocate_loop_test; +extern TEST_FLAG threadx_byte_release_loop_test; + +#endif + + +void abort_and_resume_byte_allocating_thread(void) +{ + +UCHAR *search_ptr; + + /* Adjust the search pointer to avoid the search pointer change for this test. */ + search_ptr = pool_0.tx_byte_pool_search; + while (search_ptr >= pool_0.tx_byte_pool_search) + + { + search_ptr = *((UCHAR **) ((VOID *) search_ptr)); + } + pool_0.tx_byte_pool_search = search_ptr; + + tx_thread_wait_abort(&thread_3); + tx_thread_resume(&thread_3); +} + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_byte_memory_suspension_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Suspension Test................................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Suspension Test................................. ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Suspension Test................................. ERROR #3\n"); + test_control_return(1); + } + + /* Create byte pool 0. */ + status = tx_byte_pool_create(&pool_0, "pool 0", pointer, 108); + pointer = pointer + 108; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Suspension Test................................. ERROR #4\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer; + + + /* Inform user. */ + printf("Running Byte Memory Suspension Test................................. "); + + /* Increment the thread counter. */ + thread_0_counter++; + + /* Allocate memory from the pool. Only one block of this size will fit. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 60, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Let other thread suspend on byte pool. */ + tx_thread_relinquish(); + + /* Now release the blocks. */ + status = tx_byte_release(pointer); + + /* Check status. */ + if ((status != TX_SUCCESS) && (thread_1_counter == 0)) + { + + /* Byte memory error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Let other thread run again. */ + tx_thread_relinquish(); + + /* Check to make sure thread 1 has now run. */ + if (thread_1_counter != 1) + { + + /* Byte memory error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Now allocate the memory again. Only one block of this size will fit. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 60, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Resume the second thread. */ + tx_thread_resume(&thread_2); + + /* Now relinquish to let both thread 1 and 2 suspend. */ + tx_thread_relinquish(); + + /* At this point both threads should be suspended on the byte pool. */ + + /* Release the memory again. */ + status = tx_byte_release(pointer); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Now relinquish to get the other threads to run once. */ + tx_thread_relinquish(); + tx_thread_relinquish(); + + /* At this point both threads 1 and 2 are suspended on the byte pool again. */ + if ((thread_1_counter != 3) && (thread_2_counter != 1)) + { + + /* Byte memory error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Now allocate the memory again. Only one block of this size will fit. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 60, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #10a\n"); + test_control_return(1); + } + + /* Resume thread 3 to get it suspended on the the pool. */ + tx_thread_resume(&thread_3); + +#ifdef TX_MANUAL_TEST + + /* Set BP hear. Now release the memory and step into the code. After byte search issue IRQ2 mannually, which will + make thread 3 abort the first request and make another request of a different size. This is the path we are trying + to generate in the test. */ + status = tx_byte_release(pointer); +#else + + /* Set the flag that will make thread 3 abort the first request and make another request of a different size. This tests the memory size change path + in the byte release loop logic. */ + threadx_byte_release_loop_test = 1; + status = tx_byte_release(pointer); + +#endif + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #10b\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer; + + while(1) + { + + /* Allocate memory from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 60, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + return; + + /* Increment the thread counter. */ + thread_1_counter++; + + /* Now release each of the blocks. */ + status = tx_byte_release(pointer); + + /* Check for status. */ + if (status != TX_SUCCESS) + return; + + /* Let thread 0 run again. */ + tx_thread_relinquish(); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer; + + while(1) + { + + /* Allocate memory from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 60, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + return; + + /* Increment the thread counter. */ + thread_2_counter++; + + /* Now release each of the blocks. */ + status = tx_byte_release(pointer); + + /* Check for status. */ + if (status != TX_SUCCESS) + return; + + /* Let thread 0 run again. */ + tx_thread_relinquish(); + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer; + + while (1) + { + + /* Allocate memory from the pool. */ + tx_byte_allocate(&pool_0, (VOID **) &pointer, 60, TX_WAIT_FOREVER); + +#ifdef TX_MANUAL_TEST + + /* Set BP here and manually clear the owner after one failed byte search just to test the loop + construct in tx_byte_allocate.c. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 90, TX_WAIT_FOREVER); +#else + + /* Set the flag that clears the pool owner after one failed byte search to test the loop + construct processing in tx_byte_allocate.c. */ + threadx_byte_allocate_loop_test = 1; + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 90, TX_WAIT_FOREVER); +#endif + + /* Check for status. */ + if (status != TX_SUCCESS) + return; + + /* Increment the thread counter. */ + thread_3_counter++; + + /* Now release the block. */ + status = tx_byte_release(pointer); + + /* Check for status. */ + if (status != TX_SUCCESS) + return; + + /* suspend this thread. */ + tx_thread_suspend(&thread_3); + } +} diff --git a/test/tx/regression/threadx_byte_memory_suspension_timeout_test.c b/test/tx/regression/threadx_byte_memory_suspension_timeout_test.c new file mode 100644 index 00000000..ed122dab --- /dev/null +++ b/test/tx/regression/threadx_byte_memory_suspension_timeout_test.c @@ -0,0 +1,196 @@ +/* This test is designed to test suspension timeout on a memory byte pool. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + + +static TX_BYTE_POOL pool_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_byte_memory_suspension_timeout_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Suspension Timeout Test......................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Suspension Timeout Test......................... ERROR #2\n"); + test_control_return(1); + } + + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Suspension Timeout Test......................... ERROR #3\n"); + test_control_return(1); + } + + /* Create byte pool 0. */ + status = tx_byte_pool_create(&pool_0, "pool 0", pointer, 108); + pointer = pointer + 108; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Suspension Timeout Test......................... ERROR #4\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer; + + + /* Inform user. */ + printf("Running Byte Memory Suspension Timeout Test......................... "); + + /* Increment the thread counter. */ + thread_0_counter++; + + /* Allocate memory from the pool. Only one block of this size will fit. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 60, TX_NO_WAIT); + + /* Check status. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 0)) + { + + /* Byte memory error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Sleep to allow the other thread to suspend and timeout on the memory + pool once. */ + tx_thread_sleep(64); + + /* Check the counter of the other thread. */ + if ((thread_1_counter != 6) || (thread_2_counter != 3)) + { + + /* Block memory error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer; + + while(1) + { + + /* Allocate memory from the pool - with timeout. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 60, 10); + + /* Check status. */ + if (status != TX_NO_MEMORY) + return; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer; + + + /* Delay so we get some single suspension timeouts as well. */ + tx_thread_sleep(32); + + while(1) + { + + /* Allocate memory from the pool - with timeout. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 60, 10); + + /* Check status. */ + if (status != TX_NO_MEMORY) + return; + + /* Increment the thread counter. */ + thread_2_counter++; + } +} diff --git a/test/tx/regression/threadx_byte_memory_thread_contention_test.c b/test/tx/regression/threadx_byte_memory_thread_contention_test.c new file mode 100644 index 00000000..a3e689c8 --- /dev/null +++ b/test/tx/regression/threadx_byte_memory_thread_contention_test.c @@ -0,0 +1,255 @@ +/* This test is designed to test contention of two threads on a single + memory byte pool. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; +static unsigned long initial_pool_size; + + +static TX_BYTE_POOL pool_0; + + +static int test_done; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_byte_memory_thread_contention_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 1, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Thread Contention Test.......................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 1, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Thread Contention Test.......................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 1, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Thread Contention Test.......................... ERROR #3\n"); + test_control_return(1); + } + + /* Create byte pool 0. */ + status = tx_byte_pool_create(&pool_0, "pool 0", pointer, 108); + pointer = pointer + 108; + + /* Save off the intial pool size. */ + initial_pool_size = pool_0.tx_byte_pool_available; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Thread Contention Test.......................... ERROR #4\n"); + test_control_return(1); + } + + /* Set the test done flag to false. */ + test_done = TX_FALSE; +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer; + + + /* Inform user. */ + printf("Running Byte Memory Thread Contention Test.......................... "); + + /* Set time to 0. */ + tx_time_set(0); + + while(1) + { + + /* Allocate memory from the pool. This size will cause merge activity + because the search pointer will sit in this large block about half + the time. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 60, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Fill the memory. */ + TX_MEMSET(pointer, (CHAR) 0xEF, 60); + + /* Now release the block. */ + status = tx_byte_release(pointer); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Check the time. */ + if (tx_time_get() > 128) + break; + + /* Increment the thread counter. */ + thread_0_counter++; + } + + /* Set the done flag. */ + test_done = TX_TRUE; + + /* Sleep to let the other threads finish up! */ + tx_thread_sleep(2); + + /* Determine if we all all the original memory and that thread 1 + is in the proper place. */ + if (pool_0.tx_byte_pool_available != initial_pool_size) + { + + /* Byte memory error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer; + + + while(test_done == TX_FALSE) + { + + /* Allocate memory from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 30, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + return; + + /* Fill the memory. */ + TX_MEMSET(pointer, (CHAR) 0xEF, 30); + + /* Now release the block. */ + status = tx_byte_release(pointer); + + /* Check for status. */ + if (status != TX_SUCCESS) + return; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer; + + + while(test_done == TX_FALSE) + { + + /* Allocate memory from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 12, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + return; + + /* Fill the memory. */ + TX_MEMSET(pointer, (CHAR) 0xEF, 12); + + /* Now release the block. */ + status = tx_byte_release(pointer); + + /* Check for status. */ + if (status != TX_SUCCESS) + return; + + /* Increment the thread counter. */ + thread_2_counter++; + } +} diff --git a/test/tx/regression/threadx_byte_memory_thread_terminate_test.c b/test/tx/regression/threadx_byte_memory_thread_terminate_test.c new file mode 100644 index 00000000..29fec0c0 --- /dev/null +++ b/test/tx/regression/threadx_byte_memory_thread_terminate_test.c @@ -0,0 +1,177 @@ +/* This test is designed to test termination on thread suspended on memory byte pool. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + + +static TX_BYTE_POOL pool_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_byte_memory_thread_terminate_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Thread Terminate Test........................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Thread Terminate Test........................... ERROR #2\n"); + test_control_return(1); + } + + /* Create byte pools 0 and 1. */ + status = tx_byte_pool_create(&pool_0, "pool 0", pointer, 108); + pointer = pointer + 108; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Thread Terminate Test........................... ERROR #3\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer; + + + /* Inform user. */ + printf("Running Byte Memory Thread Terminate Test........................... "); + + /* Increment the thread counter. */ + thread_0_counter++; + + /* Allocate memory from the pool. Only one block of this size will fit. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 60, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Let other thread suspend on byte pool. */ + tx_thread_relinquish(); + + /* Terminate the other thread. */ + status = tx_thread_terminate(&thread_1); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Release block back. */ + status = tx_byte_release(pointer); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Byte memory error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Allocate memory from the pool. Only one block of this size will fit. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 60, TX_NO_WAIT); + + /* Check status. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 0)) + { + + /* Byte memory error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +CHAR *pointer; + + while(1) + { + + /* Allocate memory from the pool. */ + status = tx_byte_allocate(&pool_0, (VOID **) &pointer, 60, TX_WAIT_FOREVER); + + /* Should never get here! */ + if (status != TX_NO_MEMORY) + return; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + diff --git a/test/tx/regression/threadx_event_flag_basic_test.c b/test/tx/regression/threadx_event_flag_basic_test.c new file mode 100644 index 00000000..9c19f9bd --- /dev/null +++ b/test/tx/regression/threadx_event_flag_basic_test.c @@ -0,0 +1,743 @@ +/* This test is designed to test simple event flag group creation, deletion, gets and + sets. */ + +#include <stdio.h> +#include "tx_api.h" + + +typedef struct EVENT_FLAG_MEMORY_TEST_STRUCT +{ + ULONG first; + ULONG second; + TX_EVENT_FLAGS_GROUP event_flags; + ULONG next_to_last; + ULONG last; + +} EVENT_FLAG_MEMORY_TEST; + +static EVENT_FLAG_MEMORY_TEST event_flag_memory; + + +/* Define external reference to the event flag create call from initialization. */ + +extern UINT test_event_flags_from_init; + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +static TX_THREAD thread_0; +static TX_THREAD thread_1; +static TX_TIMER timer_0; + +static unsigned long error = 0; +static unsigned long timer_executed = 0; +static unsigned long isr_executed = 0; + +static TX_EVENT_FLAGS_GROUP group_0; +static TX_EVENT_FLAGS_GROUP group_1; +static TX_EVENT_FLAGS_GROUP group_2; +static TX_EVENT_FLAGS_GROUP group_3; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void event_set_notify(TX_EVENT_FLAGS_GROUP *group) +{ + + /* Not necessary to do anything in this function. */ +} + + +/* Define the timer for this test. */ + +static void timer_entry(ULONG i) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +UINT status; +ULONG actual_events; + + + /* Determine if calling event flag create from initialization was successful. */ + if (test_event_flags_from_init != TX_SUCCESS) + { + + /* Error! */ + error++; + } + + /* Attempt to create an event flag group from a timer. */ + status = tx_event_flags_create(&group_2, "group 2"); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Try to delete an event flags group from a timer. */ + status = tx_event_flags_delete(&group_0); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Get events with suspendsion from a timer. */ + status = tx_event_flags_get(&group_0, 0x80008000, 14, &actual_events, 100); + + /* Check status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + timer_executed = 1; +#endif +} + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +UINT status; +ULONG actual_events; + + + /* Attempt to create an event flag group from an ISR. */ + status = tx_event_flags_create(&group_2, "group 2"); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to delete an event flags group from an ISR. */ + status = tx_event_flags_delete(&group_0); + + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Get events with suspendsion from an ISR. */ + status = tx_event_flags_get(&group_0, 0x80008000, 14, &actual_events, 100); + + /* Check status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + + isr_executed = 1; +#endif +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_event_flag_basic_application_define(void *first_unused_memory) +#endif +{ + +INT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Basic Test....................................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Basic Test....................................... ERROR #2\n"); + test_control_return(1); + } + + /* Create event flag group 0 and 1. */ + status = tx_event_flags_create(&group_0, "group 0"); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Basic Test....................................... ERROR #3\n"); + test_control_return(1); + } + + status = tx_event_flags_create(&group_1, "group 1"); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Basic Test....................................... ERROR #4\n"); + test_control_return(1); + } + + /* Register the event set notify function. */ + status = tx_event_flags_set_notify(&group_0, event_set_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Basic Test....................................... ERROR #5\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Event Flag Basic Test....................................... ERROR #6\n"); + test_control_return(1); + } + +#endif + + /* Un-register the event set notify function. */ + status = tx_event_flags_set_notify(&group_0, TX_NULL); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Basic Test....................................... ERROR #5a\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Event Flag Basic Test....................................... ERROR #6a\n"); + test_control_return(1); + } +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual_events; + + + /* Inform user. */ + printf("Running Event Flag Basic Test....................................... "); + + /* Perform event flag memory test. */ + event_flag_memory.first = 0x11223344; + event_flag_memory.second = 0x55667788; + event_flag_memory.next_to_last = 0x99aabbcc; + event_flag_memory.last = 0xddeeff00; + + /* Create the event flag group. */ + status = tx_event_flags_create(&event_flag_memory.event_flags, "group memory"); + tx_event_flags_delete(&event_flag_memory.event_flags); + + /* Check for status. */ + if ((status != TX_SUCCESS) || + (event_flag_memory.first != 0x11223344) || + (event_flag_memory.second != 0x55667788) || + (event_flag_memory.next_to_last != 0x99aabbcc) || + (event_flag_memory.last != 0xddeeff00)) + { + + /* Event flag error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Event flags should be created now. */ + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Try to create with a NULL pointer. */ + status = tx_event_flags_create(TX_NULL, "group 0"); + + /* Check status. */ + if (status != TX_GROUP_ERROR) + { + + /* Event flag error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Try to create with a bad size. */ + status = _txe_event_flags_create(&group_3, "group 3", (sizeof(TX_EVENT_FLAGS_GROUP)+1)); + + /* Check status. */ + if (status != TX_GROUP_ERROR) + { + + /* Event flag error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Try to create an already created group. */ + status = tx_event_flags_create(&group_0, "group 0"); + + /* Check status. */ + if (status != TX_GROUP_ERROR) + { + + /* Event flag error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Delete with a NULL pointer. */ + status = tx_event_flags_delete(TX_NULL); + + /* Check the status. */ + if (status != TX_GROUP_ERROR) + { + + /* Event flag error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Delete with a non-created pointer. */ + group_2.tx_event_flags_group_id = 0; + status = tx_event_flags_delete(&group_2); + + /* Check the status. */ + if (status != TX_GROUP_ERROR) + { + + /* Event flag error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Get events with a null group pointer. */ + status = tx_event_flags_get(TX_NULL, 0x80008000, TX_AND, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_GROUP_ERROR) + { + + /* Event flag error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Get events with a non-created group pointer. */ + group_2.tx_event_flags_group_id = 0; + status = tx_event_flags_get(&group_2, 0x80008000, TX_AND, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_GROUP_ERROR) + { + + /* Event flag error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Get events with a null flags retun pointer. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND, TX_NULL, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_PTR_ERROR) + { + + /* Event flag error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Get events with a bad option. */ + status = tx_event_flags_get(&group_0, 0x80008000, 14, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_OPTION_ERROR) + { + + /* Event flag error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Set evetns with a NULL group pointer. */ + status = tx_event_flags_set(TX_NULL, 0x80008000, TX_OR); + + /* Check status. */ + if (status != TX_GROUP_ERROR) + { + + /* Event flag error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Set events with a non-created group pointer. */ + group_2.tx_event_flags_group_id = 0; + status = tx_event_flags_set(&group_2, 0x80008000, TX_OR); + + /* Check status. */ + if (status != TX_GROUP_ERROR) + { + + /* Event flag error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Set events with a bad option. */ + status = tx_event_flags_set(&group_0, 0x80008000, 14); + + /* Check status. */ + if (status != TX_OPTION_ERROR) + { + + /* Event flag error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Attempt to register the event set notify function with a NULL group pointer. */ + status = tx_event_flags_set_notify(TX_NULL, event_set_notify); + + /* Check status. */ + if (status != TX_GROUP_ERROR) + { + + /* Event flag error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Attempt to register the event set notify function with a non-created group pointer. */ + group_2.tx_event_flags_group_id = 0; + status = tx_event_flags_set_notify(&group_2, event_set_notify); + + /* Check status. */ + if (status != TX_GROUP_ERROR) + { + + /* Event flag error. */ + printf("ERROR #21\n"); + test_control_return(1); + } +#endif + + /* Attempt to get events from an empty event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_EVENTS) + { + + /* Event flag error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + /* Attempt to get events from an empty event flag group. OR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_OR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_EVENTS) + { + + /* Event flag error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Attempt to get events from an empty event flag group. AND CLEAR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND_CLEAR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_EVENTS) + { + + /* Event flag error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Attempt to get events from an empty event flag group. OR CLEAR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_OR_CLEAR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_EVENTS) + { + + /* Event flag error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + + /* Set the necessary events. */ + status = tx_event_flags_set(&group_0, 0x80008000, TX_OR); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + /* Just for fun, clear bit 15. */ + status = tx_event_flags_set(&group_0, 0x80000000, TX_AND); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Set bit 15 again. */ + status = tx_event_flags_set(&group_0, 0x00008000, TX_OR); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #28\n"); + test_control_return(1); + } + + /* Now attemp to retrieve events... */ + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x80008000UL)) + { + + /* Event flag error. */ + printf("ERROR #29\n"); + test_control_return(1); + } + + /* Attempt to get events from event flag group. OR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_OR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x80008000UL)) + { + + /* Event flag error. */ + printf("ERROR #30\n"); + test_control_return(1); + } + + /* Attempt to get events from event flag group. AND CLEAR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND_CLEAR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x80008000UL)) + { + + /* Event flag error. */ + printf("ERROR #31\n"); + test_control_return(1); + } + + /* Attempt to get events from an empty event flag group. OR CLEAR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_OR_CLEAR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_EVENTS) + { + + /* Event flag error. */ + printf("ERROR #32\n"); + test_control_return(1); + } + + /* Put event flags back in the group. */ + + /* Set the necessary events. */ + status = tx_event_flags_set(&group_0, 0x80008000, TX_OR); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #33\n"); + test_control_return(1); + } + + /* Attempt to get events from event flag group. OR CLEAR option. */ + status = tx_event_flags_get(&group_0, 0x00008000, TX_OR_CLEAR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x80008000UL)) + { + + /* Event flag error. */ + printf("ERROR #34\n"); + test_control_return(1); + } + + /* Attempt to get events from event flag group. OR CLEAR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_OR_CLEAR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x80000000UL)) + { + + /* Event flag error. */ + printf("ERROR #35\n"); + test_control_return(1); + } + + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Create a timer for the test. */ + tx_timer_create(&timer_0, "timer 0", timer_entry, 0, 1, 1, TX_AUTO_ACTIVATE); + + /* Setup the ISR. */ + test_isr_dispatch = test_isr; + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Now resume thread 1. */ + tx_thread_resume(&thread_1); + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Clear the ISR. */ + test_isr_dispatch = TX_NULL; + + /* Test for error. */ + if ((error) || (timer_executed != 1) || (isr_executed != 1)) + { + + /* Block memory error. */ + printf("ERROR #36\n"); + test_control_return(1); + } + +#endif + + /* Delete both event flag groups. */ + status = tx_event_flags_delete(&group_0); + + /* Check the status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #37\n"); + test_control_return(1); + } + + status = tx_event_flags_delete(&group_1); + + /* Check the status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #38\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + + while(1) + { + + tx_thread_relinquish(); + } +} + diff --git a/test/tx/regression/threadx_event_flag_information_test.c b/test/tx/regression/threadx_event_flag_information_test.c new file mode 100644 index 00000000..1f03fdf3 --- /dev/null +++ b/test/tx/regression/threadx_event_flag_information_test.c @@ -0,0 +1,562 @@ +/* This test is designed to test the event flag group information gathering services. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_event_flags.h" + + +static TX_THREAD thread_0; + + +static TX_EVENT_FLAGS_GROUP group_0; +static TX_EVENT_FLAGS_GROUP group_1; +static TX_EVENT_FLAGS_GROUP group_2; + + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +UINT _tx_event_flags_performance_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG *sets, ULONG *gets, + ULONG *suspensions, ULONG *timeouts); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void event_set_notify(TX_EVENT_FLAGS_GROUP *group) +{ + + /* Not necessary to do anything in this function. */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_event_flag_information_application_define(void *first_unused_memory) +#endif +{ + +INT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Information Test................................. ERROR #1\n"); + test_control_return(1); + } + + /* Create event flag group 0 and 1. */ + status = tx_event_flags_create(&group_0, "group 0"); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Information Test................................. ERROR #2\n"); + test_control_return(1); + } + + status = tx_event_flags_create(&group_1, "group 1"); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Information Test................................. ERROR #3\n"); + test_control_return(1); + } + + /* Register the event set notify function. */ + status = tx_event_flags_set_notify(&group_0, event_set_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Information Test................................. ERROR #4\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Event Flag Information Test................................. ERROR #5\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual_events; +CHAR *name; +ULONG current_flags; +TX_THREAD *first_suspended; +ULONG suspended_count; +TX_EVENT_FLAGS_GROUP *next_group; +ULONG sets; +ULONG gets; +ULONG suspensions; +ULONG timeouts; + + + /* Inform user. */ + printf("Running Event Flag Information Test................................. "); + + /* Event flags should be created now. */ + + /* Attempt to get events from an empty event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_EVENTS) + { + + /* Event flag error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Attempt to get events from an empty event flag group. OR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_OR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_EVENTS) + { + + /* Event flag error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Attempt to get events from an empty event flag group. AND CLEAR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND_CLEAR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_EVENTS) + { + + /* Event flag error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Attempt to get events from an empty event flag group. OR CLEAR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_OR_CLEAR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_EVENTS) + { + + /* Event flag error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Set the necessary events. */ + status = tx_event_flags_set(&group_0, 0x80008000, TX_OR); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Just for fun, clear bit 15. */ + status = tx_event_flags_set(&group_0, 0x80000000, TX_AND); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Set bit 15 again. */ + status = tx_event_flags_set(&group_0, 0x00008000, TX_OR); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Now attemp to retrieve events... */ + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x80008000UL)) + { + + /* Event flag error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Attempt to get events from event flag group. OR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_OR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x80008000UL)) + { + + /* Event flag error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Attempt to get events from event flag group. AND CLEAR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND_CLEAR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x80008000UL)) + { + + /* Event flag error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Attempt to get events from an empty event flag group. OR CLEAR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_OR_CLEAR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_EVENTS) + { + + /* Event flag error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Put event flags back in the group. */ + + /* Set the necessary events. */ + status = tx_event_flags_set(&group_0, 0x80008000, TX_OR); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Attempt to get events from event flag group. OR CLEAR option. */ + status = tx_event_flags_get(&group_0, 0x00008000, TX_OR_CLEAR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x80008000UL)) + { + + /* Event flag error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Attempt to get events from event flag group. OR CLEAR option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_OR_CLEAR, &actual_events, TX_NO_WAIT); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x80000000UL)) + { + + /* Event flag error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Get information with a NULL pointer. */ + status = tx_event_flags_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_GROUP_ERROR) + { + + /* Event flag error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Get information from a non-created group. */ + group_2.tx_event_flags_group_id = 0; + status = tx_event_flags_info_get(&group_2, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_GROUP_ERROR) + { + + /* Event flag error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + +#endif + + /* Get information about the event flag group. */ + status = tx_event_flags_info_get(&group_0, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_event_flags_info_get(&group_0, &name, ¤t_flags, &first_suspended, &suspended_count, &next_group); + + /* Check the status. */ + if ((status != TX_SUCCESS) || (current_flags != group_0.tx_event_flags_group_current) || (first_suspended != TX_NULL) || (suspended_count != 0) || (next_group != &group_1)) + { + + /* Event flag error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + +#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO + + /* Get performance information with NULL pointer. */ + status = _tx_event_flags_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check the status. */ + if (status != TX_PTR_ERROR) + { + + /* Event flag error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Get performance information on the event flag group. */ + status = tx_event_flags_performance_info_get(&group_0, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_event_flags_performance_info_get(&group_0, &sets, &gets, &suspensions, &timeouts); + + /* Check the status. */ + if ((status != TX_SUCCESS) || (sets != group_0.tx_event_flags_group_performance_set_count) || (gets != group_0.tx_event_flags_group__performance_get_count) || + (suspensions != group_0.tx_event_flags_group___performance_suspension_count) || (timeouts != group_0.tx_event_flags_group____performance_timeout_count)) + { + + /* Event flag error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Get system performance information on all event flags groups. */ + status = tx_event_flags_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_event_flags_performance_system_info_get(&sets, &gets, &suspensions, &timeouts); + + /* Check the status. */ + if ((status != TX_SUCCESS) || (sets != _tx_event_flags_performance_set_count) || (gets != _tx_event_flags_performance_get_count) || + (suspensions != _tx_event_flags_performance_suspension_count) || (timeouts != _tx_event_flags_performance_timeout_count)) + { + + /* Event flag error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + +#else + + /* Get performance information on the event flag group. */ + status = tx_event_flags_performance_info_get(&group_0, &sets, &gets, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Event flag error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + /* Get performance information on the event flag group. */ + status = tx_event_flags_performance_info_get(TX_NULL, &sets, &gets, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Event flag error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Get performance information on the event flag group. */ + status = tx_event_flags_performance_info_get(TX_NULL, TX_NULL, &gets, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Event flag error. */ + printf("ERROR #28\n"); + test_control_return(1); + } + + /* Get performance information on the event flag group. */ + status = tx_event_flags_performance_info_get(TX_NULL, TX_NULL, TX_NULL, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Event flag error. */ + printf("ERROR #29\n"); + test_control_return(1); + } + + /* Get performance information on the event flag group. */ + status = tx_event_flags_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Event flag error. */ + printf("ERROR #30\n"); + test_control_return(1); + } + + /* Get performance information on the event flag group. */ + status = tx_event_flags_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Event flag error. */ + printf("ERROR #31\n"); + test_control_return(1); + } + + /* Get system performance information on all event flags groups. */ + status = tx_event_flags_performance_system_info_get(&sets, &gets, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Event flag error. */ + printf("ERROR #32\n"); + test_control_return(1); + } + + /* Get system performance information on all event flags groups. */ + status = tx_event_flags_performance_system_info_get(TX_NULL, &gets, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Event flag error. */ + printf("ERROR #33\n"); + test_control_return(1); + } + + /* Get system performance information on all event flags groups. */ + status = tx_event_flags_performance_system_info_get(TX_NULL, TX_NULL, &suspensions, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Event flag error. */ + printf("ERROR #34\n"); + test_control_return(1); + } + + /* Get system performance information on all event flags groups. */ + status = tx_event_flags_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, &timeouts); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Event flag error. */ + printf("ERROR #35\n"); + test_control_return(1); + } + + /* Get system performance information on all event flags groups. */ + status = tx_event_flags_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check the status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Event flag error. */ + printf("ERROR #36\n"); + test_control_return(1); + } +#endif + + /* Delete both event flag groups. */ + status = tx_event_flags_delete(&group_0); + + /* Check the status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #37\n"); + test_control_return(1); + } + + status = tx_event_flags_delete(&group_1); + + /* Check the status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #38\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} diff --git a/test/tx/regression/threadx_event_flag_isr_set_clear_test.c b/test/tx/regression/threadx_event_flag_isr_set_clear_test.c new file mode 100644 index 00000000..2d2f28af --- /dev/null +++ b/test/tx/regression/threadx_event_flag_isr_set_clear_test.c @@ -0,0 +1,359 @@ +/* This test is designed to test for simultaneous thread event flag set AND ISR event flag set and clear. */ + +#include <stdio.h> +#include "tx_api.h" + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static unsigned long timer_0_counter = 0; +static TX_TIMER timer_0; + +static unsigned long event_flags_set_counter = 0; +static unsigned long condition_count = 0; + +static TX_EVENT_FLAGS_GROUP event_flags_0; + +extern UINT _tx_thread_preempt_disable; +extern UINT _tx_timer_system_clock; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void timer_0_entry(ULONG timer_input); + + +static void event_set_notify(TX_EVENT_FLAGS_GROUP *group) +{ + + /* Not necessary to do anything in this function. */ +} + + +static void test_isr(void) +{ + +UINT status; +ULONG actual; +static volatile UINT miss_count = 0; + + + /* Determine if the interrupt occurred when the preempt disable flag was set. */ + if (_tx_thread_preempt_disable) + { + + /* Yes this is the condition we are looking for, increment the test condition counter. */ + condition_count++; + } + + /* + It is possible for this test to get into a resonance condition in which + the ISR never occurs while preemption is disabled (especially if the + ISR is installed in the periodic timer interrupt handler, which is + conveniently available). Detect this condition and break out of it by + perturbing the duration of this ISR a pseudo-random amount of time. + */ + else if (++miss_count > 100) + { + for (miss_count = _tx_timer_system_clock % 100; miss_count != 0; --miss_count); + } + + if (((event_flags_0.tx_event_flags_group_current & 0x3) == 0) && + (event_flags_0.tx_event_flags_group_suspended_count == 2)) + { + + /* Put the event_flags to wakeup thread 0. */ + status = tx_event_flags_set(&event_flags_0, 0x3, TX_OR); + + /* Clear the same flags immediately. */ + status += tx_event_flags_set(&event_flags_0, 0xFFFFFFFC, TX_AND); + + /* Setup some event flags just so we can clear them. */ + status += tx_event_flags_set(&event_flags_0, 0x30000, TX_OR); + + /* Clear the same flags immediately. */ + status += tx_event_flags_set(&event_flags_0, 0xFFFEFFFF, TX_AND); + + /* Clear the same flags immediately. */ + status += tx_event_flags_set(&event_flags_0, 0xFFFDFFFC, TX_AND); + + /* Check for an error. */ + if (status) + return; + + /* Get the events from an ISR. */ + status = tx_event_flags_get(&event_flags_0, 0x30000, TX_OR, &actual, TX_NO_WAIT); + + /* Check to make sure this results in an error. */ + if (status != TX_NO_EVENTS) + return; + + /* Do a set and a get consume from an ISR. */ + status = tx_event_flags_set(&event_flags_0, 0x000000C0, TX_OR); + + status += tx_event_flags_get(&event_flags_0, 0x00000080, TX_OR, &actual, TX_NO_WAIT); + + status += tx_event_flags_get(&event_flags_0, 0x000000C0, TX_OR_CLEAR, &actual, TX_NO_WAIT); + + /* Increment the event_flags counter. */ + if ((status == TX_SUCCESS) && (actual == 0xC4)) + { + event_flags_set_counter++; + } + } +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_event_flag_isr_set_clear_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #3\n"); + test_control_return(1); + } + + /* Create event flags group. */ + status = tx_event_flags_create(&event_flags_0, "event_flags 0"); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #4\n"); + test_control_return(1); + } + + /* Create a timer to ensure a context save is called for every interrupt. */ + status = tx_timer_create(&timer_0, "timer 0", timer_0_entry, 0, 1, 1, TX_AUTO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #5\n"); + test_control_return(1); + } + + /* Register the event set notify function. */ + status = tx_event_flags_set_notify(&event_flags_0, event_set_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #6\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #7\n"); + test_control_return(1); + } + +#endif +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual; + + + /* Inform user. */ + printf("Running Event Flag Set/Clear from ISR Test.......................... "); + + /* Setup the test ISR. */ + test_isr_dispatch = test_isr; + + /* Loop to exploit the probability window inside tx_event_flags_set call. */ + while (condition_count < 40) + { + + /* Suspend on the event_flags that is going to be set via the ISR. */ + status = tx_event_flags_get(&event_flags_0, 2, TX_OR_CLEAR, &actual, 4); + + /* Determine if we have an unexpected result. */ + if (status != TX_SUCCESS) + { + + /* Test error! */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Check for the preempt disable flag being set. */ + if (_tx_thread_preempt_disable) + { + + /* Test error! */ + printf("ERROR #9\n"); + test_control_return(2); + } + + /* Determine if we really got the event_flags. */ + if (status == TX_SUCCESS) + { + + /* Increment the thread count. */ + thread_0_counter++; + } + } + + /* Setup the test ISR. */ + test_isr_dispatch = TX_NULL; + + /* Let the other threads run once more... */ + tx_thread_relinquish(); + + /* At this point, check to see if we got all the event_flagss! */ + if ((thread_0_counter != event_flags_set_counter) || + (thread_1_counter != event_flags_set_counter)) + { + + /* Test error! */ + printf("ERROR #10\n"); + test_control_return(3); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual; + + + /* Loop to exploit the probability window inside tx_event_flags_set call. */ + while (1) + { + + /* Suspend on the event_flags that is going to be set via the ISR. */ + status = tx_event_flags_get(&event_flags_0, 1, TX_OR_CLEAR, &actual, 4); + + /* Determine if we have an unexpected result. */ + if (status != TX_SUCCESS) + { + + break; + } + + /* Increment this thread's counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + + /* Loop forever! */ + while(1) + { + + + /* Set event flags - not the one needed by threads 0 and 1. */ + tx_event_flags_set(&event_flags_0, 0x4, TX_OR); + + /* Increment the thread counter. */ + thread_2_counter++; + + /* Let thread 0 run again! */ + tx_thread_relinquish(); + } +} + + +static void timer_0_entry(ULONG input) +{ + timer_0_counter++; +} + + diff --git a/test/tx/regression/threadx_event_flag_isr_wait_abort_test.c b/test/tx/regression/threadx_event_flag_isr_wait_abort_test.c new file mode 100644 index 00000000..1c9bf5d2 --- /dev/null +++ b/test/tx/regression/threadx_event_flag_isr_wait_abort_test.c @@ -0,0 +1,331 @@ +/* This test is designed to test for wait abort from an ISR. */ + +#include <stdio.h> +#include "tx_api.h" + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static unsigned long timer_0_counter = 0; +static TX_TIMER timer_0; + +static unsigned long event_flags_wait_abort_counter = 0; +static unsigned long condition_count = 0; + +static TX_EVENT_FLAGS_GROUP event_flags_0; + +extern UINT _tx_thread_preempt_disable; +extern UINT _tx_timer_system_clock; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void timer_0_entry(ULONG timer_input); + + +static void event_set_notify(TX_EVENT_FLAGS_GROUP *group) +{ + + /* Not necessary to do anything in this function. */ +} + + +static void test_isr(void) +{ + +UINT status; +static volatile UINT miss_count = 0; + + + /* Determine if the interrupt occurred when the preempt disable flag was set. */ + if (_tx_thread_preempt_disable) + { + + /* Yes this is the condition we are looking for, increment the test condition counter. */ + condition_count++; + } + + /* + It is possible for this test to get into a resonance condition in which + the ISR never occurs while preemption is disabled (especially if the + ISR is installed in the periodic timer interrupt handler, which is + conveniently available). Detect this condition and break out of it by + perturbing the duration of this ISR a pseudo-random amount of time. + */ + else if (++miss_count > 100) + { + for (miss_count = _tx_timer_system_clock % 100; miss_count != 0; --miss_count); + } + + if (((event_flags_0.tx_event_flags_group_current & 0x3) == 0) && + (event_flags_0.tx_event_flags_group_suspended_count == 2)) + { + + /* Set event flags - not the one needed by threads 0 and 1. */ + status = tx_event_flags_set(&event_flags_0, 0x4, TX_OR); + + /* Abort the threads 1 and 2. */ + status += tx_thread_wait_abort(&thread_0); + status += tx_thread_wait_abort(&thread_1); + + if (status == TX_SUCCESS) + { + + event_flags_wait_abort_counter++; + } + } +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_event_flag_isr_wait_abort_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Wait Abort from ISR Test......................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Wait Abort from ISR Test......................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Wait Abort from ISR Test......................... ERROR #3\n"); + test_control_return(1); + } + + /* Create event flags group. */ + status = tx_event_flags_create(&event_flags_0, "event_flags 0"); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Wait Abort from ISR Test......................... ERROR #4\n"); + test_control_return(1); + } + + /* Create a timer to ensure a context save is called for every interrupt. */ + status = tx_timer_create(&timer_0, "timer 0", timer_0_entry, 0, 1, 1, TX_AUTO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Wait Abort from ISR Test......................... ERROR #5\n"); + test_control_return(1); + } + + /* Register the event set notify function. */ + status = tx_event_flags_set_notify(&event_flags_0, event_set_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Wait Abort from ISR Test......................... ERROR #6\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Event Flag Wait Abort from ISR Test......................... ERROR #7\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual; + + + /* Inform user. */ + printf("Running Event Flag Wait Abort from ISR Test......................... "); + + /* Setup the test ISR. */ + test_isr_dispatch = test_isr; + + /* Loop to exploit the probability window inside tx_event_flags_set call. */ + while (condition_count < 40) + { + + /* Suspend on the event_flags that is going to be set via the ISR. */ + status = tx_event_flags_get(&event_flags_0, 2, TX_OR_CLEAR, &actual, 4); + + /* Determine if we have an unexpected result. */ + if (status != TX_WAIT_ABORTED) + { + + /* Test error! */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Check for the preempt disable flag being set. */ + if (_tx_thread_preempt_disable) + { + + /* Test error! */ + printf("ERROR #9\n"); + test_control_return(2); + } + + /* Determine if we really got the event_flags. */ + if (status == TX_WAIT_ABORTED) + { + + /* Increment the thread count. */ + thread_0_counter++; + } + } + + /* Setup the test ISR. */ + test_isr_dispatch = TX_NULL; + + /* Let the other threads run once more... */ + tx_thread_relinquish(); + + /* At this point, check to see if we got all the event_flagss! */ + if ((thread_0_counter != event_flags_wait_abort_counter) || + (thread_1_counter != event_flags_wait_abort_counter)) + { + + /* Test error! */ + printf("ERROR #10\n"); + test_control_return(3); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual; + + + /* Loop to exploit the probability window inside tx_event_flags_set call. */ + while (1) + { + + /* Suspend on the event_flags that is going to be set via the ISR. */ + status = tx_event_flags_get(&event_flags_0, 1, TX_OR_CLEAR, &actual, 4); + + /* Determine if we have an unexpected result. */ + if (status != TX_WAIT_ABORTED) + { + + break; + } + + /* Increment this thread's counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + + /* Loop forever! */ + while(1) + { + + + /* Set event flags - not the one needed by threads 0 and 1. */ + tx_event_flags_set(&event_flags_0, 0x4, TX_OR); + + /* Increment the thread counter. */ + thread_2_counter++; + + /* Let thread 0 run again! */ + tx_thread_relinquish(); + } +} + + +static void timer_0_entry(ULONG input) +{ + timer_0_counter++; +} diff --git a/test/tx/regression/threadx_event_flag_single_thread_terminate_test.c b/test/tx/regression/threadx_event_flag_single_thread_terminate_test.c new file mode 100644 index 00000000..a5db6e41 --- /dev/null +++ b/test/tx/regression/threadx_event_flag_single_thread_terminate_test.c @@ -0,0 +1,331 @@ +/* This test is designed to test event flag suspension with a single suspended thread + being terminated at the same priority level. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + + +extern UINT _tx_thread_preempt_disable; + +static TX_EVENT_FLAGS_GROUP group_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +static void event_set_notify(TX_EVENT_FLAGS_GROUP *group) +{ + + /* Not necessary to do anything in this function. */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_event_flag_single_thread_terminate_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Single Thread Terminate Test..................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Single Thread Terminate Test..................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Single Thread Terminate Test..................... ERROR #3\n"); + test_control_return(1); + } + + /* Create event flag group 0. */ + status = tx_event_flags_create(&group_0, "group 0"); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Single Thread Terminate Test..................... ERROR #4\n"); + test_control_return(1); + } + + /* Register the event set notify function. */ + status = tx_event_flags_set_notify(&group_0, event_set_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Single Thread Terminate Test..................... ERROR #5\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Event Flag Single Thread Terminate Test..................... ERROR #6\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Event Flag Single Thread Terminate Test..................... "); + + /* Increment run counter. */ + thread_0_counter++; + + /* Sleep to allow lower-priority thread 1 to run. */ + tx_thread_sleep(5); + + /* Resume Thread 2. */ + status = tx_thread_resume(&thread_2); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Now terminate thread 1. */ + status = tx_thread_terminate(&thread_1); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Now sleep to allow Thread 2 to run. */ + tx_thread_sleep(5); + + /* Set only one of the event flags needed. */ + status = tx_event_flags_set(&group_0, 0x00080000, TX_OR); + + /* Now sleep to allow thread 2 to run. */ + tx_thread_sleep(5); + + /* Check status. */ + if ((status != TX_SUCCESS) && (thread_2_counter != 1)) + { + + /* Event flag error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Set the other event flag needed. */ + status = tx_event_flags_set(&group_0, 0x00800000, TX_OR); + + /* Now sleep to allow thread 2 to run. */ + tx_thread_sleep(5); + + /* Check status. */ + if ((status != TX_SUCCESS) && (thread_2_counter != 2)) + { + + /* Event flag error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* At this point, thread 2 is suspended on the flags again. Or some flags that are + not needed. */ + + /* Set an event flag that is not needed. */ + status = tx_event_flags_set(&group_0, 0x00000001, TX_OR); + + /* Now sleep to allow thread 2 to run. */ + tx_thread_sleep(5); + + /* Check status. */ + if ((status != TX_SUCCESS) && (thread_2_counter != 2)) + { + + /* Event flag error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Set an event flag that is needed. */ + status = tx_event_flags_set(&group_0, 0x00080001, TX_OR); + + /* Now sleep to allow thread 2 to run. */ + tx_thread_sleep(5); + + /* Check status and run counters. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 3) || + (_tx_thread_preempt_disable)) + { + + /* Event flag error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Terminate thread 2. */ + status = tx_thread_terminate(&thread_2); + + /* Check status. */ + if ((status != TX_SUCCESS) || (thread_2_counter != 3)) + { + + /* Event flag error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_1_counter++; + + /* Self suspend thread. */ + status = tx_thread_suspend(&thread_1); + + /* Check status. */ + if (status != TX_SUCCESS) + { + thread_1_counter = 0; /* Make an error! */ + return; + } + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_2_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x000880000, TX_AND_CLEAR, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + return; + + /* Increment run counter. */ + thread_2_counter++; + + /* Attempt to get events from event flag group. OR option. */ + status = tx_event_flags_get(&group_0, 0x000880000, TX_OR_CLEAR, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + return; + + /* Increment run counter. */ + thread_2_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x000880000, TX_AND_CLEAR, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_NO_EVENTS) + return; + } +} + diff --git a/test/tx/regression/threadx_event_flag_suspension_consume_test.c b/test/tx/regression/threadx_event_flag_suspension_consume_test.c new file mode 100644 index 00000000..b83a8123 --- /dev/null +++ b/test/tx/regression/threadx_event_flag_suspension_consume_test.c @@ -0,0 +1,281 @@ +/* This test is designed to test event flag suspension and resumption of two threads + waiting on the same event flag set with the consumption. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + + +static TX_EVENT_FLAGS_GROUP group_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +static void event_set_notify(TX_EVENT_FLAGS_GROUP *group) +{ + + /* Not necessary to do anything in this function. */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_event_flag_suspension_consume_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension/Consumption Test...................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension/Consumption Test...................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension/Consumption Test...................... ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension/Consumption Test...................... ERROR #4\n"); + test_control_return(1); + } + + /* Create event flag group 0. */ + status = tx_event_flags_create(&group_0, "group 0"); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension/Consumption Test...................... ERROR #5\n"); + test_control_return(1); + } + + /* Register the event set notify function. */ + status = tx_event_flags_set_notify(&group_0, event_set_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension/Consumption Test...................... ERROR #6\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Event Flag Suspension/Consumption Test...................... ERROR #7\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG event_flag = 1; +int i; + + + /* Inform user. */ + printf("Running Event Flag Suspension/Consumption Test...................... "); + + /* Set all event flags. */ + for (i = 0; i < 32; i++) + { + + /* Increment run counter. */ + thread_0_counter++; + + /* Set event flag. */ + status = tx_event_flags_set(&group_0, event_flag, TX_OR); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Check the thread counters... */ + if ((i < 31) && ((thread_1_counter != 1) || (thread_2_counter != 1) || (thread_3_counter != 1))) + { + + /* Event flag error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + if ((i == 31) && ((thread_1_counter != 2) || (thread_2_counter != 2) || (thread_3_counter != 2))) + { + + /* Event flag error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Shift event flag up one bit. */ + event_flag = event_flag << 1; + + /* Check for 0. */ + if (event_flag == 0) + event_flag = 1; + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +//ULONG event_flag = 1; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_1_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND_CLEAR, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0xFFFFFFFFUL)) + return; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +//ULONG event_flag = 1; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_2_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0xFFFFFFFFUL)) + return; + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + +UINT status; +//ULONG event_flag = 1; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_3_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0xFFFFFFFFUL)) + return; + } +} + diff --git a/test/tx/regression/threadx_event_flag_suspension_different_bits_consume_test.c b/test/tx/regression/threadx_event_flag_suspension_different_bits_consume_test.c new file mode 100644 index 00000000..fa4a985a --- /dev/null +++ b/test/tx/regression/threadx_event_flag_suspension_different_bits_consume_test.c @@ -0,0 +1,224 @@ +/* This test is designed to test event flag suspension and resumption of two threads + waiting on different event flags with consumption. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + + +static TX_EVENT_FLAGS_GROUP group_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +static void event_set_notify(TX_EVENT_FLAGS_GROUP *group) +{ + + /* Not necessary to do anything in this function. */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_event_flag_suspension_different_bits_consume_application_define(void *first_unused_memory) +#endif +{ + +INT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension/Consumption Unique Bit Test........... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension/Consumption Unique Bit Test........... ERROR #2\n"); + test_control_return(1); + } + + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension/Consumption Unique Bit Test........... ERROR #3\n"); + test_control_return(1); + } + + /* Create event flag group 0. */ + status = tx_event_flags_create(&group_0, "group 0"); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension/Consumption Unique Bit Test........... ERROR #4\n"); + test_control_return(1); + } + + /* Register the event set notify function. */ + status = tx_event_flags_set_notify(&group_0, event_set_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension/Consumption Unique Bit Test........... ERROR #5\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Event Flag Suspension/Consumption Unique Bit Test........... ERROR #6\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Event Flag Suspension/Consumption Unique Bit Test........... "); + + /* Increment run counter. */ + thread_0_counter++; + + /* Set event flag. */ + status = tx_event_flags_set(&group_0, 0x80000000, TX_OR); + + /* Check status and run counters. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 2) || + (thread_2_counter != 1)) + { + + /* Event flag error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Set event flag. */ + status = tx_event_flags_set(&group_0, 0x00008000, TX_OR); + + /* Check status. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 2) || + (thread_2_counter != 2)) + { + + /* Event flag error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_1_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80000000, TX_AND_CLEAR, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x80000000UL)) + return; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +//ULONG event_flag = 1; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_2_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x00008000, TX_AND_CLEAR, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x00008000UL)) + return; + } +} + diff --git a/test/tx/regression/threadx_event_flag_suspension_different_bits_test.c b/test/tx/regression/threadx_event_flag_suspension_different_bits_test.c new file mode 100644 index 00000000..92505744 --- /dev/null +++ b/test/tx/regression/threadx_event_flag_suspension_different_bits_test.c @@ -0,0 +1,230 @@ +/* This test is designed to test event flag suspension and resumption of two threads + waiting on different event flags. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + + +static TX_EVENT_FLAGS_GROUP group_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +static void event_set_notify(TX_EVENT_FLAGS_GROUP *group) +{ + + /* Not necessary to do anything in this function. */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_event_flag_suspension_different_bits_application_define(void *first_unused_memory) +#endif +{ + +INT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Unique Bit Test....................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Unique Bit Test....................... ERROR #2\n"); + test_control_return(1); + } + + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Unique Bit Test....................... ERROR #3\n"); + test_control_return(1); + } + + /* Create event flag group 0. */ + status = tx_event_flags_create(&group_0, "group 0"); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Unique Bit Test....................... ERROR #4\n"); + test_control_return(1); + } + + /* Register the event set notify function. */ + status = tx_event_flags_set_notify(&group_0, event_set_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Unique Bit Test....................... ERROR #5\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Event Flag Suspension Unique Bit Test....................... ERROR #6\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Event Flag Suspension Unique Bit Test....................... "); + + /* Increment run counter. */ + thread_0_counter++; + + /* Set event flag. */ + status = tx_event_flags_set(&group_0, 0x80000000, TX_OR); + + /* Check status and run counters. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 2) || + (thread_2_counter != 1)) + { + + /* Event flag error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Set event flag. */ + status = tx_event_flags_set(&group_0, 0x00008000, TX_OR); + + /* Check status. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 2) || + (thread_2_counter != 2)) + { + + /* Event flag error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_1_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80000000, TX_AND, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x80000000UL)) + return; + + /* Clear the event flags. */ + tx_event_flags_set(&group_0, 0x7FFFFFFF, TX_AND); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +//ULONG event_flag = 1; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_2_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x00008000, TX_AND, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x00008000UL)) + return; + + /* Clear the event flags. */ + tx_event_flags_set(&group_0, 0xFFFF7FFF, TX_AND); + } +} + diff --git a/test/tx/regression/threadx_event_flag_suspension_test.c b/test/tx/regression/threadx_event_flag_suspension_test.c new file mode 100644 index 00000000..3587fadd --- /dev/null +++ b/test/tx/regression/threadx_event_flag_suspension_test.c @@ -0,0 +1,349 @@ +/* This test is designed to test event flag suspension and resumption of three threads + waiting on the same event flag set. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; +static unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; + + +static TX_EVENT_FLAGS_GROUP group_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +static void event_set_notify(TX_EVENT_FLAGS_GROUP *group) +{ + + /* Not necessary to do anything in this function. */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_event_flag_suspension_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Same Bit Test......................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Same Bit Test......................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Same Bit Test......................... ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Same Bit Test......................... ERROR #4\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Same Bit Test......................... ERROR #5\n"); + test_control_return(1); + } + + /* Create event flag group 0. */ + status = tx_event_flags_create(&group_0, "group 0"); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Same Bit Test......................... ERROR #6\n"); + test_control_return(1); + } + + /* Register the event set notify function. */ + status = tx_event_flags_set_notify(&group_0, event_set_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Same Bit Test......................... ERROR #7\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Event Flag Suspension Same Bit Test......................... ERROR #8\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG event_flag = 1; +int i; + + + /* Inform user. */ + printf("Running Event Flag Suspension Same Bit Test......................... "); + + /* Set all event flags. */ + for (i = 0; i < 32; i++) + { + + /* Increment run counter. */ + thread_0_counter++; + + /* Set event flag. */ + status = tx_event_flags_set(&group_0, event_flag, TX_OR); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Check the thread counters... */ + if ((i < 31) && ((thread_1_counter != 1) || (thread_2_counter != 1) || (thread_3_counter != 1))) + { + + /* Event flag error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + if ((i == 31) && ((thread_1_counter != 2) || (thread_2_counter != 2) || (thread_3_counter != 2))) + { + + /* Event flag error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Shift event flag up one bit. */ + event_flag = event_flag << 1; + + /* Check for 0. */ + if (event_flag == 0) + event_flag = 1; + } + + /* Set the event flags to 0. */ + status = tx_event_flags_set(&group_0, 0x0, TX_AND); + + /* Resume thread 4 so it can suspend on the event flag group too. */ + status += tx_thread_resume(&thread_4); + + /* Determine if there was an error. */ + if ((status != TX_SUCCESS) || (thread_4_counter != 1)) + { + + /* Event flag error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Now set the event flag that only thread 4 is waiting on to ensure that we are not satisfying the first thread on the list. */ + status = tx_event_flags_set(&group_0, 0x1, TX_OR); + + /* Determine if there was an error. */ + if ((status != TX_SUCCESS) || (thread_4_counter != 2)) + { + + /* Event flag error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +//ULONG event_flag = 1; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_1_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0xFFFFFFFFUL)) + return; + + /* Clear the event flags. */ + tx_event_flags_set(&group_0, 0, TX_AND); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +//ULONG event_flag = 1; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_2_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0xFFFFFFFFUL)) + return; + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + +UINT status; +//ULONG event_flag = 1; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_3_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80008000, TX_AND, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0xFFFFFFFFUL)) + return; + } +} + + +static void thread_4_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_4_counter++; + + /* Attempt to get events from event flag group. OR option. */ + status = tx_event_flags_get(&group_0, 0x00000001, TX_OR_CLEAR, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_events != 0x1UL)) + return; + } +} diff --git a/test/tx/regression/threadx_event_flag_suspension_timeout_test.c b/test/tx/regression/threadx_event_flag_suspension_timeout_test.c new file mode 100644 index 00000000..2fed61c0 --- /dev/null +++ b/test/tx/regression/threadx_event_flag_suspension_timeout_test.c @@ -0,0 +1,266 @@ +/* This test is designed to test event flag suspension timeout processing. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + + +static TX_EVENT_FLAGS_GROUP group_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +static void event_set_notify(TX_EVENT_FLAGS_GROUP *group) +{ + + /* Not necessary to do anything in this function. */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_event_flag_suspension_timeout_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Timeout Test.......................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Timeout Test.......................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Timeout Test.......................... ERROR #3\n"); + test_control_return(1); + } + + /* Create event flag group 0. */ + status = tx_event_flags_create(&group_0, "group 0"); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Timeout Test.......................... ERROR #4\n"); + test_control_return(1); + } + + /* Register the event set notify function. */ + status = tx_event_flags_set_notify(&group_0, event_set_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Suspension Timeout Test.......................... ERROR #5\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Event Flag Suspension Timeout Test.......................... ERROR #6\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +ULONG actual_events; +UINT status; + + + /* Inform user. */ + printf("Running Event Flag Suspension Timeout Test.......................... "); + + /* Increment run counter. */ + thread_0_counter++; + + /* Set event flag 0. */ + tx_event_flags_set(&group_0, 0x00000001, TX_OR); + + /* Resume thread 3. */ + tx_thread_resume(&thread_3); + tx_thread_sleep(1); /* Thread 3 should now be suspended on group 0. */ + tx_event_flags_set(&group_0, 0x00000002, TX_OR); + + /* Start everything on a new timer. */ + tx_thread_sleep(2); + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + tx_thread_sleep(1); + status = tx_event_flags_get(&group_0, 0x00000001, TX_AND_CLEAR, &actual_events, TX_WAIT_FOREVER); + + /* Check the status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #6a\n"); + test_control_return(1); + } + + /* Sleep for 63 ticks. */ + tx_thread_sleep(63); + + /* Check the run counters. */ + if ((thread_1_counter != 33) || (thread_2_counter != 13)) + { + + /* Event flag error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual_events; + + + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_1_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80000000, TX_AND_CLEAR, &actual_events, 2); + + /* Check status. */ + if (status != TX_NO_EVENTS) + return; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +//ULONG event_flag = 1; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_2_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x00008000, TX_AND_CLEAR, &actual_events, 5); + + /* Check status. */ + if (status != TX_NO_EVENTS) + return; + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + +UINT status; +//ULONG event_flag = 1; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_3_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x00000002, TX_AND, &actual_events, 5); + + /* Check status. */ + if (status != TX_NO_EVENTS) + return; + } +} diff --git a/test/tx/regression/threadx_event_flag_thread_terminate_test.c b/test/tx/regression/threadx_event_flag_thread_terminate_test.c new file mode 100644 index 00000000..eecb76e6 --- /dev/null +++ b/test/tx/regression/threadx_event_flag_thread_terminate_test.c @@ -0,0 +1,234 @@ +/* This test is designed to test event flag suspension with the suspended threads + being terminated. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + + +static TX_EVENT_FLAGS_GROUP group_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +static void event_set_notify(TX_EVENT_FLAGS_GROUP *group) +{ + + /* Not necessary to do anything in this function. */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_event_flag_thread_terminate_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Thread Terminate Test............................ ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Thread Terminate Test............................ ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Thread Terminate Test............................ ERROR #3\n"); + test_control_return(1); + } + + /* Create event flag group 0. */ + status = tx_event_flags_create(&group_0, "group 0"); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Thread Terminate Test............................ ERROR #4\n"); + test_control_return(1); + } + + /* Register the event set notify function. */ + status = tx_event_flags_set_notify(&group_0, event_set_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Event Flag Thread Terminate Test............................ ERROR #5\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Event Flag Thread Terminate Test............................ ERROR #6\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Event Flag Thread Terminate Test............................ "); + + /* Increment run counter. */ + thread_0_counter++; + + /* Terminate thread 2. */ + status = tx_thread_terminate(&thread_2); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Terminate thread 1. */ + status = tx_thread_terminate(&thread_1); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Event flag error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Set event flags to make sure no threads are suspended. */ + status = tx_event_flags_set(&group_0, 0xFFFFFFFF, TX_OR); + + /* Check status and run counters. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 1)) + { + + /* Event flag error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_1_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x80000000, TX_AND_CLEAR, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_NO_EVENTS) + return; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +//ULONG event_flag = 1; +ULONG actual_events; + + /* Wait for event flags. */ + while(1) + { + + /* Increment run counter. */ + thread_2_counter++; + + /* Attempt to get events from event flag group. AND option. */ + status = tx_event_flags_get(&group_0, 0x00008000, TX_AND_CLEAR, &actual_events, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_NO_EVENTS) + return; + } +} + diff --git a/test/tx/regression/threadx_initialize_kernel_setup_test.c b/test/tx/regression/threadx_initialize_kernel_setup_test.c new file mode 100644 index 00000000..f248694d --- /dev/null +++ b/test/tx/regression/threadx_initialize_kernel_setup_test.c @@ -0,0 +1,81 @@ +/* This test is designed to test kernel setup functionality in ThreadX. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" + + +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 test_initialize_flag; +TEST_FLAG threadx_byte_release_loop_test; +TEST_FLAG test_stack_analyze_flag; + + +/* 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; + + +__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) +{ +} + +void main() +{ + + /* Setup the ThreadX kernel. */ + _tx_initialize_kernel_setup(); + + if (_tx_thread_system_state == TX_INITIALIZE_ALMOST_DONE) + { + printf("Running Initialize Kernel Setup Test................................ SUCCESS!\n"); + exit(0); + } + else + { + printf("Running Initialize Kernel Setup Test................................ ERROR!\n"); + exit(1); + } +} + +void test_application_define(void *first_unused_memory){} +void tx_application_define(void *first_unused_memory){} + + +#ifndef TX_TIMER_PROCESS_IN_ISR + +/* Define the deletion of the system timer thread. */ + +extern TX_THREAD _tx_timer_thread; +TEST_FLAG threadx_delete_timer_thread; +void delete_timer_thread(void) +{ + + _tx_thread_terminate(&_tx_timer_thread); + _tx_thread_delete(&_tx_timer_thread); +} + +#endif
\ No newline at end of file diff --git a/test/tx/regression/threadx_interrupt_control_test.c b/test/tx/regression/threadx_interrupt_control_test.c new file mode 100644 index 00000000..d58ceba3 --- /dev/null +++ b/test/tx/regression/threadx_interrupt_control_test.c @@ -0,0 +1,94 @@ +/* This test is designed to test the interrupt control service call avaialbe to the + application. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_interrupt_control_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Interrupt Control Test...................................... ERROR #1\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT saved_interrupt_posture; + + + /* Inform user. */ + printf("Running Interrupt Control Test...................................... "); + + /* Lockout interrupts. */ + saved_interrupt_posture = tx_interrupt_control(TX_INT_DISABLE); + + /* Increment the thread counter. */ + thread_0_counter++; + + /* Restore interrupts. */ + saved_interrupt_posture = tx_interrupt_control(saved_interrupt_posture); + + /* Sleep to make sure interrupts now work. */ + tx_thread_sleep(2); + + /* Check to make sure the returned interrupt type works. */ + if (saved_interrupt_posture != TX_INT_DISABLE) + { + + /* Interrupt control error. */ + printf("ERROR #2\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + diff --git a/test/tx/regression/threadx_mutex_basic_test.c b/test/tx/regression/threadx_mutex_basic_test.c new file mode 100644 index 00000000..2e784961 --- /dev/null +++ b/test/tx/regression/threadx_mutex_basic_test.c @@ -0,0 +1,767 @@ +/* This test is designed to test the mutex create/delete and immediate + return gets and puts. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_mutex.h" + + +typedef struct MUTEX_MEMORY_TEST_STRUCT +{ + ULONG first; + ULONG second; + TX_MUTEX mutex; + ULONG next_to_last; + ULONG last; + +} MUTEX_MEMORY_TEST; + +static MUTEX_MEMORY_TEST mutex_memory; + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +static unsigned long thread_0_counter = 0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_0; +static TX_THREAD thread_1; +static TX_THREAD thread_2; +static TX_THREAD thread_3; +static TX_THREAD thread_4; + +static TX_MUTEX mutex_0; +static TX_MUTEX mutex_1; +static TX_MUTEX mutex_2; +static TX_MUTEX mutex_3; +static TX_MUTEX mutex_4; +static TX_MUTEX mutex_5; +static TX_MUTEX mutex_6; +static TX_MUTEX mutex_7; +static TX_MUTEX mutex_8; + +static TX_TIMER timer_0; + + +static unsigned long error = 0; +static unsigned long timer_executed = 0; +static unsigned long isr_executed = 0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); + +UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define the timer for this test. */ + +static void timer_entry(ULONG i) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +UINT status; + + /* Attempt to create a mutex from a timer. */ + status = tx_mutex_create(&mutex_4, "mutex 4", TX_NO_INHERIT); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to delete a mutex from a timer. */ + status = tx_mutex_delete(&mutex_2); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to get from mutex from a timer with suspension. */ + status = tx_mutex_get(&mutex_2, 100); + + /* Check status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + timer_executed = 1; +#endif +} + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +UINT status; + + + /* Attempt to create a mutex from an ISR. */ + status = tx_mutex_create(&mutex_4, "mutex 4", TX_NO_INHERIT); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to delete a mutex from an ISR. */ + status = tx_mutex_delete(&mutex_2); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to get from mutex from an ISR with suspension. */ + status = tx_mutex_get(&mutex_2, 100); + + /* Check status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to get from mutex from an ISR without suspension. */ + status = tx_mutex_get(&mutex_2, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to put a mutex from an ISR. */ + status = tx_mutex_put(&mutex_2); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + isr_executed = 1; +#endif +} + + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_mutex_basic_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + + status += tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + status += tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + status += tx_thread_create(&thread_3, "thread 3", thread_3_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + status += tx_thread_create(&thread_4, "thread 4", thread_4_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Basic Test............................................ ERROR #1\n"); + test_control_return(1); + } + + /* Create a mutex. */ + status = tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Basic Test............................................ ERROR #2\n"); + test_control_return(1); + } + + /* Create another mutex. */ + status = tx_mutex_create(&mutex_1, "mutex 1", TX_NO_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Basic Test............................................ ERROR #3\n"); + test_control_return(1); + } + + /* Create another mutex. */ + status = tx_mutex_create(&mutex_2, "mutex 2", TX_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Basic Test............................................ ERROR #4\n"); + test_control_return(1); + } + + /* Create another mutex. */ + status = tx_mutex_create(&mutex_3, "mutex 3", TX_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Basic Test............................................ ERROR #5\n"); + test_control_return(1); + } + + /* Create another mutex. */ + status = tx_mutex_create(&mutex_8, "mutex 8", TX_NO_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Basic Test............................................ ERROR #5a\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Mutex Basic Test............................................ "); + + /* Perform mutex memory test. */ + mutex_memory.first = 0x11223344; + mutex_memory.second = 0x55667788; + mutex_memory.next_to_last = 0x99aabbcc; + mutex_memory.last = 0xddeeff00; + + /* Create the semaphore. */ + status = tx_mutex_create(&mutex_memory.mutex, "mutex memory", TX_INHERIT); + tx_mutex_delete(&mutex_memory.mutex); + + /* Check for status. */ + if ((status != TX_SUCCESS) || + (mutex_memory.first != 0x11223344) || + (mutex_memory.second != 0x55667788) || + (mutex_memory.next_to_last != 0x99aabbcc) || + (mutex_memory.last != 0xddeeff00)) + { + + /* Mutex error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Increment thread 0 counter. */ + thread_0_counter++; + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to create a mutex with a NULL pointer. */ + status = tx_mutex_create(TX_NULL, "mutex 2", TX_INHERIT); + + /* Check status. */ + if (status != TX_MUTEX_ERROR) + { + + /* Mutex error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Attempt to create a mutex with a bad size. */ + status = _txe_mutex_create(&mutex_5, "mutex 5", TX_INHERIT, (sizeof(TX_MUTEX)+1)); + + /* Check status. */ + if (status != TX_MUTEX_ERROR) + { + + /* Mutex error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Attempt to create a mutex that has already been created. */ + status = tx_mutex_create(&mutex_2, "mutex 2", TX_INHERIT); + + /* Check status. */ + if (status != TX_MUTEX_ERROR) + { + + /* Mutex error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to create a mutex with a bad inheritance option. */ + status = tx_mutex_create(&mutex_4, "mutex 4", 14); + + /* Check status. */ + if (status != TX_INHERIT_ERROR) + { + + /* Mutex error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Attempt to delete a mutex with a NULL pointer. */ + status = tx_mutex_delete(TX_NULL); + + /* Check status. */ + if (status != TX_MUTEX_ERROR) + { + + /* Mutex error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Attempt to delete a non-created mutex. */ + mutex_4.tx_mutex_id = 0; + status = tx_mutex_delete(&mutex_4); + + /* Check status. */ + if (status != TX_MUTEX_ERROR) + { + + /* Mutex error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Attempt to get a mutex with a NULL pointer. */ + status = tx_mutex_get(TX_NULL, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_MUTEX_ERROR) + { + + /* Mutex error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Attempt to get a non-created mutex. */ + mutex_4.tx_mutex_id = 0; + status = tx_mutex_get(&mutex_4, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_MUTEX_ERROR) + { + + /* Mutex error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Attempt to put a NULL mutex. */ + status = tx_mutex_put(TX_NULL); + + /* Check status. */ + if (status != TX_MUTEX_ERROR) + { + + /* Mutex error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Attempt to put a non-created mutex. */ + mutex_4.tx_mutex_id = 0; + status = tx_mutex_put(&mutex_4); + + /* Check status. */ + if (status != TX_MUTEX_ERROR) + { + + /* Mutex error. */ + printf("ERROR #16\n"); + test_control_return(1); + } +#endif + + /* Attempt to get from mutex that is available. Should be successful! */ + status = tx_mutex_get(&mutex_0, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Attempt to get the same mutex again. Should be successful! */ + status = tx_mutex_get(&mutex_0, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Put the mutex. */ + status = tx_mutex_put(&mutex_0); + + /* Check status. */ + if ((status != TX_SUCCESS) || (mutex_0.tx_mutex_ownership_count != 1)) + { + + /* Mutex error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Put the mutex again. Should be successful! */ + status = tx_mutex_put(&mutex_0); + + /* Check status. */ + if ((status != TX_SUCCESS) != (mutex_0.tx_mutex_owner != TX_NULL)) + { + + /* Mutex error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Relinquish to allow other thread to get the mutex. */ + tx_thread_relinquish(); + + /* Attempt to get the mutex. Should be unsuccessful. */ + status = tx_mutex_get(&mutex_1, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NOT_AVAILABLE) + { + + /* Mutex error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + /* Relinquish again so that the other thread can release it. */ + tx_thread_relinquish(); + + /* Delete mutex. */ + status = tx_mutex_delete(&mutex_0); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + status = tx_mutex_delete(&mutex_1); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Attempt to get a priority inheritance mutex. */ + status = tx_mutex_get(&mutex_2, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Attempt to get another priority inheritance mutex. */ + status = tx_mutex_get(&mutex_3, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Create a timer for the test. */ + tx_timer_create(&timer_0, "timer 0", timer_entry, 0, 1, 1, TX_AUTO_ACTIVATE); + + /* Setup the ISR. */ + test_isr_dispatch = test_isr; + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Wakeup thread 2 to get the ISR to take place on top of the thread. */ + tx_thread_resume(&thread_2); + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Clear the ISR. */ + test_isr_dispatch = TX_NULL; + + /* Test for error. */ + if ((error) || (timer_executed != 1) || (isr_executed != 1)) + { + + /* Block memory error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + +#endif + + /* Release mutex multiple times. */ + status = tx_mutex_put(&mutex_2); + status += tx_mutex_put(&mutex_2); + + /* Check status. */ + if (status != TX_NOT_OWNED) + { + + /* Mutex error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Attempt to release a mutex that is not owned. */ + status = _tx_mutex_put(&mutex_2); + + /* Check status. */ + if (status != TX_NOT_OWNED) + { + + /* Mutex error. */ + printf("ERROR #28\n"); + test_control_return(1); + } + + /* Delete mutex. */ + status = tx_mutex_delete(&mutex_2); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #29\n"); + test_control_return(1); + } + + /* Get mutex 8. */ + status = tx_mutex_get(&mutex_8, TX_WAIT_FOREVER); + + /* Start thread 3 and 4. */ + status += tx_thread_resume(&thread_3); + status += tx_thread_resume(&thread_4); + + /* Sleep to let thread 3 suspend on the mutex. */ + tx_thread_sleep(2); + + /* Now, put the mutex to give it to thread 3. */ + status += tx_mutex_put(&mutex_8); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #29a\n"); + test_control_return(1); + } + + status = tx_mutex_delete(&mutex_3); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #30\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + /* Increment thread 1 counter. */ + thread_1_counter++; + + /* Attempt to get from mutex that is available. Should be successful! */ + status = tx_mutex_get(&mutex_1, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #31\n"); + test_control_return(1); + } + + /* Let other thread run again. */ + tx_thread_relinquish(); + + /* Release mutex! */ + status = tx_mutex_put(&mutex_1); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #32\n"); + test_control_return(1); + } + + /* Create and obtain a couple mutexes so the thread completion can release them. */ + status = tx_mutex_create(&mutex_6, "mutex 6", TX_NO_INHERIT); + status += tx_mutex_create(&mutex_7, "mutex 7", TX_NO_INHERIT); + status += tx_mutex_get(&mutex_6, TX_NO_WAIT); + status += tx_mutex_get(&mutex_7, TX_NO_WAIT); + status += tx_mutex_get(&mutex_6, TX_NO_WAIT); + status += tx_mutex_get(&mutex_7, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #33\n"); + test_control_return(1); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + + while(1) + { + + tx_thread_relinquish(); + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + + while(1) + { + + tx_mutex_get(&mutex_8, TX_WAIT_FOREVER); + tx_mutex_put(&mutex_8); + } +} + + +static void thread_4_entry(ULONG thread_input) +{ + + while(1) + { + + tx_mutex_get(&mutex_8, TX_WAIT_FOREVER); + tx_mutex_put(&mutex_8); + } +} diff --git a/test/tx/regression/threadx_mutex_delete_test.c b/test/tx/regression/threadx_mutex_delete_test.c new file mode 100644 index 00000000..28676f4b --- /dev/null +++ b/test/tx/regression/threadx_mutex_delete_test.c @@ -0,0 +1,194 @@ +/* This test is designed to test the mutex suspension and mutex delete with + suspended threads. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + + +static TX_MUTEX mutex_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_mutex_delete_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Delete Test........................................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Delete Test........................................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Delete Test........................................... ERROR #3\n"); + test_control_return(1); + } + + /* Create a mutex. */ + status = tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Delete Test........................................... ERROR #4\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Mutex Delete Test........................................... "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Grab the mutex so it is owned by this thread. */ + status = tx_mutex_get(&mutex_0, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Relinquish to let other threads run. */ + tx_thread_relinquish(); + + /* Other threads should now be suspended on the mutex. */ + + /* Delete the mutex to test it out! */ + status = tx_mutex_delete(&mutex_0); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Relinquish to allow other threads to run again before we return. */ + tx_thread_relinquish(); + + /* Now check the run counter of each thread. */ + if ((thread_1_counter != 1) || (thread_2_counter != 1)) + { + + /* Mutex error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + /* Suspend on the mutex. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Did we get the right status? */ + if (status == TX_DELETED) + thread_1_counter++; +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; + + + /* Suspend on the mutex. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Did we get the right status? */ + if (status == TX_DELETED) + thread_2_counter++; +} diff --git a/test/tx/regression/threadx_mutex_information_test.c b/test/tx/regression/threadx_mutex_information_test.c new file mode 100644 index 00000000..e95c16c6 --- /dev/null +++ b/test/tx/regression/threadx_mutex_information_test.c @@ -0,0 +1,592 @@ +/* This test is designed to test the mutex information services. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_mutex.h" + + +static unsigned long thread_0_counter = 0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_0; +static TX_THREAD thread_1; + +static TX_MUTEX mutex_0; +static TX_MUTEX mutex_1; +static TX_MUTEX mutex_2; +static TX_MUTEX mutex_3; +static TX_MUTEX mutex_4; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +UINT _tx_mutex_performance_info_get(TX_MUTEX *mutex_ptr, ULONG *puts, ULONG *gets, + ULONG *suspensions, ULONG *timeouts, ULONG *inversions, ULONG *inheritances); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_mutex_information_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Information Test...................................... ERROR #1\n"); + test_control_return(1); + } + + /* Create a mutex. */ + status = tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Information Test...................................... ERROR #2\n"); + test_control_return(1); + } + + /* Create another mutex. */ + status = tx_mutex_create(&mutex_1, "mutex 1", TX_NO_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Information Test...................................... ERROR #3\n"); + test_control_return(1); + } + + /* Create another mutex. */ + status = tx_mutex_create(&mutex_2, "mutex 2", TX_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Information Test...................................... ERROR #4\n"); + test_control_return(1); + } + + /* Create another mutex. */ + status = tx_mutex_create(&mutex_3, "mutex 3", TX_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Information Test...................................... ERROR #5\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +CHAR *name; +ULONG count; +TX_THREAD *owner; +TX_THREAD *first_suspended; +ULONG suspended_count; +TX_MUTEX *next_mutex; +ULONG puts; +ULONG gets; +ULONG suspensions; +ULONG timeouts; +ULONG inversions; +ULONG inheritances; + + + /* Inform user. */ + printf("Running Mutex Information Test...................................... "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Attempt to get from mutex that is available. Should be successful! */ + status = tx_mutex_get(&mutex_0, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Attempt to get the same mutex again. Should be successful! */ + status = tx_mutex_get(&mutex_0, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Put the mutex. */ + status = tx_mutex_put(&mutex_0); + + /* Check status. */ + if ((status != TX_SUCCESS) || (mutex_0.tx_mutex_ownership_count != 1)) + { + + /* Mutex error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Put the mutex again. Should be successful! */ + status = tx_mutex_put(&mutex_0); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Relinquish to allow other thread to get the mutex. */ + tx_thread_relinquish(); + + /* Attempt to get the mutex. Should be unsuccessful. */ + status = tx_mutex_get(&mutex_1, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NOT_AVAILABLE) + { + + /* Mutex error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Relinquish again so that the other thread can release it. */ + tx_thread_relinquish(); + + /* Delete mutex. */ + status = tx_mutex_delete(&mutex_0); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + status = tx_mutex_delete(&mutex_1); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Attempt to get a priority inheritance mutex. */ + status = tx_mutex_get(&mutex_2, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Attempt to get another priority inheritance mutex. */ + status = tx_mutex_get(&mutex_3, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to get mutex info with a NULL pointer. */ + status = tx_mutex_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_MUTEX_ERROR) + { + + /* Mutex error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Attempt to get mutex info from a non-created mutex. */ + mutex_4.tx_mutex_id = 0; + status = tx_mutex_info_get(&mutex_4, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_MUTEX_ERROR) + { + + /* Mutex error. */ + printf("ERROR #16\n"); + test_control_return(1); + } +#endif + + /* Get mutex information. */ + status = tx_mutex_info_get(&mutex_2, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_mutex_info_get(&mutex_2, &name, &count, &owner, &first_suspended, &suspended_count, &next_mutex); + + /* Check status. */ + if ((status != TX_SUCCESS) || (count != mutex_2.tx_mutex_ownership_count) || (owner != mutex_2.tx_mutex_owner) || + (first_suspended != mutex_2.tx_mutex_suspension_list) || (suspended_count != mutex_2.tx_mutex_suspended_count) || (next_mutex != mutex_2.tx_mutex_created_next)) + { + + /* Mutex error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO + + /* Call with NULL pointer. */ + status = _tx_mutex_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_PTR_ERROR) + { + + /* Mutex error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Now get the performance inforamtion. */ + status = tx_mutex_performance_info_get(&mutex_2, &puts, &gets, &suspensions, &timeouts, &inversions, &inheritances); + + /* Check status. */ + if ((status != TX_SUCCESS) || (puts != mutex_2.tx_mutex_performance_put_count) || (gets != mutex_2.tx_mutex_performance_get_count) || + (suspensions != mutex_2.tx_mutex_performance_suspension_count) || (timeouts != mutex_2.tx_mutex_performance_timeout_count) || + (inversions != mutex_2.tx_mutex_performance_priority_inversion_count) || (inheritances != mutex_2.tx_mutex_performance__priority_inheritance_count)) + { + + /* Mutex error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Now get the system performance inforamtion. */ + status = tx_mutex_performance_system_info_get(&puts, &gets, &suspensions, &timeouts, &inversions, &inheritances); + + /* Check status. */ + if ((status != TX_SUCCESS) || (puts != _tx_mutex_performance_put_count) || (gets != _tx_mutex_performance_get_count) || + (suspensions != _tx_mutex_performance_suspension_count) || (timeouts != _tx_mutex_performance_timeout_count) || + (inversions != _tx_mutex_performance_priority_inversion_count) || (inheritances != _tx_mutex_performance__priority_inheritance_count)) + { + + /* Mutex error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + +#else + + /* Now get the performance inforamtion. */ + status = tx_mutex_performance_info_get(&mutex_2, &puts, &gets, &suspensions, &timeouts, &inversions, &inheritances); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + /* Now get the performance inforamtion. */ + status = tx_mutex_performance_info_get(TX_NULL, &puts, &gets, &suspensions, &timeouts, &inversions, &inheritances); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + /* Now get the performance inforamtion. */ + status = tx_mutex_performance_info_get(TX_NULL, TX_NULL, &gets, &suspensions, &timeouts, &inversions, &inheritances); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Now get the performance inforamtion. */ + status = tx_mutex_performance_info_get(TX_NULL, TX_NULL, TX_NULL, &suspensions, &timeouts, &inversions, &inheritances); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Now get the performance inforamtion. */ + status = tx_mutex_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, &timeouts, &inversions, &inheritances); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + + /* Now get the performance inforamtion. */ + status = tx_mutex_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &inversions, &inheritances); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + /* Now get the performance inforamtion. */ + status = tx_mutex_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &inheritances); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Now get the performance inforamtion. */ + status = tx_mutex_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #28\n"); + test_control_return(1); + } + + /* Now get the system performance inforamtion. */ + status = tx_mutex_performance_system_info_get(&puts, &gets, &suspensions, &timeouts, &inversions, &inheritances); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #29\n"); + test_control_return(1); + } + + /* Now get the system performance inforamtion. */ + status = tx_mutex_performance_system_info_get(TX_NULL, &gets, &suspensions, &timeouts, &inversions, &inheritances); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #30\n"); + test_control_return(1); + } + + /* Now get the system performance inforamtion. */ + status = tx_mutex_performance_system_info_get(TX_NULL, TX_NULL, &suspensions, &timeouts, &inversions, &inheritances); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #31\n"); + test_control_return(1); + } + + /* Now get the system performance inforamtion. */ + status = tx_mutex_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, &timeouts, &inversions, &inheritances); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #32\n"); + test_control_return(1); + } + + /* Now get the system performance inforamtion. */ + status = tx_mutex_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, &inversions, &inheritances); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #33\n"); + test_control_return(1); + } + + /* Now get the system performance inforamtion. */ + status = tx_mutex_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &inheritances); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #34\n"); + test_control_return(1); + } + + /* Now get the system performance inforamtion. */ + status = tx_mutex_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Mutex error. */ + printf("ERROR #35\n"); + test_control_return(1); + } + +#endif + + /* Delete mutex. */ + status = tx_mutex_delete(&mutex_2); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #36\n"); + test_control_return(1); + } + + status = tx_mutex_delete(&mutex_3); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #37\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + /* Increment thread 1 counter. */ + thread_1_counter++; + + /* Attempt to get from mutex that is available. Should be successful! */ + status = tx_mutex_get(&mutex_1, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #38\n"); + test_control_return(1); + } + + /* Let other thread run again. */ + tx_thread_relinquish(); + + /* Release mutex! */ + status = tx_mutex_put(&mutex_1); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #39\n"); + test_control_return(1); + } +} diff --git a/test/tx/regression/threadx_mutex_nested_priority_inheritance_test.c b/test/tx/regression/threadx_mutex_nested_priority_inheritance_test.c new file mode 100644 index 00000000..7397b4e2 --- /dev/null +++ b/test/tx/regression/threadx_mutex_nested_priority_inheritance_test.c @@ -0,0 +1,701 @@ +/* This test is designed to test multiple mutex priority inheritance situations. */ + +#include <stdio.h> +#include "tx_api.h" + +#define DEMO_STACK_SIZE TEST_STACK_SIZE_PRINTF + + +/* Define the ThreadX object control blocks... */ + +static TX_THREAD thread_0; +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD +static TX_THREAD thread_1; +static TX_THREAD thread_2; +static TX_THREAD thread_3; +static TX_THREAD thread_4; +static TX_THREAD thread_5; +static TX_THREAD thread_6; + +static TX_MUTEX mutex_0; +static TX_MUTEX mutex_1; +static TX_MUTEX mutex_2; +static TX_MUTEX mutex_3; + + +/* Define the counters used in the demo application... */ + +static ULONG thread_0_counter; +static ULONG thread_1_counter; +static ULONG thread_2_counter; +static ULONG thread_3_counter; +static ULONG thread_4_counter; +static ULONG thread_5_counter; +static ULONG thread_6_counter; +#endif + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +static void thread_5_entry(ULONG thread_input); +static void thread_6_entry(ULONG thread_input); +#endif + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_mutex_nested_priority_inheritance_application_define(void *first_unused_memory) +#endif +{ + +CHAR *pointer; +UINT status; + + + pointer = (CHAR *) first_unused_memory; + + /* Create thread. */ + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, DEMO_STACK_SIZE, + 16, 1, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + DEMO_STACK_SIZE; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Nested Priority Inheritance Test...................... ERROR #1\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Create thread. */ + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + DEMO_STACK_SIZE; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Nested Priority Inheritance Test...................... ERROR #2\n"); + test_control_return(1); + } + + /* Create thread. */ + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, DEMO_STACK_SIZE, + 4, 4, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + DEMO_STACK_SIZE; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Nested Priority Inheritance Test...................... ERROR #3\n"); + test_control_return(1); + } + + /* Create thread. */ + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, DEMO_STACK_SIZE, + 30, 1, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + DEMO_STACK_SIZE; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Nested Priority Inheritance Test...................... ERROR #4\n"); + test_control_return(1); + } + + /* Create thread. */ + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, DEMO_STACK_SIZE, + 4, 4, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + DEMO_STACK_SIZE; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Nested Priority Inheritance Test...................... ERROR #4a\n"); + test_control_return(1); + } + + /* Create thread. */ + status = tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, + pointer, DEMO_STACK_SIZE, + 2, 2, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + DEMO_STACK_SIZE; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Nested Priority Inheritance Test...................... ERROR #4b\n"); + test_control_return(1); + } + + /* Create thread. */ + status = tx_thread_create(&thread_6, "thread 6", thread_6_entry, 6, + pointer, DEMO_STACK_SIZE, + 30, 30, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + DEMO_STACK_SIZE; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Nested Priority Inheritance Test...................... ERROR #4c\n"); + test_control_return(1); + } + + /* Create the mutexes. */ + status = tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + status += tx_mutex_create(&mutex_1, "mutex 1", TX_INHERIT); + status += tx_mutex_create(&mutex_2, "mutex 2", TX_INHERIT); + status += tx_mutex_create(&mutex_3, "mutex 3", TX_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Nested Priority Inheritance Test...................... ERROR #5\n"); + test_control_return(1); + } +#endif +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +#ifdef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Preemption threshold is not enabled, skip this test. */ + + /* Inform user. */ + printf("Running Mutex Nested Priority Inheritance Test...................... SUCCESS!\n"); + test_control_return(0); + +#else + +UINT test_case = 0; +UINT loop_count = 0; +UINT priority; +UINT status; + + + /* Inform user. */ + printf("Running Mutex Nested Priority Inheritance Test...................... "); + + /* Get the mutex that will be owned always.... */ + tx_mutex_get(&mutex_3, TX_WAIT_FOREVER); + + while(loop_count++ < 50) + { + + /* Increment the thread counter. */ + thread_0_counter++; + + tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + tx_mutex_get(&mutex_1, TX_WAIT_FOREVER); + tx_mutex_get(&mutex_2, TX_WAIT_FOREVER); + + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + + /* Suspend this thread. */ + tx_thread_suspend(&thread_0); + + /* Resume thread thread 3. */ + tx_thread_resume(&thread_3); + + /* Thread priority should be 4. */ + if (thread_0.tx_thread_priority != 4) + { + + /* Test error! */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Release the mutexes... Depending on the order they are released should dictate + the thread's returned to priority. */ + if (test_case == 0) + { + + + tx_mutex_put(&mutex_2); + + /* Priority should now be returned to priority 8. */ + if (thread_0.tx_thread_priority != 8) + { + + /* Test error! */ + printf("ERROR #7\n"); + test_control_return(2); + } + + tx_mutex_put(&mutex_1); + + /* Priority should now be returned to priority 15. */ + if (thread_0.tx_thread_priority != 15) + { + + /* Test error! */ + printf("ERROR #8\n"); + test_control_return(3); + } + + tx_mutex_put(&mutex_0); + + /* No change. */ + if (thread_0.tx_thread_priority != 15) + { + + /* Test error! */ + printf("ERROR #9\n"); + test_control_return(4); + } + } + else if (test_case == 1) + { + + priority = thread_0.tx_thread_priority; + tx_mutex_put(&mutex_0); + + /* Should have no change in priority since nothing was inherited for this mutex. */ + if (thread_0.tx_thread_priority != priority) + { + + /* Test error! */ + printf("ERROR #10\n"); + test_control_return(4); + } + + tx_mutex_put(&mutex_1); + + /* Should not do anything since mutex 2 elevated to a higher priority. */ + if (thread_0.tx_thread_priority != priority) + { + + /* Test error! */ + printf("ERROR #11\n"); + test_control_return(5); + } + + tx_mutex_put(&mutex_2); + + /* Should go back to priority 15. */ + if (thread_0.tx_thread_priority != 15) + { + + /* Test error! */ + printf("ERROR #12\n"); + test_control_return(6); + } + } + else if (test_case == 2) + { + + tx_mutex_put(&mutex_2); + + /* Should go back to priority 8. */ + if (thread_0.tx_thread_priority != 8) + { + + /* Test error! */ + printf("ERROR #13\n"); + test_control_return(7); + } + + tx_mutex_put(&mutex_0); + + /* Should not do anything. */ + if (thread_0.tx_thread_priority != 8) + { + + /* Test error! */ + printf("ERROR #14\n"); + test_control_return(8); + } + + tx_mutex_put(&mutex_1); + + /* Should go back to priority 15. */ + if (thread_0.tx_thread_priority != 15) + { + + /* Test error! */ + printf("ERROR #15\n"); + test_control_return(9); + } + } + else if (test_case == 3) + { + + priority = thread_0.tx_thread_priority; + tx_mutex_put(&mutex_1); + + /* Should not do anything since mutex 2 is still owned. */ + if (thread_0.tx_thread_priority != priority) + { + + /* Test error! */ + printf("ERROR #16\n"); + test_control_return(10); + } + + tx_mutex_put(&mutex_0); + + /* Should not do anything. */ + if (thread_0.tx_thread_priority != priority) + { + + /* Test error! */ + printf("ERROR #17\n"); + test_control_return(11); + } + + tx_mutex_put(&mutex_2); + + /* Should finally go back to priority 15. */ + if (thread_0.tx_thread_priority != 15) + { + + /* Test error! */ + printf("ERROR #18\n"); + test_control_return(12); + } + } + else if (test_case == 4) + { + + priority = thread_0.tx_thread_priority; + tx_mutex_put(&mutex_1); + + /* Should not do anything since mutex 2 is still owned. */ + if (thread_0.tx_thread_priority != priority) + { + + /* Test error! */ + printf("ERROR #19\n"); + test_control_return(13); + } + + tx_mutex_put(&mutex_2); + + /* Should reurn us back to priority 15. */ + if (thread_0.tx_thread_priority != 15) + { + + /* Test error! */ + printf("ERROR #20\n"); + test_control_return(14); + } + + tx_mutex_put(&mutex_0); + + /* Should not do anything. */ + if (thread_0.tx_thread_priority != 15) + { + + /* Test error! */ + printf("ERROR #21\n"); + test_control_return(15); + } + } + else if (test_case == 5) + { + + priority = thread_0.tx_thread_priority; + tx_mutex_put(&mutex_0); + + /* Should not do anything since mutex 2 is still owned. */ + if (thread_0.tx_thread_priority != priority) + { + + /* Test error! */ + printf("ERROR #22\n"); + test_control_return(16); + } + + tx_mutex_put(&mutex_2); + + /* Should reurn us back to priority 8. */ + if (thread_0.tx_thread_priority != 8) + { + + /* Test error! */ + printf("ERROR #23\n"); + test_control_return(17); + } + + tx_mutex_put(&mutex_1); + + /* Should return us back to priority 15. */ + if (thread_0.tx_thread_priority != 15) + { + + /* Test error! */ + printf("ERROR #24\n"); + test_control_return(18); + } + } + + test_case++; + if (test_case > 5) + test_case = 0; + } + + /* Check for thread 3 running... this should not happen! */ + if (thread_3_counter != 50) + { + + printf("ERROR #25\n"); + test_control_return(19); + } + + /* At this point, mutex 3 owned by this thread. */ + + /* Resume thread 6, lowest priority thread. */ + status = tx_thread_resume(&thread_6); + + /* Check for an error. */ + if ((status != TX_SUCCESS) || (thread_0.tx_thread_priority != 15) || (thread_6_counter != 0)) + { + + printf("ERROR #27\n"); + test_control_return(19); + } + + /* Now resume thread 4. */ + status = tx_thread_resume(&thread_4); + + /* Check for an error. */ + if ((status != TX_SUCCESS) || (thread_0.tx_thread_priority != 4) || (thread_6_counter != 0)) + { + + printf("ERROR #28\n"); + test_control_return(19); + } + + /* Now resume thread 5. */ + status = tx_thread_resume(&thread_5); + + /* Check for an error. */ + if ((status != TX_SUCCESS) || (thread_0.tx_thread_priority != 2) || (thread_6_counter != 0)) + { + + printf("ERROR #29\n"); + test_control_return(19); + } + + /* Sleep to let thread 6 run, which is lower priority. */ + tx_thread_sleep(1); + + /* Now release the mutex. */ + status = tx_mutex_put(&mutex_3); + + /* Check for an error. */ + if ((status != TX_SUCCESS) || (thread_0.tx_thread_priority != 15) || (thread_6_counter != 0) || (thread_4_counter != 1) || (thread_5_counter != 1)) + { + + printf("ERROR #30\n"); + test_control_return(19); + } + + /* Sleep to let thread 6 run and release the mutex. */ + tx_thread_sleep(2); + + + /* If we get here the test was successful! */ + printf("SUCCESS!\n"); + test_control_return(0); +#endif +} + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + +static void thread_1_entry(ULONG thread_input) +{ + +UINT old_priority; +UINT old_threshold; + + + while(1) + { + + /* Increment the thread counter. */ + thread_1_counter++; + + /* Update the thread priority and thread preemption-threshold of thread 0. */ + tx_thread_priority_change(&thread_0, 15, &old_priority); + tx_thread_preemption_change(&thread_0, 14, &old_threshold); + + /* Get mutex. */ + tx_mutex_get(&mutex_1, TX_WAIT_FOREVER); + tx_mutex_put(&mutex_1); + + tx_thread_suspend(&thread_1); + + /* Increment the thread counter. */ + thread_1_counter++; + + /* Update the thread priority and thread preemption-threshold of thread 0. */ + tx_thread_priority_change(&thread_0, 15, &old_priority); + tx_thread_preemption_change(&thread_0, 8, &old_threshold); + + /* Get mutex. */ + tx_mutex_get(&mutex_1, TX_WAIT_FOREVER); + tx_mutex_put(&mutex_1); + + tx_thread_suspend(&thread_1); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT old_priority; +UINT old_threshold; + + while(1) + { + + /* Increment the thread counter. */ + thread_2_counter++; + + /* Update the thread priority and thread preemption-threshold of thread 0. */ + tx_thread_priority_change(&thread_0, 15, &old_priority); + tx_thread_preemption_change(&thread_0, 14, &old_threshold); + + /* Get mutex. */ + tx_mutex_get(&mutex_2, TX_WAIT_FOREVER); + tx_mutex_put(&mutex_2); + + tx_thread_suspend(&thread_2); + + /* Increment the thread counter. */ + thread_2_counter++; + + /* Update the thread priority and thread preemption-threshold of thread 0. */ + tx_thread_priority_change(&thread_0, 15, &old_priority); + tx_thread_preemption_change(&thread_0, 8, &old_threshold); + + /* Get mutex. */ + tx_mutex_get(&mutex_2, TX_WAIT_FOREVER); + tx_mutex_put(&mutex_2); + + tx_thread_suspend(&thread_2); + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + + + while(1) + { + + /* Resume thread 0. */ + tx_thread_resume(&thread_0); + + /* Increment the thread counter. */ + thread_3_counter++; + + /* Suspend this thread. */ + tx_thread_suspend(&thread_3); + } +} + + +static void thread_4_entry(ULONG thread_input) +{ + + + while(1) + { + + /* Get priority inherit mutex. */ + tx_mutex_get(&mutex_3, TX_WAIT_FOREVER); + + /* Increment the thread counter. */ + thread_4_counter++; + + /* Release the priority inherit mutex. */ + tx_mutex_put(&mutex_3); + + /* Suspend this thread. */ + tx_thread_suspend(&thread_4); + } +} + + +static void thread_5_entry(ULONG thread_input) +{ + + + while(1) + { + + /* Get priority inherit mutex. */ + tx_mutex_get(&mutex_3, TX_WAIT_FOREVER); + + /* Increment the thread counter. */ + thread_5_counter++; + + /* Release the priority inherit mutex. */ + tx_mutex_put(&mutex_3); + + /* Suspend this thread. */ + tx_thread_suspend(&thread_5); + } +} + + +static void thread_6_entry(ULONG thread_input) +{ + + + while(1) + { + + /* Get priority inherit mutex. */ + tx_mutex_get(&mutex_3, TX_WAIT_FOREVER); + + /* Increment the thread counter. */ + thread_6_counter++; + + /* Release the priority inherit mutex. */ + tx_mutex_put(&mutex_3); + + /* Suspend this thread. */ + tx_thread_suspend(&thread_6); + } +} +#endif + + diff --git a/test/tx/regression/threadx_mutex_no_preemption_test.c b/test/tx/regression/threadx_mutex_no_preemption_test.c new file mode 100644 index 00000000..c26c3651 --- /dev/null +++ b/test/tx/regression/threadx_mutex_no_preemption_test.c @@ -0,0 +1,173 @@ +/* This test is designed to test the mutex suspension and another thread resuming the + same priority thread by doing a mutex put. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + + +static TX_MUTEX mutex_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_mutext_no_preemption_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Put with No Preemption Test........................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Put with No Preemption Test........................... ERROR #2\n"); + test_control_return(1); + } + + /* Create a mutex. */ + status = tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Put with No Preemption Test........................... ERROR #3\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Mutex Put with No Preemption Test........................... "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Get the mutex. */ + status = tx_mutex_get(&mutex_0, TX_NO_WAIT); + + /* Should be successful. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Relinquish to make the other thread suspend on the mutex. */ + tx_thread_relinquish(); + + /* Make sure the other thread has run. */ + if (thread_1_counter != 1) + { + + /* Mutex error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Put the mutex, this should resume the other thread + but not preempt this thread. */ + status = tx_mutex_put(&mutex_0); + + /* Check the status and the run counter of the other thread. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1)) + { + + /* Mutex error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Relinquish to allow the other thread to run. */ + tx_thread_relinquish(); + + /* Make sure the other thread has run. */ + if (thread_1_counter != 2) + { + + /* Mutex error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + /* Increment thread run counter. */ + thread_1_counter++; + + /* Suspend on the mutex. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_1_counter++; +} + diff --git a/test/tx/regression/threadx_mutex_preemption_test.c b/test/tx/regression/threadx_mutex_preemption_test.c new file mode 100644 index 00000000..238dda03 --- /dev/null +++ b/test/tx/regression/threadx_mutex_preemption_test.c @@ -0,0 +1,161 @@ +/* This test is designed to test the mutex suspension and another thread resuming the + higher priority thread by doing a mutex put. Higher-priority thread should preempt. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + + +static TX_MUTEX mutex_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_mutex_preemption_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Put with Preemption Test.............................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Put with Preemption Test.............................. ERROR #2\n"); + test_control_return(1); + } + + /* Create a mutex. */ + status = tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Put with Preemption Test.............................. ERROR #3\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Mutex Put with Preemption Test.............................. "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Get the mutex. */ + status = tx_mutex_get(&mutex_0, TX_NO_WAIT); + + /* Should be successful. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Now resume the higher priority thread to cause suspension. */ + tx_thread_resume(&thread_1); + + /* The other thread should now be suspended on the mutex. */ + if (thread_1_counter != 1) + { + + /* Mutex error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Release the mutex, this should cause the other thread + to preempt. */ + status = tx_mutex_put(&mutex_0); + + /* Check status and run counter of other thread. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 2)) + { + + /* Mutex error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + /* Increment thread run counter. */ + thread_1_counter++; + + /* Suspend on the mutex. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_1_counter++; +} + diff --git a/test/tx/regression/threadx_mutex_priority_inheritance_test.c b/test/tx/regression/threadx_mutex_priority_inheritance_test.c new file mode 100644 index 00000000..68a7f0ce --- /dev/null +++ b/test/tx/regression/threadx_mutex_priority_inheritance_test.c @@ -0,0 +1,573 @@ +/* This test is designed to test the mutex suspension and priority inheritance with another + thread resuming the higher priority thread by doing a mutex put. Higher-priority thread should preempt. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; +static TX_THREAD thread_3; + +static unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; + +static unsigned long thread_5_counter = 0; +static TX_THREAD thread_5; + +static unsigned long thread_6_counter = 0; +static TX_THREAD thread_6; + +static unsigned long thread_7_counter = 0; +static TX_THREAD thread_7; + +static TX_MUTEX mutex_0; +static TX_MUTEX mutex_1; +static TX_MUTEX mutex_2; +static TX_MUTEX mutex_3; + + +extern UINT test_mutex_from_init; +extern TEST_FLAG test_forced_mutex_timeout; + + +VOID _tx_mutex_priority_change(TX_THREAD *thread_ptr, UINT priority, UINT threshold); + + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +static void thread_5_entry(ULONG thread_input); +static void thread_6_entry(ULONG thread_input); +static void thread_7_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_mutex_priority_inheritance_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Test for an error creating/using a mutex from initialization. */ + if (test_mutex_from_init != TX_SUCCESS) + { + + printf("Running Mutex Priority Inheritance Test............................. ERROR #0\n"); + test_control_return(1); + } + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Priority Inheritance Test............................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Priority Inheritance Test............................. ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 14, 14, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Priority Inheritance Test............................. ERROR #3\n"); + test_control_return(1); + } + + /* Create a high-priority thread that will get all the priority inheritance mutexes and return from + it's entry function in order to test the auto delete feature. */ + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 10, 10, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Priority Inheritance Test............................. ERROR #4\n"); + test_control_return(1); + } + + /* Create a higher-priority thread that is used to get thread 4 into a priority inheritance state. */ + status = tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, + pointer, TEST_STACK_SIZE_PRINTF, + 8, 8, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Priority Inheritance Test............................. ERROR #5\n"); + test_control_return(1); + } + + + /* Create a higher-priority thread that is used to suspend on priority inheritance mutex 3. */ + status = tx_thread_create(&thread_6, "thread 6", thread_6_entry, 6, + pointer, TEST_STACK_SIZE_PRINTF, + 6, 6, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Priority Inheritance Test............................. ERROR #6\n"); + test_control_return(1); + } + + + /* Create a higher-priority thread that is used to suspend on priority inheritance mutex 3. */ + status = tx_thread_create(&thread_7, "thread 7", thread_7_entry, 7, + pointer, TEST_STACK_SIZE_PRINTF, + 7, 7, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Priority Inheritance Test............................. ERROR #7\n"); + test_control_return(1); + } + + /* Create a mutex. */ + status = tx_mutex_create(&mutex_0, "mutex 0", TX_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Priority Inheritance Test............................. ERROR #8\n"); + test_control_return(1); + } + + /* Create another mutex. */ + status = tx_mutex_create(&mutex_1, "mutex 1", TX_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Priority Inheritance Test............................. ERROR #9\n"); + test_control_return(1); + } + + /* Create another mutex. */ + status = tx_mutex_create(&mutex_2, "mutex 2", TX_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Priority Inheritance Test............................. ERROR #10\n"); + test_control_return(1); + } + + /* Create another mutex. */ + status = tx_mutex_create(&mutex_3, "mutex 3", TX_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Priority Inheritance Test............................. ERROR #11\n"); + test_control_return(1); + } + + /* Drive one path of the internal mutex priority change routine directly for code coverage. */ + thread_3.tx_thread_user_priority = 1; + thread_3.tx_thread_user_preempt_threshold = 1; + thread_3.tx_thread_state = 4; + _tx_mutex_priority_change(&thread_3, 3, 3); +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Mutex Priority Inheritance Test............................. "); + + /* Resume thread 4 to test the automatic release of the mutexes. */ + tx_thread_resume(&thread_4); + + /* Determine if thread 4 was able to get the mutexes before completion... and + have its original priority restored after the priority inheritance. */ + if ((thread_4_counter != 1) || (thread_5_counter != 1) || (thread_4.tx_thread_priority != 10) || + (thread_4.tx_thread_inherit_priority != TX_MAX_PRIORITIES)) + { + + /* Mutex error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Get all the mutexex. */ + status = tx_mutex_get(&mutex_0, TX_NO_WAIT); + status += tx_mutex_get(&mutex_1, TX_NO_WAIT); + status += tx_mutex_get(&mutex_2, TX_NO_WAIT); + + /* Should be successful. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Release mutex 2 to be compatible with original test. */ + tx_mutex_put(&mutex_2); + + /* Now resume the higher priority thread to cause suspension. */ + tx_thread_resume(&thread_1); + + /* The other thread should now be suspended on the mutex. */ + if ((thread_1_counter != 1) || (thread_0.tx_thread_priority != 15)) + { + + /* Mutex error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Release the mutex, this should cause the other thread + to preempt. */ + status = tx_mutex_put(&mutex_0); + + /* Check status and run counter of other thread. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 2) || (thread_0.tx_thread_priority != 16)) + { + + /* Mutex error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* At this point, get the mutex again. */ + status = tx_mutex_get(&mutex_0, TX_NO_WAIT); + + /* Should be successful. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Now sleep for 20 ticks in order to test the priority inheritance change of a + non-ready thread. */ + tx_thread_sleep(20); + + /* The other thread should now be suspended on the mutex. */ + if ((thread_1_counter != 3) || (thread_0.tx_thread_priority != 15)) + { + + /* Mutex error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Resume thread 2 in order to get two threads suspended on the mutex. */ + tx_thread_resume(&thread_2); + + /* Now do a mutex put to release both threads suspended on this mutex. */ + status = tx_mutex_put(&mutex_0); + + /* The other thread should now be suspended on the mutex. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 4) || (thread_2_counter != 2) || (thread_0.tx_thread_priority != 16)) + { + + /* Mutex error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* At this point, get the mutex again. */ + status = tx_mutex_get(&mutex_0, TX_NO_WAIT); + + /* Should be successful. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Abort the sleep. */ + tx_thread_wait_abort(&thread_1); + tx_thread_wait_abort(&thread_2); + + /* Now both threads are suspended again on mutex... and then terminate them. */ + tx_thread_terminate(&thread_1); + tx_thread_terminate(&thread_2); + + /* Now do a mutex put to release both threads suspended on this mutex. */ + status = tx_mutex_put(&mutex_0); + + /* The other thread should now be suspended on the mutex. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 5) || (thread_2_counter != 3) || (thread_0.tx_thread_priority != 16)) + { + + /* Mutex error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Now test the timeout on the suspension list of a priority inheritance mutex. */ + + /* First, obtain priority inheritance mutex 3. */ + status = tx_mutex_get(&mutex_3, TX_WAIT_FOREVER); + + /* Next resume threads 6 and 7 so they will block on trying to get this mutex forever. */ + status += tx_thread_resume(&thread_7); + status += tx_thread_resume(&thread_6); + + /* Now set the flag which will cause the last thread in the suspension list to timeout (abort) + resulting in a NULL suspension list and covering that branch condition in tx_mutex_put */ + test_forced_mutex_timeout = 1; + + /* Perform a mutex put to release the mutex. */ + status += tx_mutex_put(&mutex_3); + + /* Now check for errors. */ +#ifndef TX_MISRA_ENABLE +#ifndef TX_MANUAL_TEST +#ifndef TX_NOT_INTERRUPTABLE + if ((status != TX_SUCCESS) || (thread_6_counter != 1) || (thread_7_counter != 0)) +#else + if ((status != TX_SUCCESS) || (thread_6_counter != 1)) +#endif +#else + if ((status != TX_SUCCESS) || (thread_6_counter != 1)) +#endif +#else + if ((status != TX_SUCCESS) || (thread_6_counter != 1)) +#endif + { + + /* Mutex error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + while(1) + { + + /* Increment thread run counter. */ + thread_1_counter++; + + /* Suspend on the mutex. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + status += tx_mutex_put(&mutex_0); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_1_counter++; + + /* Sleep for 10 ticks... to delay. */ + tx_thread_sleep(10); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; + + + /* Get mutex to cause additional ownership linked-list processing. */ + tx_mutex_get(&mutex_2, TX_WAIT_FOREVER); + + while(1) + { + + /* Increment thread run counter. */ + thread_2_counter++; + + /* Suspend on the mutex. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + status += tx_mutex_put(&mutex_0); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_2_counter++; + + /* Sleep for 10 ticks... to delay. */ + tx_thread_sleep(10); + } +} + + +static void thread_4_entry(ULONG thread_input) +{ + +UINT status; + + + /* Get mutex to cause additional ownership linked-list processing. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + status += tx_mutex_get(&mutex_1, TX_WAIT_FOREVER); + status += tx_mutex_get(&mutex_1, TX_WAIT_FOREVER); + status += tx_mutex_get(&mutex_1, TX_WAIT_FOREVER); + status += tx_mutex_get(&mutex_2, TX_WAIT_FOREVER); + + /* Resume thread 5 to get into priority inheritance. */ + tx_thread_resume(&thread_5); + + /* Determine if all the mutex gets were successful... and we have + inherited priority 8. */ + if ((status == TX_SUCCESS) && (thread_4.tx_thread_priority == 8)) + { + + /* Yes, increment the thread counter. */ + thread_4_counter++; + } + + /* Now fall through and make sure the mutex cleanup function + releases all the mutexes. */ +} + + +static void thread_5_entry(ULONG thread_input) +{ + +UINT status; + + + /* Get mutex to cause priority inheritance in thread 4. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Determine if all the mutex gets were successful. */ + if (status == TX_SUCCESS) + { + + /* Yes, increment the thread counter. */ + thread_5_counter++; + } + + /* Now fall through and make sure the mutex cleanup function + releases all the mutexes. */ +} + + +static void thread_6_entry(ULONG thread_input) +{ + +UINT status; + + + /* Get mutex to cause priority inheritance in thread 0. */ + status = tx_mutex_get(&mutex_3, TX_WAIT_FOREVER); + + /* Determine if all the mutex gets were successful. */ + if (status == TX_SUCCESS) + { + + /* Yes, increment the thread counter. */ + thread_6_counter++; + } + + /* Now fall through and make sure the mutex cleanup function + releases all the mutexes. */ +} + + +static void thread_7_entry(ULONG thread_input) +{ + +UINT status; + + + /* Get mutex to cause priority inheritance in thread 0. */ + status = tx_mutex_get(&mutex_3, TX_WAIT_FOREVER); + + /* Determine if all the mutex gets were successful. */ + if (status == TX_SUCCESS) + { + + /* Yes, increment the thread counter. */ + thread_7_counter++; + } + + /* Now fall through and make sure the mutex cleanup function + releases all the mutexes. */ +} + diff --git a/test/tx/regression/threadx_mutex_proritize_test.c b/test/tx/regression/threadx_mutex_proritize_test.c new file mode 100644 index 00000000..4e25673f --- /dev/null +++ b/test/tx/regression/threadx_mutex_proritize_test.c @@ -0,0 +1,525 @@ +/* This test is designed to test the mutex suspension prioritization. */ + +#include <stdio.h> +#include "tx_api.h" + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +/* Define the external reference for the preempt disable flag. */ + +extern volatile UINT _tx_thread_preempt_disable; + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + +static unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; + +static unsigned long thread_5_counter = 0; +static TX_THREAD thread_5; + +static unsigned long thread_6_counter = 0; +static TX_THREAD thread_6; + + +static TX_MUTEX mutex_0; +static TX_MUTEX mutex_1; + +static int test_status; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +static void thread_5_entry(ULONG thread_input); +static void thread_6_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + + /* Determine if the test case we are looking for is present. */ + if ((_tx_thread_preempt_disable) && (test_status == 1)) + { + + /* Determine if thread 3 is at the front of the suspension list. */ + if (mutex_0.tx_mutex_suspension_list == &thread_3) + { + + /* Abort the wait of thread 3. */ + tx_thread_wait_abort(&thread_3); + } + else + { + + /* Abort the wait of thread 5. */ + tx_thread_wait_abort(&thread_5); + + /* End the ISR processing. */ + test_status = 2; + test_isr_dispatch = TX_NULL; + } + } +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_mutex_prioritize_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Prioritize Test....................................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Prioritize Test....................................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 14, 14, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Prioritize Test....................................... ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 3, 3, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Prioritize Test....................................... ERROR #4\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 4, 4, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Prioritize Test....................................... ERROR #5\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, + pointer, TEST_STACK_SIZE_PRINTF, + 5, 5, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Prioritize Test....................................... ERROR #6\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_6, "thread 6", thread_6_entry, 6, + pointer, TEST_STACK_SIZE_PRINTF, + 6, 6, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Prioritize Test....................................... ERROR #7\n"); + test_control_return(1); + } + + /* Create a mutex. */ + status = tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Prioritize Test....................................... ERROR #8\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Mutex Prioritize Test....................................... "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to prioritize a NULL mutex. */ + status = tx_mutex_prioritize(TX_NULL); + + /* Check status. */ + if (status != TX_MUTEX_ERROR) + { + + /* Mutex error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to prioritize a non-created mutex. */ + mutex_1.tx_mutex_id = 0; + status = tx_mutex_prioritize(&mutex_1); + + /* Check status. */ + if (status != TX_MUTEX_ERROR) + { + + /* Mutex error. */ + printf("ERROR #10\n"); + test_control_return(1); + } +#endif + + /* Prioritize the mutex with no suspended threads! */ + status = tx_mutex_prioritize(&mutex_0); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Grab the mutex so it is owned by this thread. */ + status = tx_mutex_get(&mutex_0, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Resume other threads run. */ + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + + /* Other threads should now be suspended on the mutex. Thread 1 should be + in front of thread 2 since it was suspended first. */ + if (mutex_0.tx_mutex_suspension_list != &thread_1) + { + + /* Mutex error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Prioritize the mutex to test it out! */ + status = tx_mutex_prioritize(&mutex_0); + + /* Check status and make sure thread 2 is now at the front of the list. */ + if ((status != TX_SUCCESS) || (mutex_0.tx_mutex_suspension_list != &thread_2)) + { + + /* Mutex error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Prioritize the mutex again to make sure nothing has changed! */ + status = tx_mutex_prioritize(&mutex_0); + + /* Check status and make sure thread 2 is now at the front of the list. */ + if ((status != TX_SUCCESS) || (mutex_0.tx_mutex_suspension_list != &thread_2)) + { + + /* Mutex error. */ + printf("ERROR #14a\n"); + test_control_return(1); + } + + /* At this point we are going to get more than 2 threads suspended. */ + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + tx_thread_resume(&thread_3); + tx_thread_resume(&thread_4); + tx_thread_resume(&thread_5); + tx_thread_resume(&thread_6); + + /* Prioritize the block pool suspension list. */ + status = tx_mutex_prioritize(&mutex_0); + + /* Check status and make sure thread 3 is at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (mutex_0.tx_mutex_suspension_list != &thread_3)) + { + + /* Mutex error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Now loop to test the interrupt of the prioritize loop logic. */ + test_status = 1; + test_isr_dispatch = test_isr; + do + { + + /* Prioritize the mutex suspension list. */ + status = tx_mutex_prioritize(&mutex_0); + + /* Check status and make sure thread 1 is terminated. */ + if (status != TX_SUCCESS) + { + + /* Mutex error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + } while (test_status == 1); + + /* Now determine if thread 4 is at the front of the list... It should be! */ + if (mutex_0.tx_mutex_suspension_list != &thread_4) + { + + /* Mutex error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + while (1) + { + + /* Suspend on the mutex. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Release the mutex. */ + status += tx_mutex_put(&mutex_0); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_1_counter++; + + /* Self suspend. */ + tx_thread_suspend(&thread_1); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; + + + while (1) + { + + /* Suspend on the mutex. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Release the mutex. */ + status += tx_mutex_put(&mutex_0); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_2_counter++; + + /* Self suspend. */ + tx_thread_suspend(&thread_2); + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + +UINT status; + + + while (1) + { + + /* Suspend on the mutex. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Release the mutex. */ + status += tx_mutex_put(&mutex_0); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_3_counter++; + + /* Self suspend. */ + tx_thread_suspend(&thread_3); + } +} + + +static void thread_4_entry(ULONG thread_input) +{ + +UINT status; + + + while (1) + { + + /* Suspend on the mutex. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Release the mutex. */ + status += tx_mutex_put(&mutex_0); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_4_counter++; + + /* Self suspend. */ + tx_thread_suspend(&thread_4); + } +} + + +static void thread_5_entry(ULONG thread_input) +{ + +UINT status; + + + while (1) + { + + /* Suspend on the mutex. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Release the mutex. */ + status += tx_mutex_put(&mutex_0); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_5_counter++; + + /* Self suspend. */ + tx_thread_suspend(&thread_5); + } +} + + +static void thread_6_entry(ULONG thread_input) +{ + +UINT status; + + + while (1) + { + + /* Suspend on the mutex. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Release the mutex. */ + status += tx_mutex_put(&mutex_0); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_6_counter++; + + /* Self suspend. */ + tx_thread_suspend(&thread_6); + } +} + diff --git a/test/tx/regression/threadx_mutex_suspension_timeout_test.c b/test/tx/regression/threadx_mutex_suspension_timeout_test.c new file mode 100644 index 00000000..cae257b5 --- /dev/null +++ b/test/tx/regression/threadx_mutex_suspension_timeout_test.c @@ -0,0 +1,319 @@ +/* This test is designed to test the mutex suspension and timeout functionality. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_mutex.h" + + +//static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static TX_THREAD thread_1; +static TX_THREAD thread_2; +static TX_THREAD thread_3; +static TX_THREAD thread_4; +static TX_THREAD low_priority; + + +static TX_MUTEX mutex_0; +static TX_MUTEX mutex_1; + + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +static void low_priority_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +extern void test_control_return(UINT status); + + +#ifndef TX_MANUAL_TEST + +/* Define test flags for automated test. */ + +extern TEST_FLAG threadx_mutex_suspension_put_test; +extern TEST_FLAG threadx_mutex_suspension_priority_test; + +#endif + + +/* This test routine is used to get NULL suspension lists in various parts of tx_mutex_put. This is hooked up to IRQ 0 on this simulation and is entered manually at the + correct time. */ +void abort_all_threads_suspended_on_mutex(void) +{ + +TX_THREAD *thread_ptr; + + thread_ptr = _tx_thread_created_ptr; + while (thread_ptr) + { + if (thread_ptr -> tx_thread_state == TX_MUTEX_SUSP) + tx_thread_wait_abort(thread_ptr); + + thread_ptr = thread_ptr -> tx_thread_created_next; + if (thread_ptr == _tx_thread_created_ptr) + break; + } +} + + +/* This test routine is used to get a thread of a non ready state into _tx_mutex_change, called froim _tx_mutex_put. This is hooked up to IRQ 1 on this simulation and is entered manually at the + correct time. */ +void suspend_lowest_priority(void) +{ + + tx_thread_suspend(&low_priority); +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_mutex_suspension_timeout_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 1, 1, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 2, 2, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 3, 3, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 4, 4, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_create(&low_priority, "low priority", low_priority_entry, 30, + pointer, TEST_STACK_SIZE_PRINTF, + 30, 30, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Suspension Timeout Test............................... ERROR #1\n"); + test_control_return(1); + } + + /* Create mutexes. */ + status = tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + status += tx_mutex_create(&mutex_1, "mutex 1", TX_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Suspension Timeout Test............................... ERROR #2\n"); + test_control_return(1); + } + + /* Get the mutex to prevent thread from getting it. */ + tx_mutex_get(&mutex_0, TX_NO_WAIT); +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +UINT old_preempt; +UINT old_priority; + + + /* Inform user. */ + printf("Running Mutex Suspension Timeout Test............................... "); + + /* Sleep for 2 ticks for fresh timer. */ + tx_thread_sleep(2); + + /* Set clock to 0. */ + tx_time_set(0); + + /* Suspend on the mutex. */ + status = tx_mutex_get(&mutex_0, 33); + + /* Did we get the right status at the right time? */ + if ((status != TX_NOT_AVAILABLE) || (tx_time_get() != 33)) + { + + /* Mutex error. */ + printf("ERROR #3\n"); + test_control_return(1); + } + + /* Get the mutex. */ + status = tx_mutex_get(&mutex_1, TX_WAIT_FOREVER); + + /* Make sure the three higher priority threads suspend on the mutex. */ + tx_thread_resume(&thread_4); + tx_thread_resume(&thread_3); + tx_thread_resume(&thread_2); + tx_thread_resume(&thread_1); + + +#ifdef TX_MANUAL_TEST + + /* Set BP hear and step into code and generate appropriate interrupt IRQ 0 by hand right after the prioritize function with interrupts enabled. This is to achieve the empty list branch coverage after the prioritize function. */ + tx_mutex_put(&mutex_1); +#else + + /* Set the flag such that generate the condition wehre the empty list condition is satisfied in the branch coverage. */ + threadx_mutex_suspension_put_test = 1; + tx_mutex_put(&mutex_1); +#endif + + /* Now some hand testing for tx_mutex_priority_change. */ + + /* Resume the low priority thread. */ + tx_thread_resume(&low_priority); + + /* Simulate a call from inside of mutex put, but doing it here makes life easier. */ + _tx_thread_preempt_disable++; + +#ifdef TX_MANUAL_TEST + + /* Set BP here and step into code and step through the code until the internal thread resume function returns, then issue an IRQ 1 to cause an ISR to suspend the thread and test the first condition. */ + _tx_mutex_priority_change(&low_priority, 30); +#else + + /* Set the flag to suspend the thread and test the first condition after internal resume is called. */ + threadx_mutex_suspension_priority_test = 1; + _tx_mutex_priority_change(&low_priority, 30); +#endif + + /* Resume the low priority thread. */ + tx_thread_resume(&low_priority); + + /* Now call internal _tx_mutex_priority_change, this should test the preemption-threshold throw-away path. */ + _tx_mutex_priority_change(&low_priority, 30); + + /* Now make it so we can have a higher-priority thread ready but not the execute pointer because of preemption-threshold. */ + tx_thread_preemption_change(&thread_0, 10, &old_preempt); + tx_thread_priority_change(&low_priority, 10, &old_priority); + + /* Now call the internal mutex priority change on this thread to get the throw-away path on original priority being the same when execute ptr is different. */ + _tx_thread_execute_ptr = &low_priority; + _tx_mutex_priority_change(&low_priority, 10); + _tx_thread_execute_ptr = &thread_0; + + /* Now make the low priority thread lower again, but with a preemption-threshold equal to thread_0. This will test yet another throw away condition. */ + low_priority.tx_thread_inherit_priority = ((UINT) TX_MAX_PRIORITIES); + tx_thread_priority_change(&low_priority, 30, &old_priority); + tx_thread_preemption_change(&low_priority, 10, &old_preempt); + + /* Now call the internal mutex priority change on this thread with the same priority. */ + _tx_mutex_priority_change(&low_priority, 30); + _tx_thread_preempt_disable--; + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ +UINT status; + + /* Loop to get the mutex. */ + while(1) + { + + /* Get and release the mutex. */ + status = tx_mutex_get(&mutex_1, TX_WAIT_FOREVER); + if (status == TX_SUCCESS) + tx_mutex_put(&mutex_1); + tx_thread_suspend(&thread_1); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; + + /* Loop to get the mutex. */ + while(1) + { + + /* Get and release the mutex. */ + status = tx_mutex_get(&mutex_1, TX_WAIT_FOREVER); + if (status == TX_SUCCESS) + tx_mutex_put(&mutex_1); + tx_thread_suspend(&thread_2); + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + +UINT status; + + /* Loop to get the mutex. */ + while(1) + { + + /* Get and release the mutex. */ + status = tx_mutex_get(&mutex_1, TX_WAIT_FOREVER); + if (status == TX_SUCCESS) + tx_mutex_put(&mutex_1); + tx_thread_suspend(&thread_3); + } +} + +static void thread_4_entry(ULONG thread_input) +{ + +UINT status; + + /* Loop to get the mutex. */ + while(1) + { + + /* Get and release the mutex. */ + status = tx_mutex_get(&mutex_1, TX_WAIT_FOREVER); + if (status == TX_SUCCESS) + tx_mutex_put(&mutex_1); + tx_thread_suspend(&thread_4); + } +} + + +static void low_priority_entry(ULONG thread_input) +{ +} diff --git a/test/tx/regression/threadx_mutex_thread_terminate_test.c b/test/tx/regression/threadx_mutex_thread_terminate_test.c new file mode 100644 index 00000000..9b552f54 --- /dev/null +++ b/test/tx/regression/threadx_mutex_thread_terminate_test.c @@ -0,0 +1,198 @@ +/* This test is designed to test thread terminate calls when threads are suspended on + a mutex. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + + +static TX_MUTEX mutex_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_mutex_thread_terminate_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Thread Terminate Test................................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Thread Terminate Test................................. ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Thread Terminate Test................................. ERROR #3\n"); + test_control_return(1); + } + + /* Create a mutex. */ + status = tx_mutex_create(&mutex_0, "mutex 0", 0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Mutex Thread Terminate Test................................. ERROR #4\n"); + test_control_return(1); + } + + /* Get the mutex. */ + tx_mutex_get(&mutex_0, TX_NO_WAIT); +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Mutex Thread Terminate Test................................. "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Relinquish to let other threads run. */ + tx_thread_relinquish(); + + /* Other threads should now be suspended on the mutex. */ + if ((thread_1_counter != 1) || (thread_2_counter != 1)) + { + + /* Mutex error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Terminate the other threads to make sure the mutex gets + cleaned up. */ + status = tx_thread_terminate(&thread_1); + + /* Check status and run counters of other threads. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 1)) + { + + /* Mutex error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Terminate the other thread. */ + status = tx_thread_terminate(&thread_2); + + /* Relinquish just to make sure. */ + tx_thread_relinquish(); + + /* Check status and run counters of other threads. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 1)) + { + + /* Mutex error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +//UINT status; + + /* Increment thread run counter. */ + thread_1_counter++; + + /* Suspend on the mutex. */ + tx_mutex_get(&mutex_0, 33); + + /* Should never get here! */ + thread_1_counter++; +} + + +static void thread_2_entry(ULONG thread_input) +{ + +//UINT status; + + /* Increment thread run counter. */ + thread_2_counter++; + + /* Suspend on the mutex. */ + tx_mutex_get(&mutex_0, 44); + + /* Should never get here! */ + thread_2_counter++; +} diff --git a/test/tx/regression/threadx_queue_basic_eight_word_test.c b/test/tx/regression/threadx_queue_basic_eight_word_test.c new file mode 100644 index 00000000..c201fdee --- /dev/null +++ b/test/tx/regression/threadx_queue_basic_eight_word_test.c @@ -0,0 +1,423 @@ +/* This test is designed to test immediate response queue services including create + and delete. This test is for queue sizes of 8 ULONG. Two queues are used one with + a capacity of 1 message and another with a capacity of 3 messages. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static TX_QUEUE queue_0; +static TX_QUEUE queue_1; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_basic_eight_word_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Eight Word Queue Test................................. ERROR #1\n"); + test_control_return(1); + } + + /* Create the queues. */ + status = tx_queue_create(&queue_0, "queue 0", TX_8_ULONG, pointer, 8*sizeof(ULONG)); + pointer = pointer + (8*sizeof(ULONG)); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Eight Word Queue Test................................. ERROR #2\n"); + test_control_return(1); + } + + status = tx_queue_create(&queue_1, "queue 1", TX_8_ULONG, pointer, 8*3*sizeof(ULONG)); + pointer = pointer + 8*3*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Eight Word Queue Test................................. ERROR #3\n"); + test_control_return(1); + } +} + + + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG source_message[8]; +ULONG dest_message[8]; +ULONG expected_message[8]; + + + /* Inform user. */ + printf("Running Queue Eight Word Queue Test................................. "); + + source_message[0] = 0x01234567; + source_message[7] = 0x89ABCDEF; + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Place something on queue 0. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (source_message[0] != dest_message[0]) || + (source_message[7] != dest_message[7])) + { + + /* Queue error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Make sure we can do the same thing again! */ + source_message[0]++; + source_message[7]++; + + /* Place something on queue 0. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (source_message[0] != dest_message[0]) || + (source_message[7] != dest_message[7])) + { + + /* Queue error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Now we need to do the same thing with the queue with three entries. */ + + source_message[0]++; + source_message[7]++; + expected_message[0] = source_message[0]; + expected_message[7] = source_message[7]; + + /* Place something on queue 1. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[7]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[7]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[7]++; + + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[7] != dest_message[7])) + { + + /* Queue error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[7]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[7] != dest_message[7])) + { + + /* Queue error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[7]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[7] != dest_message[7])) + { + + /* Queue error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[7]++; + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Make sure we can do the same thing again! */ + + /* Place something on queue 1. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[7]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[7]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[7]++; + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[7] != dest_message[7])) + { + + /* Queue error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[7]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[7] != dest_message[7])) + { + + /* Queue error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[7]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[7] != dest_message[7])) + { + + /* Queue error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[7]++; + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Delete the queues. */ + status = tx_queue_delete(&queue_1); + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + status = tx_queue_delete(&queue_0); + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + diff --git a/test/tx/regression/threadx_queue_basic_four_word_test.c b/test/tx/regression/threadx_queue_basic_four_word_test.c new file mode 100644 index 00000000..5e01bc5b --- /dev/null +++ b/test/tx/regression/threadx_queue_basic_four_word_test.c @@ -0,0 +1,423 @@ +/* This test is designed to test immediate response queue services including create + and delete. This test is for queue sizes of 4 ULONG. Two queues are used one with + a capacity of 1 message and another with a capacity of 3 messages. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static TX_QUEUE queue_0; +static TX_QUEUE queue_1; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_basic_four_word_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Four Word Test........................................ ERROR #1\n"); + test_control_return(1); + } + + /* Create the queues. */ + status = tx_queue_create(&queue_0, "queue 0", TX_4_ULONG, pointer, 4*sizeof(ULONG)); + pointer = pointer + (4*sizeof(ULONG)); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Four Word Test........................................ ERROR #2\n"); + test_control_return(1); + } + + status = tx_queue_create(&queue_1, "queue 1", TX_4_ULONG, pointer, 4*3*sizeof(ULONG)); + pointer = pointer + 4*3*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Four Word Test........................................ ERROR #3\n"); + test_control_return(1); + } +} + + + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG source_message[4]; +ULONG dest_message[4]; +ULONG expected_message[4]; + + + /* Inform user. */ + printf("Running Queue Four Word Test........................................ "); + + source_message[0] = 0x01234567; + source_message[3] = 0x89ABCDEF; + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Place something on queue 0. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (source_message[0] != dest_message[0]) || + (source_message[3] != dest_message[3])) + { + + /* Queue error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Make sure we can do the same thing again! */ + source_message[0]++; + source_message[3]++; + + /* Place something on queue 0. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (source_message[0] != dest_message[0]) || + (source_message[3] != dest_message[3])) + { + + /* Queue error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Now we need to do the same thing with the queue with three entries. */ + + source_message[0]++; + source_message[3]++; + expected_message[0] = source_message[0]; + expected_message[3] = source_message[3]; + + /* Place something on queue 1. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[3]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[3]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[3]++; + + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[3] != dest_message[3])) + { + + /* Queue error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[3]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[3] != dest_message[3])) + { + + /* Queue error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[3]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[3] != dest_message[3])) + { + + /* Queue error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[3]++; + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Make sure we can do the same thing again! */ + + /* Place something on queue 1. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[3]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[3]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[3]++; + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[3] != dest_message[3])) + { + + /* Queue error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[3]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[3] != dest_message[3])) + { + + /* Queue error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[3]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[3] != dest_message[3])) + { + + /* Queue error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[3]++; + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Delete the queues. */ + status = tx_queue_delete(&queue_1); + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + status = tx_queue_delete(&queue_0); + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + diff --git a/test/tx/regression/threadx_queue_basic_one_word_test.c b/test/tx/regression/threadx_queue_basic_one_word_test.c new file mode 100644 index 00000000..142a9b60 --- /dev/null +++ b/test/tx/regression/threadx_queue_basic_one_word_test.c @@ -0,0 +1,867 @@ +/* This test is designed to test immediate response queue services including create + and delete. This test is for queue sizes of 1 ULONG. Two queues are used one with + a capacity of 1 message and another with a capacity of 3 messages. */ + +#include <stdio.h> +#include "tx_api.h" + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static TX_THREAD thread_1; + + +static TX_TIMER timer_0; + + +static unsigned long error = 0; +static unsigned long timer_executed = 0; +static unsigned long isr_executed = 0; + +static TX_QUEUE queue_0; +static TX_QUEUE queue_1; +static TX_QUEUE queue_2; +static TX_QUEUE queue_3; + + +/* Define the external reference to the status for queue create from initialization. */ + +extern UINT test_queue_from_init; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, + VOID *queue_start, ULONG queue_size, UINT queue_control_block_size); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define the timer for this test. */ + +static void timer_entry(ULONG i) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +UINT status; +CHAR *pointer; +ULONG source = 1234; +ULONG destination; + + + /* Determine if calling queue create from initialization was successful. */ + if (test_queue_from_init != TX_SUCCESS) + { + + /* Error! */ + error++; + } + + /* Attempt to create a queue from a timer. */ + pointer = (CHAR *) 0x3000; + status = tx_queue_create(&queue_2, "queue 2", TX_1_ULONG, pointer, 3*sizeof(ULONG)); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to delete a queue from a timer. */ + status = tx_queue_delete(&queue_0); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to send something with suspension from a timer. */ + status = tx_queue_front_send(&queue_0, &source, 100); + + /* Check for status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to send something with suspension from a timer. */ + status = tx_queue_send(&queue_0, &source, 100); + + /* Check for status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to receive something with suspension from a timer. */ + status = tx_queue_receive(&queue_0, &destination, 100); + + /* Check for status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + + timer_executed = 1; +#endif +} + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +CHAR *pointer; +UINT status; +ULONG source = 1234; +ULONG destination; + + + /* Attempt to create a queue from an ISR. */ + pointer = (CHAR *) 0x3000; + status = tx_queue_create(&queue_2, "queue 2", TX_1_ULONG, pointer, 3*sizeof(ULONG)); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to delete a queue from an ISR. */ + status = tx_queue_delete(&queue_0); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to send something with suspension from an ISR. */ + status = tx_queue_front_send(&queue_0, &source, 100); + + /* Check for status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to send something with suspension from an ISR. */ + status = tx_queue_send(&queue_0, &source, 100); + + /* Check for status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to receive something with suspension from an ISR. */ + status = tx_queue_receive(&queue_0, &destination, 100); + + /* Check for status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + isr_executed = 1; +#endif +} + + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_basic_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + status += tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue One Word Queue Test................................... ERROR #1\n"); + test_control_return(1); + } + + /* Create the queues. */ + status = tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, sizeof(ULONG)); + pointer = pointer + sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue One Word Queue Test................................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_queue_create(&queue_1, "queue 1", TX_1_ULONG, pointer, 3*sizeof(ULONG)); + pointer = pointer + 3*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue One Word Queue Test................................... ERROR #3\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG source_message = 0x12345678UL; +ULONG dest_message; +ULONG expected_message; +#ifndef TX_DISABLE_ERROR_CHECKING +CHAR *pointer; +#endif + + /* Inform user. */ + printf("Running Queue One Word Queue Test................................... "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to create with NULL queue. */ + pointer = (CHAR *) 0x3000; + status = tx_queue_create(TX_NULL, "queue 1", TX_1_ULONG, pointer, 3*sizeof(ULONG)); + + /* Check for status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Attempt to create with bad sized queue control block. */ + status = _txe_queue_create(&queue_3, "queue 3", TX_1_ULONG, pointer, 3*sizeof(ULONG), (sizeof(TX_QUEUE)+1)); + + /* Check for status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Attempt to create with bad sized message. */ + status = tx_queue_create(&queue_3, "queue 3", 0, pointer, 3*sizeof(ULONG)); + + /* Check for status. */ + if (status != TX_SIZE_ERROR) + { + + /* Queue error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Attempt to create a queue that has already been created. */ + pointer = (CHAR *) 0x3000; + status = tx_queue_create(&queue_0, "queue 1", TX_1_ULONG, pointer, 3*sizeof(ULONG)); + + /* Check for status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Attempt to create a queue with an invalid message size. */ + pointer = (CHAR *) 0x3000; + status = tx_queue_create(&queue_2, "queue 2", 47, pointer, 3*sizeof(ULONG)); + + /* Check for status. */ + if (status != TX_SIZE_ERROR) + { + + /* Queue error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Attempt to create a queue with a NULL queue area. */ + status = tx_queue_create(&queue_2, "queue 2", TX_1_ULONG, TX_NULL, 3*sizeof(ULONG)); + + /* Check for status. */ + if (status != TX_PTR_ERROR) + { + + /* Queue error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to create a queue with a too small queue area. */ + pointer = (CHAR *) 0x3000; + status = tx_queue_create(&queue_2, "queue 2", TX_1_ULONG, pointer, 1); + + /* Check for status. */ + if (status != TX_SIZE_ERROR) + { + + /* Queue error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Attempt to delete a NULL pointer. */ + status = tx_queue_delete(TX_NULL); + + /* Check for status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Attempt to delete a non-created queue. */ + queue_2.tx_queue_id = 0; + status = tx_queue_delete(&queue_2); + + /* Check for status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Attempt to flush a NULL pointer. */ + status = tx_queue_flush(TX_NULL); + + /* Check for status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Attempt to flush a non-created queue. */ + queue_2.tx_queue_id = 0; + status = tx_queue_flush(&queue_2); + + /* Check for status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Attempt to send something to the front of a non-queue. */ + status = tx_queue_front_send(TX_NULL, &source_message, TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Attempt to send something to the front of a non-created queue. */ + queue_2.tx_queue_id = 0; + status = tx_queue_front_send(&queue_2, &source_message, TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Attempt to send something with a NULL source pointer. */ + status = tx_queue_front_send(&queue_0, TX_NULL, TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_PTR_ERROR) + { + + /* Queue error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Attempt to send something to a non-queue. */ + status = tx_queue_send(TX_NULL, &source_message, TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Attempt to send something to a non-created queue. */ + queue_2.tx_queue_id = 0; + status = tx_queue_send(&queue_2, &source_message, TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Attempt to send something with a NULL source pointer. */ + status = tx_queue_send(&queue_0, TX_NULL, TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_PTR_ERROR) + { + + /* Queue error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Attempt to receive something from a non-queue. */ + status = tx_queue_receive(TX_NULL, &dest_message, TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + /* Attempt to receive something from a non-created queue. */ + queue_2.tx_queue_id = 0; + status = tx_queue_receive(&queue_2, &dest_message, TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + /* Attempt to receive something to a NULL destination. */ + status = tx_queue_receive(&queue_0, TX_NULL, TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_PTR_ERROR) + { + + /* Queue error. */ + printf("ERROR #23\n"); + test_control_return(1); + } +#endif + + /* Place something on queue 0. */ + status = tx_queue_send(&queue_0, &source_message, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_0, &source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (source_message != dest_message)) + { + + /* Queue error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Make sure we can do the same thing again! */ + source_message++; + + /* Place something on queue 0. */ + status = tx_queue_send(&queue_0, &source_message, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #28\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_0, &source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #29\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (source_message != dest_message)) + { + + /* Queue error. */ + printf("ERROR #30\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #31\n"); + test_control_return(1); + } + + /* Now we need to do the same thing with the queue with three entries. */ + + source_message++; + expected_message = source_message; + + /* Place something on queue 1. */ + status = tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + source_message++; + status += tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + source_message++; + status += tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + source_message++; + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #32\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #33\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message++ != dest_message)) + { + + /* Queue error. */ + printf("ERROR #34\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message++ != dest_message)) + { + + /* Queue error. */ + printf("ERROR #35\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message++ != dest_message)) + { + + /* Queue error. */ + printf("ERROR #36\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #37\n"); + test_control_return(1); + } + + /* Make sure we can do the same thing again! */ + + /* Place something on queue 1. */ + status = tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + source_message++; + status += tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + source_message++; + status += tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + source_message++; + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #38\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #39\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message++ != dest_message)) + { + + /* Queue error. */ + printf("ERROR #40\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message++ != dest_message)) + { + + /* Queue error. */ + printf("ERROR #41\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message++ != dest_message)) + { + + /* Queue error. */ + printf("ERROR #42\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #43\n"); + test_control_return(1); + } + + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Create a timer for the test. */ + tx_timer_create(&timer_0, "timer 0", timer_entry, 0, 1, 1, TX_AUTO_ACTIVATE); + + /* Setup the ISR. */ + test_isr_dispatch = test_isr; + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Resume thread 1 so that we can take an interrupt on top of it. */ + tx_thread_resume(&thread_1); + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Clear the ISR. */ + test_isr_dispatch = TX_NULL; + + /* Test for error. */ + if ((error) || (timer_executed != 1) || (isr_executed != 1)) + { + + /* Queue error. */ + printf("ERROR #44\n"); + test_control_return(1); + } + +#endif + + /* Delete the queues. */ + status = tx_queue_delete(&queue_1); + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #45\n"); + test_control_return(1); + } + + status = tx_queue_delete(&queue_0); + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #46\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + +static void thread_1_entry(ULONG thread_input) +{ + + while(1) + { + + tx_thread_relinquish(); + } +} + diff --git a/test/tx/regression/threadx_queue_basic_sixteen_word_test.c b/test/tx/regression/threadx_queue_basic_sixteen_word_test.c new file mode 100644 index 00000000..703a1cf4 --- /dev/null +++ b/test/tx/regression/threadx_queue_basic_sixteen_word_test.c @@ -0,0 +1,423 @@ +/* This test is designed to test immediate response queue services including create + and delete. This test is for queue sizes of 16 ULONG. Two queues are used one with + a capacity of 1 message and another with a capacity of 3 messages. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static TX_QUEUE queue_0; +static TX_QUEUE queue_1; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_basic_sixteen_word_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Sixteen Word Test..................................... ERROR #1\n"); + test_control_return(1); + } + + /* Create the queues. */ + status = tx_queue_create(&queue_0, "queue 0", TX_16_ULONG, pointer, 16*sizeof(ULONG)); + pointer = pointer + (16*sizeof(ULONG)); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Sixteen Word Test..................................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_queue_create(&queue_1, "queue 1", TX_16_ULONG, pointer, 16*3*sizeof(ULONG)); + pointer = pointer + 16*3*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Sixteen Word Test..................................... ERROR #3\n"); + test_control_return(1); + } +} + + + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG source_message[16]; +ULONG dest_message[16]; +ULONG expected_message[16]; + + + /* Inform user. */ + printf("Running Queue Sixteen Word Test..................................... "); + + source_message[0] = 0x01234567; + source_message[15] = 0x89ABCDEF; + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Place something on queue 0. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (source_message[0] != dest_message[0]) || + (source_message[15] != dest_message[15])) + { + + /* Queue error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Make sure we can do the same thing again! */ + source_message[0]++; + source_message[15]++; + + /* Place something on queue 0. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (source_message[0] != dest_message[0]) || + (source_message[15] != dest_message[15])) + { + + /* Queue error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Now we need to do the same thing with the queue with three entries. */ + + source_message[0]++; + source_message[15]++; + expected_message[0] = source_message[0]; + expected_message[15] = source_message[15]; + + /* Place something on queue 1. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[15]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[15]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[15]++; + + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[15] != dest_message[15])) + { + + /* Queue error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[15]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[15] != dest_message[15])) + { + + /* Queue error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[15]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[15] != dest_message[15])) + { + + /* Queue error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[15]++; + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Make sure we can do the same thing again! */ + + /* Place something on queue 1. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[15]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[15]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[15]++; + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[15] != dest_message[15])) + { + + /* Queue error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[15]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[15] != dest_message[15])) + { + + /* Queue error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[15]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[15] != dest_message[15])) + { + + /* Queue error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[15]++; + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Delete the queues. */ + status = tx_queue_delete(&queue_1); + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + status = tx_queue_delete(&queue_0); + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + diff --git a/test/tx/regression/threadx_queue_basic_two_word_test.c b/test/tx/regression/threadx_queue_basic_two_word_test.c new file mode 100644 index 00000000..ab24d08e --- /dev/null +++ b/test/tx/regression/threadx_queue_basic_two_word_test.c @@ -0,0 +1,463 @@ +/* This test is designed to test immediate response queue services including create + and delete. This test is for queue sizes of 2 ULONG. Two queues are used one with + a capacity of 1 message and another with a capacity of 3 messages. */ + +#include <stdio.h> +#include "tx_api.h" + +typedef struct QUEUE_MEMORY_TEST_STRUCT +{ + ULONG first; + ULONG second; + TX_QUEUE queue; + ULONG first_middle; + ULONG second_middle; + ULONG queue_area[2048/sizeof(ULONG)]; + ULONG next_to_last; + ULONG last; + +} QUEUE_MEMORY_TEST; + +static QUEUE_MEMORY_TEST queue_memory; + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static TX_QUEUE queue_0; +static TX_QUEUE queue_1; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_basic_two_word_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Two Word Test......................................... ERROR #1\n"); + test_control_return(1); + } + + /* Create the queues. */ + status = tx_queue_create(&queue_0, "queue 0", TX_2_ULONG, pointer, 2*sizeof(ULONG)); + pointer = pointer + (2*sizeof(ULONG)); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Two Word Test......................................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_queue_create(&queue_1, "queue 1", TX_2_ULONG, pointer, 2*3*sizeof(ULONG)); + pointer = pointer + 2*3*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Two Word Test......................................... ERROR #3\n"); + test_control_return(1); + } +} + + + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG source_message[2]; +ULONG dest_message[2]; +ULONG expected_message[2]; + + + /* Inform user. */ + printf("Running Queue Two Word Test......................................... "); + + /* Perform queue memory test. */ + queue_memory.first = 0x11223344; + queue_memory.second = 0x55667788; + queue_memory.first_middle = 0x21314151; + queue_memory.second_middle= 0x61718191; + queue_memory.next_to_last = 0x99aabbcc; + queue_memory.last = 0xddeeff00; + + /* Create the queue. */ + status = tx_queue_create(&queue_memory.queue, "queue memory", TX_2_ULONG, &queue_memory.queue_area[0], (2048*sizeof(ULONG))/sizeof(ULONG)); + tx_queue_delete(&queue_memory.queue); + + /* Check for status. */ + if ((status != TX_SUCCESS) || + (queue_memory.first != 0x11223344) || + (queue_memory.second != 0x55667788) || + (queue_memory.first_middle != 0x21314151) || + (queue_memory.second_middle != 0x61718191) || + (queue_memory.next_to_last != 0x99aabbcc) || + (queue_memory.last != 0xddeeff00)) + { + /* Queue error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + source_message[0] = 0x01234567; + source_message[1] = 0x89ABCDEF; + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Place something on queue 0. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (source_message[0] != dest_message[0]) || + (source_message[1] != dest_message[1])) + { + + /* Queue error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Make sure we can do the same thing again! */ + source_message[0]++; + source_message[1]++; + + /* Place something on queue 0. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_0, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (source_message[0] != dest_message[0]) || + (source_message[1] != dest_message[1])) + { + + /* Queue error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_0, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Now we need to do the same thing with the queue with three entries. */ + + source_message[0]++; + source_message[1]++; + expected_message[0] = source_message[0]; + expected_message[1] = source_message[1]; + + /* Place something on queue 1. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[1]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[1]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[1]++; + + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[1] != dest_message[1])) + { + + /* Queue error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[1]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[1] != dest_message[1])) + { + + /* Queue error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[1]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[1] != dest_message[1])) + { + + /* Queue error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[1]++; + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Make sure we can do the same thing again! */ + + /* Place something on queue 1. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[1]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[1]++; + status += tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + source_message[0]++; + source_message[1]++; + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_1, source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[1] != dest_message[1])) + { + + /* Queue error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[1]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[1] != dest_message[1])) + { + + /* Queue error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[1]++; + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message[0] != dest_message[0]) || + (expected_message[1] != dest_message[1])) + { + + /* Queue error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + expected_message[0]++; + expected_message[1]++; + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_1, dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Delete the queues. */ + status = tx_queue_delete(&queue_1); + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + + status = tx_queue_delete(&queue_0); + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + diff --git a/test/tx/regression/threadx_queue_empty_suspension_test.c b/test/tx/regression/threadx_queue_empty_suspension_test.c new file mode 100644 index 00000000..59d53e70 --- /dev/null +++ b/test/tx/regression/threadx_queue_empty_suspension_test.c @@ -0,0 +1,271 @@ +/* This test is designed to test empty queue suspension of queue that supports 3 messages + that are each 2 ULONG in size. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static TX_QUEUE queue_0; +static TX_QUEUE queue_1; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void queue_notify(TX_QUEUE *queue_ptr) +{ + +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_empty_suspension_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Empty Suspension Test................................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Empty Suspension Test................................. ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Empty Suspension Test................................. ERROR #3\n"); + test_control_return(1); + } + + /* Create the queue. */ + status = tx_queue_create(&queue_0, "queue 0", TX_2_ULONG, pointer, 3*2*sizeof(ULONG)); + pointer = pointer + 3*2*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Empty Suspension Test................................. ERROR #4\n"); + test_control_return(1); + } + + /* Setup queue send notification. */ + status = tx_queue_send_notify(&queue_0, queue_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Empty Suspension Test................................. ERROR #5\n"); + test_control_return(1); + } + +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Queue Empty Suspension Test................................. ERROR #6\n"); + test_control_return(1); + } + +#endif +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG source_message[2] = {0x12345678, 0}; + + + /* Inform user. */ + printf("Running Queue Empty Suspension Test................................. "); + + /* Increment the thread counter. */ + thread_0_counter++; + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to setup notify on a non-queue. */ + status = tx_queue_send_notify(TX_NULL, queue_notify); + + /* Check status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Attempt to setup notify on a non-created queue. */ + queue_1.tx_queue_id = 0; + status = tx_queue_send_notify(&queue_1, queue_notify); + + /* Check status. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #8\n"); + test_control_return(1); + } +#endif + + /* Send message that should go directly into the the other thread's + destination area! We should also preempt and the queue should + be empty by the next time we get around! */ + status = tx_queue_send(&queue_0, &source_message[0], TX_NO_WAIT); + + /* Check status and run count of other thread - it should have got the + message already. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1)) + { + + /* Queue error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Now resume thread 2 to get another thread suspended on an empty queue. */ + tx_thread_resume(&thread_2); + + /* Now send 2 messages to wakeup both threads! */ + source_message[0]++; + status = tx_queue_send(&queue_0, &source_message[0], TX_NO_WAIT); + status += tx_queue_send(&queue_0, &source_message[0], TX_NO_WAIT); + + /* Check status and run count of other thread - it should have got the + message already. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 2) || (thread_2_counter != 1)) + { + + /* Queue error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +ULONG expected_message[2] = {0x12345678, 0}; +ULONG dest_message[2]; + + + /* Loop forever! */ + while(1) + { + + + /* Receive message from empty queue with suspension. We should always + suspend until thread 0 executes. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_WAIT_FOREVER); + + if ((status != TX_SUCCESS) || (dest_message[0] != expected_message[0]++)) + break; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; +ULONG expected_message[2] = {0x12345679, 0}; +ULONG dest_message[2]; + + + /* Loop forever! */ + while(1) + { + + + /* Receive message from empty queue with suspension. We should always + suspend until thread 0 executes. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_WAIT_FOREVER); + + if ((status != TX_SUCCESS) || (dest_message[0] != expected_message[0]++)) + break; + + /* Increment the thread counter. */ + thread_2_counter++; + } +} + diff --git a/test/tx/regression/threadx_queue_flush_no_suspension_test.c b/test/tx/regression/threadx_queue_flush_no_suspension_test.c new file mode 100644 index 00000000..940259f2 --- /dev/null +++ b/test/tx/regression/threadx_queue_flush_no_suspension_test.c @@ -0,0 +1,216 @@ +/* This test is designed to test the queue flush operation on a queue that has no threads + suspended on it. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static TX_QUEUE queue_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void queue_notify(TX_QUEUE *queue_ptr) +{ + +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_flush_no_suspension_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Flush No Suspension Test.............................. ERROR #1\n"); + test_control_return(1); + } + + /* Create the queue. */ + status = tx_queue_create(&queue_0, "queue 0", TX_2_ULONG, pointer, 3*2*sizeof(ULONG)); + pointer = pointer + 3*2*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Flush No Suspension Test.............................. ERROR #2\n"); + test_control_return(1); + } + + /* Setup queue send notification. */ + status = tx_queue_send_notify(&queue_0, queue_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Flush No Suspension Test.............................. ERROR #3\n"); + test_control_return(1); + } +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Queue Flush No Suspension Test.............................. ERROR #4\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +ULONG message[2] = {0x12345678, 0}; +UINT status; + + + /* Inform user. */ + printf("Running Queue Flush No Suspension Test.............................. "); + + /* Fill up the queue. */ + status = tx_queue_send(&queue_0, &message[0], TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #5\n"); + test_control_return(1); + } + + status = tx_queue_send(&queue_0, &message[0], TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #6\n"); + test_control_return(1); + } + + status = tx_queue_send(&queue_0, &message[0], TX_NO_WAIT); + + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Flush queue 0 to make more room. */ + status = tx_queue_flush(&queue_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #8\n"); + test_control_return(1); + } + + + /* Fill up the queue. */ + status = tx_queue_send(&queue_0, &message[2], TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #9\n"); + test_control_return(1); + } + + status = tx_queue_send(&queue_0, &message[2], TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #10\n"); + test_control_return(1); + } + + status = tx_queue_send(&queue_0, &message[2], TX_NO_WAIT); + + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Flush queue again to empty and then flush to test on an empty queue. */ + status = tx_queue_flush(&queue_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #12\n"); + test_control_return(1); + } + + status = tx_queue_flush(&queue_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Success if we get here. */ + printf("SUCCESS!\n"); + test_control_return(0); + + /* Increment the thread counter. */ + thread_0_counter++; +} + diff --git a/test/tx/regression/threadx_queue_flush_test.c b/test/tx/regression/threadx_queue_flush_test.c new file mode 100644 index 00000000..6d65c971 --- /dev/null +++ b/test/tx/regression/threadx_queue_flush_test.c @@ -0,0 +1,249 @@ +/* This test is designed to test the queue flush operation on a queue that has two threads + suspended on it. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static TX_QUEUE queue_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void queue_notify(TX_QUEUE *queue_ptr) +{ + +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_flush_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Flush w/Suspended Threads Test........................ ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Flush w/Suspended Threads Test........................ ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Flush w/Suspended Threads Test........................ ERROR #3\n"); + test_control_return(1); + } + + + /* Create the queue. */ + status = tx_queue_create(&queue_0, "queue 0", TX_2_ULONG, pointer, 3*2*sizeof(ULONG)); + pointer = pointer + 3*2*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Flush w/Suspended Threads Test........................ ERROR #4\n"); + test_control_return(1); + } + + /* Setup queue send notification. */ + status = tx_queue_send_notify(&queue_0, queue_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Flush w/Suspended Threads Test........................ ERROR #5\n"); + test_control_return(1); + } +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Queue Flush w/Suspended Threads Test........................ ERROR #6\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +ULONG message[2] = {0x12345678, 0}; +UINT status; + + + /* Inform user. */ + printf("Running Queue Flush w/Suspended Threads Test........................ "); + + /* Fill up the queue. */ + status = tx_queue_send(&queue_0, &message[0], TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #7\n"); + test_control_return(1); + } + + status = tx_queue_send(&queue_0, &message[0], TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #8\n"); + test_control_return(1); + } + + status = tx_queue_send(&queue_0, &message[0], TX_NO_WAIT); + + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Relinquish to get other threads suspended on the queue full. */ + tx_thread_relinquish(); + + /* Flush queue 0 which has the threads suspended on it. */ + status = tx_queue_flush(&queue_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Relinquish to let other threads run and finish! */ + tx_thread_relinquish(); + + /* Determine if the queue flush test was successful. */ + if ((thread_1_counter == 1) && (thread_2_counter == 1)) + { + + /* Successful queue flush test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } + else + { + + /* Queue Flush error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Increment the thread counter. */ + thread_0_counter++; +} + + +static void thread_1_entry(ULONG thread_input) +{ +UINT status; +ULONG message[2] = {0x1, 0}; + + + /* Receive message from empty queue. */ + status = tx_queue_send(&queue_0, &message[0], TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + return; + + /* Increment the thread counter. */ + thread_1_counter++; +} + + +static void thread_2_entry(ULONG thread_input) +{ +UINT status; +ULONG message[2] = {0x2, 0}; + + + /* Receive message from empty queue. */ + status = tx_queue_send(&queue_0, &message[0], TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + return; + + /* Increment the thread counter. */ + thread_2_counter++; +} + diff --git a/test/tx/regression/threadx_queue_front_send_test.c b/test/tx/regression/threadx_queue_front_send_test.c new file mode 100644 index 00000000..5329670b --- /dev/null +++ b/test/tx/regression/threadx_queue_front_send_test.c @@ -0,0 +1,686 @@ +/* This test is designed to test immediate response queue services including queue front send. + This test is for queue sizes of 2 ULONG. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static TX_THREAD thread_2; + +static TX_QUEUE queue_0; + + +static unsigned long thread_1a_counter = 0; +static TX_THREAD thread_1a; + +static TX_THREAD thread_2a; + +static TX_QUEUE queue_0a; + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_1a_entry(ULONG thread_input); +static void thread_2a_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void queue_notify(TX_QUEUE *queue_ptr) +{ + +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_front_send_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Front Test............................................ ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status = tx_thread_create(&thread_1a, "thread 1a", thread_1a_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Front Test............................................ ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status = tx_thread_create(&thread_2a, "thread 2a", thread_2a_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Front Test............................................ ERROR #3\n"); + test_control_return(1); + } + + /* Create the queues. */ + status = tx_queue_create(&queue_0, "queue 0", TX_2_ULONG, pointer, 2*2*sizeof(ULONG)); + pointer = pointer + 2*2*sizeof(ULONG); + status = tx_queue_create(&queue_0a, "queue 0a", TX_1_ULONG, pointer, 2*1*sizeof(ULONG)); + pointer = pointer + 2*1*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Front Test............................................ ERROR #4\n"); + test_control_return(1); + } + + /* Setup queue send notification. */ + status = tx_queue_send_notify(&queue_0, queue_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Front Test............................................ ERROR #5\n"); + test_control_return(1); + } +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Queue Front Test............................................ ERROR #6\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG source_message[2] = {0x12345678, 0}; +ULONG dest_message[2]; +ULONG temp[2]; + + + /* Inform user. */ + printf("Running Queue Front Test............................................ "); + + /* Perform the 1 word queue front send test. */ + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Place something on queue 0a. */ + status = tx_queue_send(&queue_0a, &source_message[0], TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #7a\n"); + test_control_return(1); + } + + /* Place a new message on the front of the queue. */ + temp[0] = 0xF000001; + status = tx_queue_front_send(&queue_0a, &temp[0], TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #8a\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0a. */ + status = tx_queue_receive(&queue_0a, &dest_message[0], TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (dest_message[0] != temp[0])) + { + + /* Queue error. */ + printf("ERROR #9a\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0a. */ + status = tx_queue_receive(&queue_0a, &dest_message[0], TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (dest_message[0] != source_message[0])) + { + + /* Queue error. */ + printf("ERROR #10a\n"); + test_control_return(1); + } + + /* Attempt to receive another message from the queue. */ + status = tx_queue_receive(&queue_0a, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #11a\n"); + test_control_return(1); + } + + /* At this point the queue is empty. Resume another thread to + suspend on an empty queue. */ + tx_thread_resume(&thread_1a); + + /* Relinquish to get this thread suspended on the empty queue. */ + tx_thread_relinquish(); + + /* Resume thread 2a to get another thread suspended on the empty queue. */ + tx_thread_resume(&thread_2a); + + /* Now send something to the front of the queue, which will resume + the first waiting thread. */ + temp[0] = 0xFF00002; + status = tx_queue_front_send(&queue_0a, &temp[0], TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #12a\n"); + test_control_return(1); + } + + /* Now send something to the front of the queue, which will resume + the second waiting thread. */ + temp[0] = 0xFF00002; + status = tx_queue_front_send(&queue_0a, &temp[0], TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #13a\n"); + test_control_return(1); + } + + /* Now relinquish again to let the other thread process the message. */ + tx_thread_relinquish(); + + /* At this point, the other thread should have placed 2 messages on the queue + so we will now send to the front, but without suspension. */ + temp[0] = 0xFF00003; + status = tx_queue_front_send(&queue_0a, &temp[0], TX_NO_WAIT); + + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #14a\n"); + test_control_return(1); + } + + /* Now, we will now send to the front, but with suspension. */ + temp[0] = 0xFF00003; + status = tx_queue_front_send(&queue_0a, &temp[0], TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #15a\n"); + test_control_return(1); + } + + /* Now resume thread 2a to get another thread suspended on the queue. */ + tx_thread_resume(&thread_2a); + + temp[0] = 0xFF00004; + status = tx_queue_front_send(&queue_0a, &temp[0], TX_WAIT_FOREVER); + + /* When we get back, the other thread has received all the messages and + verified they are in order AND relinquished. */ + if ((status != TX_SUCCESS) || (thread_1a_counter != 1)) + { + + /* Queue error. */ + printf("ERROR #16a\n"); + test_control_return(1); + } + + + /* Perform the multiword queue front send test. */ + + + /* Increment thread 0 counter. */ + thread_0_counter = 1; + + /* Reset the source message. */ + source_message[0] = 0x12345678; + source_message[1] = 0; + + /* Place something on queue 0. */ + status = tx_queue_send(&queue_0, &source_message[0], TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Place a new message on the front of the queue. */ + temp[0] = 0xF000001; + status = tx_queue_front_send(&queue_0, &temp[0], TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (dest_message[0] != temp[0])) + { + + /* Queue error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (dest_message[0] != source_message[0])) + { + + /* Queue error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Attempt to receive another message from the queue. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* At this point the queue is empty. Resume another thread to + suspend on an empty queue. */ + tx_thread_resume(&thread_1); + + /* Relinquish to get this thread suspended on the empty queue. */ + tx_thread_relinquish(); + + /* Resume thread 2 to get another thread suspended on the empty queue. */ + tx_thread_resume(&thread_2); + + /* Now send something to the front of the queue, which will resume + the first waiting thread. */ + temp[0] = 0xFF00002; + status = tx_queue_front_send(&queue_0, &temp[0], TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Now send something to the front of the queue, which will resume + the second waiting thread. */ + temp[0] = 0xFF00002; + status = tx_queue_front_send(&queue_0, &temp[0], TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Now relinquish again to let the other thread process the message. */ + tx_thread_relinquish(); + + /* At this point, the other thread should have placed 2 messages on the queue + so we will now send to the front, but without suspension. */ + temp[0] = 0xFF00003; + status = tx_queue_front_send(&queue_0, &temp[0], TX_NO_WAIT); + + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Now, we will now send to the front, but with suspension. */ + temp[0] = 0xFF00003; + status = tx_queue_front_send(&queue_0, &temp[0], TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Now resume thread 2 to get another thread suspended on the queue. */ + tx_thread_resume(&thread_2); + + temp[0] = 0xFF00004; + status = tx_queue_front_send(&queue_0, &temp[0], TX_WAIT_FOREVER); + + /* When we get back, the other thread has received all the messages and + verified they are in order AND relinquished. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1)) + { + + /* Queue error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; +ULONG source_message[2] = {0xEE000001, 0}; +ULONG dest_message[2]; + + + /* First, suspend on an empty queue. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_WAIT_FOREVER); + + /* Determine if the message is good. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xFF00002)) + return; + + /* Now fill the queue with two messages. */ + status = tx_queue_send(&queue_0, &source_message[0], TX_WAIT_FOREVER); + source_message[0]++; + status += tx_queue_front_send(&queue_0, &source_message[0], TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + return; + + /* Now let thread 0 send to the front of the queue with suspension. */ + tx_thread_relinquish(); + + /* Attempt to receive three messages from the queue. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xFF00003)) + return; + + /* Attempt to receive three messages from the queue. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xEE000002)) + return; + + /* Attempt to receive three messages from the queue. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xEE000001)) + return; + + /* At this point, we are going to fill up the queue again. */ + source_message[0]++; + status = tx_queue_send(&queue_0, &source_message[0], TX_WAIT_FOREVER); + source_message[0]++; + status += tx_queue_front_send(&queue_0, &source_message[0], TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + return; + + /* Now let thread 0 send to the front of the queue with suspension. */ + tx_thread_relinquish(); + + /* Attempt to receive four messages from the queue. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xFF00004)) + return; + + /* Attempt to receive four messages from the queue. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xDD000001)) + return; + + /* Attempt to receive four messages from the queue. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xEE000004)) + return; + + /* Attempt to receive three messages from the queue. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xEE000003)) + return; + + /* Increment this threads counter. */ + thread_1_counter++; +} + + +static void thread_2_entry(ULONG thread_input) +{ + +ULONG source_message[2] = {0xDD000001, 0}; +ULONG destination_message[2]; + + + /* Receive message. */ + tx_queue_receive(&queue_0, &destination_message[0], TX_WAIT_FOREVER); + + /* Self suspend. */ + tx_thread_suspend(&thread_2); + + /* Send another message to the front of the queue. */ + tx_queue_front_send(&queue_0, &source_message[0], TX_WAIT_FOREVER); +} + + +static void thread_1a_entry(ULONG thread_input) +{ + +UINT status; +ULONG source_message[2] = {0xEE000001, 0}; +ULONG dest_message[2]; + + + /* First, suspend on an empty queue. */ + status = tx_queue_receive(&queue_0a, &dest_message[0], TX_WAIT_FOREVER); + + /* Determine if the message is good. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xFF00002)) + return; + + /* Now fill the queue with two messages. */ + status = tx_queue_send(&queue_0a, &source_message[0], TX_WAIT_FOREVER); + source_message[0]++; + status += tx_queue_front_send(&queue_0a, &source_message[0], TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + return; + + /* Now let thread 0 send to the front of the queue with suspension. */ + tx_thread_relinquish(); + + /* Attempt to receive three messages from the queue. */ + status = tx_queue_receive(&queue_0a, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xFF00003)) + return; + + /* Attempt to receive three messages from the queue. */ + status = tx_queue_receive(&queue_0a, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xEE000002)) + return; + + /* Attempt to receive three messages from the queue. */ + status = tx_queue_receive(&queue_0a, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xEE000001)) + return; + + /* At this point, we are going to fill up the queue again. */ + source_message[0]++; + status = tx_queue_send(&queue_0a, &source_message[0], TX_WAIT_FOREVER); + source_message[0]++; + status += tx_queue_front_send(&queue_0a, &source_message[0], TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + return; + + /* Now let thread 0 send to the front of the queue with suspension. */ + tx_thread_relinquish(); + + /* Attempt to receive four messages from the queue. */ + status = tx_queue_receive(&queue_0a, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xFF00004)) + return; + + /* Attempt to receive four messages from the queue. */ + status = tx_queue_receive(&queue_0a, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xDD000001)) + return; + + /* Attempt to receive four messages from the queue. */ + status = tx_queue_receive(&queue_0a, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xEE000004)) + return; + + /* Attempt to receive three messages from the queue. */ + status = tx_queue_receive(&queue_0a, &dest_message[0], TX_NO_WAIT); + + /* Should be an error. */ + if ((status != TX_SUCCESS) || (dest_message[0] != 0xEE000003)) + return; + + /* Increment this threads counter. */ + thread_1a_counter++; +} + + +static void thread_2a_entry(ULONG thread_input) +{ + +ULONG source_message[2] = {0xDD000001, 0}; +ULONG destination_message[2]; + + + /* Receive message. */ + tx_queue_receive(&queue_0a, &destination_message[0], TX_WAIT_FOREVER); + + /* Self suspend. */ + tx_thread_suspend(&thread_2a); + + /* Send another message to the front of the queue. */ + tx_queue_front_send(&queue_0a, &source_message[0], TX_WAIT_FOREVER); +} diff --git a/test/tx/regression/threadx_queue_full_suspension_test.c b/test/tx/regression/threadx_queue_full_suspension_test.c new file mode 100644 index 00000000..556a4c77 --- /dev/null +++ b/test/tx/regression/threadx_queue_full_suspension_test.c @@ -0,0 +1,368 @@ +/* This test is designed to test queue full suspension of queue that supports 3 messages + that are each 2 ULONG in size. */ + +#include <stdio.h> +#include "tx_api.h" + +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static TX_QUEUE queue_0; + + +static unsigned long thread_1a_counter = 0; +static TX_THREAD thread_1a; + +static unsigned long thread_2a_counter = 0; +static TX_THREAD thread_2a; + +static TX_QUEUE queue_0a; + + +static ULONG queue_area[3]; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_1a_entry(ULONG thread_input); +static void thread_2a_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void queue_notify(TX_QUEUE *queue_ptr) +{ + +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_full_suspension_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Full Suspension Test.................................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_create(&thread_1a, "thread 1a", thread_1a_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Full Suspension Test.................................. ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_create(&thread_2a, "thread 2a", thread_2a_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Full Suspension Test.................................. ERROR #3\n"); + test_control_return(1); + } + + /* Create the queue. */ + status = tx_queue_create(&queue_0, "queue 0", TX_2_ULONG, pointer, 3*2*sizeof(ULONG)); + pointer = pointer + 3*2*sizeof(ULONG); + status += tx_queue_create(&queue_0a, "queue 0a", TX_1_ULONG, pointer, 3*1*sizeof(ULONG)); + pointer = pointer + 3*1*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Full Suspension Test.................................. ERROR #4\n"); + test_control_return(1); + } + + /* Setup queue send notification. */ + status = tx_queue_send_notify(&queue_0, queue_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Full Suspension Test.................................. ERROR #5\n"); + test_control_return(1); + } +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Queue Full Suspension Test.................................. ERROR #6\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG source_message[2] = {0x12345678, 0}; +ULONG dest_message[2]; + + + /* Inform user. */ + printf("Running Queue Full Suspension Test.................................. "); + + /* Perform the one word queue version. */ + + /* Suspend to get thread 1a to pend on the queue. */ + tx_thread_suspend(&thread_0); + status = tx_queue_send(&queue_0a, &source_message[0], TX_NO_WAIT); + tx_thread_suspend(&thread_0); + tx_thread_resume(&thread_1a); + tx_thread_resume(&thread_2a); + tx_queue_delete(&queue_0a); + status += tx_queue_create(&queue_0a, "queue 0a", TX_1_ULONG, queue_area, sizeof(queue_area)); + + + /* Fill the queue with an initial 3 messages! */ + status += tx_queue_send(&queue_0a, &source_message[0], TX_NO_WAIT); + status += tx_queue_send(&queue_0a, &source_message[0], TX_NO_WAIT); + status += tx_queue_send(&queue_0a, &source_message[0], TX_NO_WAIT); + source_message[0]++; + + /* Receive two of the messages back to put the first received message at the end + of the queue. */ + status += tx_queue_receive(&queue_0a, &dest_message[0], TX_NO_WAIT); + status += tx_queue_receive(&queue_0a, &dest_message[0], TX_NO_WAIT); + status += tx_queue_send(&queue_0a, &source_message[0], TX_NO_WAIT); + source_message[0]++; + status += tx_queue_send(&queue_0a, &source_message[0], TX_NO_WAIT); + source_message[0]++; + + /* Check status and run count of other thread. */ + if ((status != TX_SUCCESS) || (thread_1a_counter != 0)) + { + + /* Queue error. */ + printf("ERROR #6a\n"); + test_control_return(1); + } + + /* Send message that should cause this thread to suspend, until the + lower priority thread receives a message. */ + status = tx_queue_send(&queue_0a, &source_message[0], TX_WAIT_FOREVER); + + /* Check status and run count of other thread - it should have got the + message already even though its counter is still 0 (it was preempted + in the queue receive call. */ + if ((status != TX_SUCCESS) || (thread_1a_counter != 5) || (thread_2a_counter != 1)) + { + + /* Queue error. */ + printf("ERROR #7a\n"); + test_control_return(1); + } + + /* Perform the two word queue version. */ + + /* Reset the source message. */ + source_message[0] = 0x12345678; + source_message[1] = 0; + + /* Resume threads 1 and 2. */ + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + + /* Fill the queue with an initial 3 messages! */ + status = tx_queue_send(&queue_0, &source_message[0], TX_NO_WAIT); + status += tx_queue_send(&queue_0, &source_message[0], TX_NO_WAIT); + status += tx_queue_send(&queue_0, &source_message[0], TX_NO_WAIT); + source_message[0]++; + + /* Receive two of the messages back to put the first received message at the end + of the queue. */ + status += tx_queue_receive(&queue_0, &dest_message[0], TX_NO_WAIT); + status += tx_queue_receive(&queue_0, &dest_message[0], TX_NO_WAIT); + status += tx_queue_send(&queue_0, &source_message[0], TX_NO_WAIT); + source_message[0]++; + status += tx_queue_send(&queue_0, &source_message[0], TX_NO_WAIT); + source_message[0]++; + + /* Check status and run count of other thread. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 0)) + { + + /* Queue error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Send message that should cause this thread to suspend, until the + lower priority thread receives a message. */ + status = tx_queue_send(&queue_0, &source_message[0], TX_WAIT_FOREVER); + + /* Check status and run count of other thread - it should have got the + message already even though its counter is still 0 (it was preempted + in the queue receive call. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 5) || (thread_2_counter != 1)) + { + + /* Queue error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ +UINT status; +ULONG expected_message[2] = {0x12345678, 0}; +ULONG dest_message[2]; +UINT old_priority; + + + /* Loop forever! */ + while(1) + { + + /* Receive messages and suspend. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_WAIT_FOREVER); + + if ((status != TX_SUCCESS) || (dest_message[0] != expected_message[0]++)) + break; + + /* Change thread 2 priority. */ + tx_thread_priority_change(&thread_2, 15, &old_priority); + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +ULONG source_message[2] = {0x1234567C, 0}; + + + /* Send one message to the queue. */ + tx_queue_send(&queue_0, &source_message[0], TX_WAIT_FOREVER); + + /* Increment the thread counter. */ + thread_2_counter++; +} + + +static void thread_1a_entry(ULONG thread_input) +{ +UINT status; +ULONG expected_message[2] = {0x12345678, 0}; +ULONG dest_message[2]; +UINT old_priority; + + + /* Receive message and suspend. */ + status = tx_thread_resume(&thread_0); + status += tx_queue_receive(&queue_0a, &dest_message[0], TX_WAIT_FOREVER); + status += tx_thread_resume(&thread_0); + status += tx_thread_suspend(&thread_1a); + + if ((status != TX_SUCCESS) || (dest_message[0] != expected_message[0])) + return; + + /* Loop forever! */ + while(1) + { + + /* Receive messages and suspend. */ + status = tx_queue_receive(&queue_0a, &dest_message[0], TX_WAIT_FOREVER); + + if ((status != TX_SUCCESS) || (dest_message[0] != expected_message[0]++)) + break; + + /* Change thread 2a priority. */ + tx_thread_priority_change(&thread_2a, 15, &old_priority); + + /* Increment the thread counter. */ + thread_1a_counter++; + } +} + + +static void thread_2a_entry(ULONG thread_input) +{ + +ULONG source_message[2] = {0x1234567C, 0}; + + + /* Send one message to the queue. */ + tx_queue_send(&queue_0a, &source_message[0], TX_WAIT_FOREVER); + + /* Increment the thread counter. */ + thread_2a_counter++; +} diff --git a/test/tx/regression/threadx_queue_information_test.c b/test/tx/regression/threadx_queue_information_test.c new file mode 100644 index 00000000..c1db82ca --- /dev/null +++ b/test/tx/regression/threadx_queue_information_test.c @@ -0,0 +1,664 @@ +/* This test is designed to test the queue information services. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_queue.h" + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static TX_QUEUE queue_0; +static TX_QUEUE queue_1; +static TX_QUEUE queue_2; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +UINT _tx_queue_performance_info_get(TX_QUEUE *queue_ptr, ULONG *messages_sent, ULONG *messages_received, + ULONG *empty_suspensions, ULONG *full_suspensions, ULONG *full_errors, ULONG *timeouts); + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_information_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Information Test...................................... ERROR #1\n"); + test_control_return(1); + } + + /* Create the queues. */ + status = tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, sizeof(ULONG)); + pointer = pointer + sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Information Test...................................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_queue_create(&queue_1, "queue 1", TX_1_ULONG, pointer, 3*sizeof(ULONG)); + pointer = pointer + 3*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Information Test...................................... ERROR #3\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG source_message = 0x12345678UL; +ULONG dest_message; +ULONG expected_message; +CHAR *name; +ULONG enqueued; +ULONG available_storage; +TX_THREAD *first_suspended; +ULONG suspended_count; +TX_QUEUE *next_queue; +ULONG messages_sent; +ULONG messages_received; +ULONG empty_suspensions; +ULONG full_suspensions; +ULONG full_errors; +ULONG timeouts; + + + /* Inform user. */ + printf("Running Queue Information Test...................................... "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to get info from a non-queue. */ + status = tx_queue_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #\n"); + test_control_return(1); + } + + /* Attempt to get info from a non-created queue. */ + queue_2.tx_queue_id = 0; + status = tx_queue_info_get(&queue_2, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #4\n"); + test_control_return(1); + } +#endif + + /* Place something on queue 0. */ + status = tx_queue_send(&queue_0, &source_message, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_0, &source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (source_message != dest_message)) + { + + /* Queue error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Make sure we can do the same thing again! */ + source_message++; + + /* Place something on queue 0. */ + status = tx_queue_send(&queue_0, &source_message, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_0, &source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 0. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (source_message != dest_message)) + { + + /* Queue error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Now we need to do the same thing with the queue with three entries. */ + + source_message++; + expected_message = source_message; + + /* Place something on queue 1. */ + status = tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + source_message++; + status += tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + source_message++; + status += tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + source_message++; + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message++ != dest_message)) + { + + /* Queue error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message++ != dest_message)) + { + + /* Queue error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message++ != dest_message)) + { + + /* Queue error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Make sure we can do the same thing again! */ + + /* Place something on queue 1. */ + status = tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + source_message++; + status += tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + source_message++; + status += tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + source_message++; + + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Attempt to place something on a full queue. */ + status = tx_queue_send(&queue_1, &source_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_FULL) + { + + /* Queue error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message++ != dest_message)) + { + + /* Queue error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message++ != dest_message)) + { + + /* Queue error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + /* Attempt to receive something from queue 1. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be successful and dest_message should equal source. */ + if ((status != TX_SUCCESS) || (expected_message++ != dest_message)) + { + + /* Queue error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Attempt to receive something from an empty queue. */ + status = tx_queue_receive(&queue_1, &dest_message, TX_NO_WAIT); + + /* Should be an error. */ + if (status != TX_QUEUE_EMPTY) + { + + /* Queue error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Get queue information. */ + status = tx_queue_info_get(&queue_0, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_queue_info_get(&queue_0, &name, &enqueued, &available_storage, &first_suspended, &suspended_count, &next_queue); + + /* Check for errors. */ + if ((status != TX_SUCCESS) || (enqueued != queue_0.tx_queue_enqueued) || (available_storage != queue_0.tx_queue_available_storage) || + (first_suspended != queue_0.tx_queue_suspension_list) || (suspended_count != queue_0.tx_queue_suspended_count) || + (next_queue != queue_0.tx_queue_created_next)) + { + + /* Queue error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + + /* Test null pointer for queue performance info get. */ + status = _tx_queue_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Should be an error! */ + if (status != TX_PTR_ERROR) + { + + /* Queue error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + /* Get performance information. */ + status = tx_queue_performance_info_get(&queue_0, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_queue_performance_info_get(&queue_0, &messages_sent, &messages_received, &empty_suspensions, &full_suspensions, &full_errors, &timeouts); + + /* Check for errors. */ + if ((status != TX_SUCCESS) || (messages_sent != queue_0.tx_queue_performance_messages_sent_count) || (messages_received != queue_0.tx_queue_performance_messages_received_count) || + (empty_suspensions != queue_0.tx_queue_performance_empty_suspension_count) || (full_suspensions != queue_0.tx_queue_performance_full_suspension_count) || + (full_errors != queue_0.tx_queue_performance_full_error_count) || (timeouts != queue_0.tx_queue_performance_timeout_count)) + { + + /* Queue error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Get system performance information. */ + status = tx_queue_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_queue_performance_system_info_get(&messages_sent, &messages_received, &empty_suspensions, &full_suspensions, &full_errors, &timeouts); + + /* Check for errors. */ + if ((status != TX_SUCCESS) || (messages_sent != _tx_queue_performance_messages_sent_count) || (messages_received != _tx_queue_performance__messages_received_count) || + (empty_suspensions != _tx_queue_performance_empty_suspension_count) || (full_suspensions != _tx_queue_performance_full_suspension_count) || + (full_errors != _tx_queue_performance_full_error_count) || (timeouts != _tx_queue_performance_timeout_count)) + { + + /* Queue error. */ + printf("ERROR #28\n"); + test_control_return(1); + } + +#else + + /* Get performance information. */ + status = tx_queue_performance_info_get(&queue_0, &messages_sent, &messages_received, &empty_suspensions, &full_suspensions, &full_errors, &timeouts); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #29\n"); + test_control_return(1); + } + + /* Get performance information. */ + status = tx_queue_performance_info_get(TX_NULL, &messages_sent, &messages_received, &empty_suspensions, &full_suspensions, &full_errors, &timeouts); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #30\n"); + test_control_return(1); + } + + /* Get performance information. */ + status = tx_queue_performance_info_get(TX_NULL, TX_NULL, &messages_received, &empty_suspensions, &full_suspensions, &full_errors, &timeouts); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #31\n"); + test_control_return(1); + } + + /* Get performance information. */ + status = tx_queue_performance_info_get(TX_NULL, TX_NULL, TX_NULL, &empty_suspensions, &full_suspensions, &full_errors, &timeouts); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #32\n"); + test_control_return(1); + } + + /* Get performance information. */ + status = tx_queue_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, &full_suspensions, &full_errors, &timeouts); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #33\n"); + test_control_return(1); + } + + /* Get performance information. */ + status = tx_queue_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &full_errors, &timeouts); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #34\n"); + test_control_return(1); + } + + /* Get performance information. */ + status = tx_queue_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &timeouts); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #35\n"); + test_control_return(1); + } + + /* Get performance information. */ + status = tx_queue_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #36\n"); + test_control_return(1); + } + + /* Get system performance information. */ + status = tx_queue_performance_system_info_get(&messages_sent, &messages_received, &empty_suspensions, &full_suspensions, &full_errors, &timeouts); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #37\n"); + test_control_return(1); + } + + /* Get system performance information. */ + status = tx_queue_performance_system_info_get(TX_NULL, &messages_received, &empty_suspensions, &full_suspensions, &full_errors, &timeouts); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #38\n"); + test_control_return(1); + } + + /* Get system performance information. */ + status = tx_queue_performance_system_info_get(TX_NULL, TX_NULL, &empty_suspensions, &full_suspensions, &full_errors, &timeouts); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #39\n"); + test_control_return(1); + } + + /* Get system performance information. */ + status = tx_queue_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, &full_suspensions, &full_errors, &timeouts); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #40\n"); + test_control_return(1); + } + + /* Get system performance information. */ + status = tx_queue_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, &full_errors, &timeouts); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #41\n"); + test_control_return(1); + } + + /* Get system performance information. */ + status = tx_queue_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &timeouts); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #42\n"); + test_control_return(1); + } + + /* Get system performance information. */ + status = tx_queue_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Should be an error! */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Queue error. */ + printf("ERROR #43\n"); + test_control_return(1); + } + +#endif + + /* Delete the queues. */ + status = tx_queue_delete(&queue_1); + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #44\n"); + test_control_return(1); + } + + status = tx_queue_delete(&queue_0); + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #45\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} diff --git a/test/tx/regression/threadx_queue_prioritize.c b/test/tx/regression/threadx_queue_prioritize.c new file mode 100644 index 00000000..7a9d2b44 --- /dev/null +++ b/test/tx/regression/threadx_queue_prioritize.c @@ -0,0 +1,534 @@ +/* This test is designed to test queue prioritize. */ + +#include <stdio.h> +#include "tx_api.h" + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +/* Define the external reference for the preempt disable flag. */ + +extern volatile UINT _tx_thread_preempt_disable; + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static TX_THREAD thread_2; + +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + +static unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; + +static unsigned long thread_5_counter = 0; +static TX_THREAD thread_5; + +static unsigned long thread_6_counter = 0; +static TX_THREAD thread_6; + +static TX_QUEUE queue_0; +static TX_QUEUE queue_1; + + +static int test_status; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +static void thread_5_entry(ULONG thread_input); +static void thread_6_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void queue_notify(TX_QUEUE *queue_ptr) +{ + +} + + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + + /* Determine if the test case we are looking for is present. */ + if ((_tx_thread_preempt_disable) && (test_status == 1)) + { + + /* Determine if thread 3 is at the front of the suspension list. */ + if (queue_0.tx_queue_suspension_list == &thread_3) + { + + /* Abort the wait of thread 3. */ + tx_thread_wait_abort(&thread_3); + } + else + { + + /* Abort the wait of thread 5. */ + tx_thread_wait_abort(&thread_5); + + /* End the ISR processing. */ + test_status = 2; + test_isr_dispatch = TX_NULL; + } + } +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_prioritize_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Prioritize Test....................................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Prioritize Test....................................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Prioritize Test....................................... ERROR #3\n"); + test_control_return(1); + } + + + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 3, 3, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Prioritize Test....................................... ERROR #4\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 4, 4, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Prioritize Test....................................... ERROR #5\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, + pointer, TEST_STACK_SIZE_PRINTF, + 5, 5, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Prioritize Test....................................... ERROR #6\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_6, "thread 6", thread_6_entry, 6, + pointer, TEST_STACK_SIZE_PRINTF, + 6, 6, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Prioritize Test....................................... ERROR #7\n"); + test_control_return(1); + } + + /* Create the queue. */ + status = tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, 3*2*sizeof(ULONG)); + pointer = pointer + 3*2*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Prioritize Test....................................... ERROR #8\n"); + test_control_return(1); + } + + /* Setup queue send notification. */ + status = tx_queue_send_notify(&queue_0, queue_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Prioritize Test....................................... ERROR #9\n"); + test_control_return(1); + } +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Queue Prioritize Test....................................... ERROR #10\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Queue Prioritize Test....................................... "); + + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to prioritize a non-queue. */ + status = tx_queue_prioritize(TX_NULL); + + /* Check for an error condition. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Attempt to prioritize a non-created queue. */ + queue_1.tx_queue_id = 0; + status = tx_queue_prioritize(&queue_1); + + /* Check for an error condition. */ + if (status != TX_QUEUE_ERROR) + { + + /* Queue error. */ + printf("ERROR #12\n"); + test_control_return(1); + } +#endif + + /* Nothing to do here, but check prioritization with no suspended threads. */ + status = tx_queue_prioritize(&queue_0); + + /* Check for an error condition. */ + if (status != TX_SUCCESS) + { + + /* Queue error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + + /* Increment the thread counter. */ + thread_0_counter++; + + /* Make sure thread 1 and 2 are suspended on the queue. */ + if ((thread_1.tx_thread_state != TX_QUEUE_SUSP) || (thread_2.tx_thread_state != TX_QUEUE_SUSP) || + (queue_0.tx_queue_suspension_list != &thread_1)) + { + + /* Queue error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Prioritize the queue suspension list. */ + status = tx_queue_prioritize(&queue_0); + + /* Check status and make sure thread 2 is not at the head of the list. */ + if ((status != TX_SUCCESS) || (queue_0.tx_queue_suspension_list != &thread_2)) + { + + /* Queue error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Prioritize the queue suspension list again, but slightly different path because it was previously prioritized. */ + status = tx_queue_prioritize(&queue_0); + + /* Check status and make sure thread 2 not at the head of the list. */ + if ((status != TX_SUCCESS) || (queue_0.tx_queue_suspension_list != &thread_2)) + { + + /* Queue error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* At this point we are going to get more than 2 threads suspended. */ + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + tx_thread_resume(&thread_3); + tx_thread_resume(&thread_4); + tx_thread_resume(&thread_5); + tx_thread_resume(&thread_6); + + /* Prioritize the queue suspension list. */ + status = tx_queue_prioritize(&queue_0); + + /* Check status and make sure thread 3 is at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (queue_0.tx_queue_suspension_list != &thread_3)) + { + + /* Queue error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Now loop to test the interrupt of the prioritize loop logic. */ + test_status = 1; + test_isr_dispatch = test_isr; + do + { + + /* Prioritize the queue suspension list. */ + status = tx_queue_prioritize(&queue_0); + + /* Check status and make sure thread 1 is terminated. */ + if (status != TX_SUCCESS) + { + + /* Block Pool error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + } while (test_status == 1); + + /* Now determine if thread 4 is at the front of the list... It should be! */ + if (queue_0.tx_queue_suspension_list != &thread_4) + { + + /* Queue error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ +UINT status; +ULONG dest_message; + + + /* Loop forever! */ + while(1) + { + + + /* Receive message from empty queue. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_WAIT_FOREVER); + + if (status != TX_QUEUE_EMPTY) + break; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ +UINT status; +ULONG dest_message; + + + /* Loop forever! */ + while(1) + { + + + /* Receive message from empty queue. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_WAIT_FOREVER); + + if (status != TX_QUEUE_EMPTY) + break; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + + +static void thread_3_entry(ULONG thread_input) +{ +UINT status; +ULONG dest_message; + + + /* Loop forever! */ + while(1) + { + + + /* Receive message from empty queue. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_WAIT_FOREVER); + + if (status != TX_QUEUE_EMPTY) + break; + + /* Increment the thread counter. */ + thread_3_counter++; + } +} + + +static void thread_4_entry(ULONG thread_input) +{ +UINT status; +ULONG dest_message; + + + /* Loop forever! */ + while(1) + { + + + /* Receive message from empty queue. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_WAIT_FOREVER); + + if (status != TX_QUEUE_EMPTY) + break; + + /* Increment the thread counter. */ + thread_4_counter++; + } +} + + +static void thread_5_entry(ULONG thread_input) +{ +UINT status; +ULONG dest_message; + + + /* Loop forever! */ + while(1) + { + + + /* Receive message from empty queue. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_WAIT_FOREVER); + + if (status != TX_QUEUE_EMPTY) + break; + + /* Increment the thread counter. */ + thread_5_counter++; + } +} + + +static void thread_6_entry(ULONG thread_input) +{ +UINT status; +ULONG dest_message; + + + /* Loop forever! */ + while(1) + { + + + /* Receive message from empty queue. */ + status = tx_queue_receive(&queue_0, &dest_message, TX_WAIT_FOREVER); + + if (status != TX_QUEUE_EMPTY) + break; + + /* Increment the thread counter. */ + thread_6_counter++; + } +} + + diff --git a/test/tx/regression/threadx_queue_suspension_timeout_test.c b/test/tx/regression/threadx_queue_suspension_timeout_test.c new file mode 100644 index 00000000..a3c390ed --- /dev/null +++ b/test/tx/regression/threadx_queue_suspension_timeout_test.c @@ -0,0 +1,254 @@ +/* This test is designed to test queue full and empty suspension with timeouts on queues + that supports 3 messages that are each 2 ULONG in size. */ + +#include <stdio.h> +#include "tx_api.h" + +//static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; + +static TX_THREAD thread_1; + +static TX_THREAD thread_2; +static unsigned long thread_2_counter = 0; + +static TX_QUEUE queue_0; +static TX_QUEUE queue_1; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void queue_notify(TX_QUEUE *queue_ptr) +{ + +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_suspension_timeout_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Suspension Timeout Test............................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Suspension Timeout Test............................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Suspension Timeout Test............................... ERROR #3\n"); + test_control_return(1); + } + + /* Create the queues. */ + status = tx_queue_create(&queue_0, "queue 0", TX_2_ULONG, pointer, 3*2*sizeof(ULONG)); + pointer = pointer + 3*2*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Suspension Timeout Test............................... ERROR #4\n"); + test_control_return(1); + } + + status = tx_queue_create(&queue_1, "queue 1", TX_2_ULONG, pointer, 3*2*sizeof(ULONG)); + pointer = pointer + 3*2*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Suspension Timeout Test............................... ERROR #5\n"); + test_control_return(1); + } + + /* Setup queue send notification. */ + status = tx_queue_send_notify(&queue_0, queue_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Suspension Timeout Test............................... ERROR #6\n"); + test_control_return(1); + } +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Queue Suspension Timeout Test............................... ERROR #7\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG source_message[2] = {0x12345678, 0}; + + + /* Inform user. */ + printf("Running Queue Suspension Timeout Test............................... "); + + /* Fill the queue with an initial 3 messages! */ + status = tx_queue_send(&queue_0, &source_message[0], TX_NO_WAIT); + source_message[0]++; + status += tx_queue_send(&queue_0, &source_message[0], TX_NO_WAIT); + source_message[0]++; + status += tx_queue_send(&queue_0, &source_message[0], TX_NO_WAIT); + source_message[0]++; + + /* Check status and run count of other thread. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 0)) + { + + /* Queue error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Send message to the front of the queue that should cause this thread to suspend. The timeout + should cause it to resume with a TX_QUEUE_FULL error code. */ + status = tx_queue_front_send(&queue_0, &source_message[0], 3); + + if ((status != TX_QUEUE_FULL) || (thread_1_counter != 0) || (thread_2_counter != 0)) + { + + /* Queue error. */ + printf("ERROR #9a\n"); + test_control_return(1); + } + + /* Send message that should cause this thread to suspend. The timeout + should cause it to resume with a TX_QUEUE_FULL error code. */ + status = tx_queue_send(&queue_0, &source_message[0], 32); + + if ((status != TX_QUEUE_FULL) || (thread_1_counter != 1) || (thread_2_counter != 1)) + { + + /* Queue error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ +UINT status; +ULONG dest_message[2]; + + + /* Loop forever! */ + while(1) + { + + + /* Receive message from empty queue with suspension and timeout. + We should wakeup after the timeout expires with an empty status. */ + status = tx_queue_receive(&queue_1, &dest_message[0], 20); + + if (status != TX_QUEUE_EMPTY) + break; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ +UINT status; +ULONG dest_message[2]; + + + /* Loop forever! */ + while(1) + { + + + /* Receive message from empty queue with suspension and timeout. + We should wakeup after the timeout expires with an empty status. */ + status = tx_queue_receive(&queue_1, &dest_message[0], 20); + + if (status != TX_QUEUE_EMPTY) + break; + + /* Increment the thread counter. */ + thread_2_counter++; + } +} diff --git a/test/tx/regression/threadx_queue_thread_terminate_test.c b/test/tx/regression/threadx_queue_thread_terminate_test.c new file mode 100644 index 00000000..d0834704 --- /dev/null +++ b/test/tx/regression/threadx_queue_thread_terminate_test.c @@ -0,0 +1,183 @@ +/* This test is designed to test thread terminate when the terminated thread is suspeded + on a queue. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static TX_QUEUE queue_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +static void queue_notify(TX_QUEUE *queue_ptr) +{ + +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_queue_thread_terminate_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Thread Terminate Test................................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Thread Terminate Test................................. ERROR #2\n"); + test_control_return(1); + } + + /* Create the queue. */ + status = tx_queue_create(&queue_0, "queue 0", TX_2_ULONG, pointer, 3*2*sizeof(ULONG)); + pointer = pointer + 3*2*sizeof(ULONG); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Thread Terminate Test................................. ERROR #3\n"); + test_control_return(1); + } + + /* Setup queue send notification. */ + status = tx_queue_send_notify(&queue_0, queue_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Queue Thread Terminate Test................................. ERROR #4\n"); + test_control_return(1); + } +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Queue Thread Terminate Test................................. ERROR #5\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Queue Thread Terminate Test................................. "); + + /* Increment the thread counter. */ + thread_0_counter++; + + /* Make sure thread 1 is suspended on the queue. */ + if (thread_1.tx_thread_state != TX_QUEUE_SUSP) + { + + /* Queue error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Terminate thread 1 which is suspended on queue 0. */ + status = tx_thread_terminate(&thread_1); + + /* Check status and make sure thread 1 is terminated. */ + if ((status != TX_SUCCESS) || (thread_1.tx_thread_state != TX_TERMINATED) || + (thread_1_counter != 0) || (queue_0.tx_queue_suspended_count)) + { + + /* Queue error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ +UINT status; +ULONG dest_message[2]; + + + /* Loop forever! */ + while(1) + { + + + /* Receive message from empty queue. */ + status = tx_queue_receive(&queue_0, &dest_message[0], TX_WAIT_FOREVER); + + if (status != TX_QUEUE_EMPTY) + break; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + diff --git a/test/tx/regression/threadx_semaphore_basic_test.c b/test/tx/regression/threadx_semaphore_basic_test.c new file mode 100644 index 00000000..f554257d --- /dev/null +++ b/test/tx/regression/threadx_semaphore_basic_test.c @@ -0,0 +1,545 @@ +/* This test is designed to test the semaphore create/delete and immediate return gets and puts. */ + +#include <stdio.h> +#include "tx_api.h" + + +typedef struct SEMAPHORE_MEMORY_TEST_STRUCT +{ + ULONG first; + ULONG second; + TX_SEMAPHORE semaphore; + ULONG next_to_last; + ULONG last; + +} SEMAPHORE_MEMORY_TEST; + +static SEMAPHORE_MEMORY_TEST semaphore_memory; + + +/* Define the external symbol to obtain the status from a create call in initialization. */ + +extern UINT test_semaphore_from_init; + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static TX_THREAD thread_1; + + +static TX_TIMER timer_0; + + +static unsigned long error = 0; +static unsigned long timer_executed = 0; +static unsigned long isr_executed = 0; + + +static TX_SEMAPHORE semaphore_0; +static TX_SEMAPHORE semaphore_1; +static TX_SEMAPHORE semaphore_2; +static TX_SEMAPHORE semaphore_3; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + +UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define the timer for this test. */ + +static void timer_entry(ULONG i) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +UINT status; + + + /* Determine if calling semaphore create from initialization was successful. */ + if (test_semaphore_from_init != TX_SUCCESS) + { + + /* Error! */ + error++; + } + + /* Attempt to create a semaphore from a timer. */ + status = tx_semaphore_create(&semaphore_2, "semaphore 2", 1); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to delete a semaphore from a timer. */ + status = tx_semaphore_delete(&semaphore_0); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to get a semaphore with suspension from a timer. */ + status = tx_semaphore_get(&semaphore_0, 100); + + /* Check for status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + + timer_executed = 1; +#endif +} + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +UINT status; + + + /* Attempt to create a semaphore from an ISR. */ + status = tx_semaphore_create(&semaphore_2, "semaphore 2", 1); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to delete a semaphore from an ISR. */ + status = tx_semaphore_delete(&semaphore_0); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to get a semaphore with suspension from an ISR. */ + status = tx_semaphore_get(&semaphore_0, 100); + + /* Check for status. */ + if (status != TX_WAIT_ERROR) + { + + /* Error! */ + error++; + } + + isr_executed = 1; +#endif +} + + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_semaphore_basic_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + status += tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Basic Test........................................ ERROR #1\n"); + test_control_return(1); + } + + /* Create a semaphore with an initial count of 1. */ + status = tx_semaphore_create(&semaphore_0, "semaphore 0", 1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Basic Test........................................ ERROR #2\n"); + test_control_return(1); + } + + /* Create a semaphore with an initial count of 0. */ + status = tx_semaphore_create(&semaphore_1, "semaphore 1", 1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Basic Test........................................ ERROR #3\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + /* Inform user. */ + printf("Running Semaphore Basic Test........................................ "); + + /* Perform semaphore memory test. */ + semaphore_memory.first = 0x11223344; + semaphore_memory.second = 0x55667788; + semaphore_memory.next_to_last = 0x99aabbcc; + semaphore_memory.last = 0xddeeff00; + + /* Create the semaphore. */ + status = tx_semaphore_create(&semaphore_memory.semaphore, "semaphore memory", 0); + tx_semaphore_delete(&semaphore_memory.semaphore); + + /* Check for status. */ + if ((status != TX_SUCCESS) || + (semaphore_memory.first != 0x11223344) || + (semaphore_memory.second != 0x55667788) || + (semaphore_memory.next_to_last != 0x99aabbcc) || + (semaphore_memory.last != 0xddeeff00)) + { + + /* Semaphore error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Increment thread 0 counter. */ + thread_0_counter++; + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to create a non-semaphore. */ + status = tx_semaphore_create(TX_NULL, "semaphore 0", 1); + + /* Check for status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Attempt to create a semaphore with a bad sized block. */ + status = _txe_semaphore_create(&semaphore_3, "semaphore 3", 1, (sizeof(TX_SEMAPHORE)+1)); + + /* Check for status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Attempt to create an already created semaphore. */ + status = tx_semaphore_create(&semaphore_0, "semaphore 0", 1); + + /* Check for status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Attempt to delete a non-semaphore. */ + status = tx_semaphore_delete(TX_NULL); + + /* Check for status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Attempt to delete a non-created semaphore. */ + semaphore_2.tx_semaphore_id = 0; + status = tx_semaphore_delete(&semaphore_2); + + /* Check for status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to get a non-semaphore. */ + status = tx_semaphore_get(TX_NULL, TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Attempt to get a non-created semaphore. */ + semaphore_2.tx_semaphore_id = 0; + status = tx_semaphore_get(&semaphore_2, TX_NO_WAIT); + + /* Check for status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Attempt to put a non-semaphore. */ + status = tx_semaphore_put(TX_NULL); + + /* Check for status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Attempt to put a non-created semaphore. */ + semaphore_2.tx_semaphore_id = 0; + status = tx_semaphore_put(&semaphore_2); + + /* Check for status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Attempt to ceiling put a non-semaphore. */ + status = tx_semaphore_ceiling_put(TX_NULL, 0); + + /* Check for status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Attempt to ceiling put a non-created semaphore. */ + semaphore_2.tx_semaphore_id = 0; + status = tx_semaphore_ceiling_put(&semaphore_2, 0); + + /* Check for status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Attempt to ceiling put with an invalid ceiling of 0. */ + status = tx_semaphore_ceiling_put(&semaphore_0, 0); + + /* Check for status. */ + if (status != TX_INVALID_CEILING) + { + + /* Semaphore error. */ + printf("ERROR #16\n"); + test_control_return(1); + } +#endif + + /* Attempt to get from semaphore with an instance. Should be successful! */ + status = tx_semaphore_get(&semaphore_0, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Semaphore error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Attempt to get from semaphore without an instance. Should be unsuccessful. */ + status = tx_semaphore_get(&semaphore_0, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_INSTANCE) + { + + /* Semaphore error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Put to semaphore that has an instance already. Should now be 2! */ + status = tx_semaphore_put(&semaphore_1); + + /* Check status. */ + if ((status != TX_SUCCESS) || (semaphore_1.tx_semaphore_count != 2)) + { + + /* Semaphore error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + + /* Attempt to get from semaphore with an instance. Should be successful! */ + status = tx_semaphore_get(&semaphore_1, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Semaphore error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Attempt to get from semaphore with an instance. Should be successful. */ + status = tx_semaphore_get(&semaphore_1, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Semaphore error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Create a timer for the test. */ + tx_timer_create(&timer_0, "timer 0", timer_entry, 0, 1, 1, TX_AUTO_ACTIVATE); + + /* Setup the ISR. */ + test_isr_dispatch = test_isr; + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Resume the thread 1 so we can take an interrupt on top of it. */ + tx_thread_resume(&thread_1); + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Clear the ISR. */ + test_isr_dispatch = TX_NULL; + + /* Test for error. */ + if ((error) || (timer_executed != 1) || (isr_executed != 1)) + { + + /* Semaphore error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + +#endif + + /* Delete semaphores. */ + status = tx_semaphore_delete(&semaphore_0); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Semaphore error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + status = tx_semaphore_delete(&semaphore_1); + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Semaphore error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + +static void thread_1_entry(ULONG thread_input) +{ + + while(1) + { + + tx_thread_relinquish(); + } +}
\ No newline at end of file diff --git a/test/tx/regression/threadx_semaphore_ceiling_put_test.c b/test/tx/regression/threadx_semaphore_ceiling_put_test.c new file mode 100644 index 00000000..5364d2d9 --- /dev/null +++ b/test/tx/regression/threadx_semaphore_ceiling_put_test.c @@ -0,0 +1,334 @@ +/* This test is designed to test the semaphore ceiling put. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + + +static TX_SEMAPHORE semaphore_0; +static TX_SEMAPHORE semaphore_1; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void put_notify(TX_SEMAPHORE *semaphore_ptr) +{ + + /* Don't need to do anything in here... */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_semaphore_ceiling_put_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Ceiling Put Test.................................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Ceiling Put Test.................................. ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Ceiling Put Test.................................. ERROR #3\n"); + test_control_return(1); + } + + /* Create a semaphore with an initial count of 0. */ + status = tx_semaphore_create(&semaphore_0, "semaphore 0", 0); + status += tx_semaphore_create(&semaphore_1, "semaphore 1", 0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Ceiling Put Test.................................. ERROR #4\n"); + test_control_return(1); + } + + /* Setup the semaphore notify callback. */ + status = tx_semaphore_put_notify(&semaphore_0, put_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Ceiling Put Test.................................. ERROR #5\n"); + test_control_return(1); + } + +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Semaphore Ceiling Put Test.................................. ERROR #6\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Semaphore Ceiling Put Test.................................. "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Perform semaphore puts in order to exercise the ceiling put logic. */ + status = tx_semaphore_ceiling_put(&semaphore_0, 2); + status += tx_semaphore_ceiling_put(&semaphore_0, 2); + status += tx_semaphore_ceiling_put(&semaphore_0, 2); + status += tx_semaphore_get(&semaphore_0, TX_NO_WAIT); + status += tx_semaphore_get(&semaphore_0, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_CEILING_EXCEEDED) + { + + /* Semaphore error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Relinquish to make the other thread suspend on the semaphore. */ + tx_thread_relinquish(); + + /* Make sure the other thread has run. */ + if (thread_1_counter != 1) + { + + /* Semaphore error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Place an instance on the semaphore, this should resume the other thread + but not preempt this thread. */ + status = tx_semaphore_ceiling_put(&semaphore_0, 2); + + /* Check the status and the run counter of the other thread. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1)) + { + + /* Semaphore error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Relinquish to allow the other thread to run. */ + tx_thread_relinquish(); + + /* Make sure the other thread has run. */ + if (thread_1_counter != 3) + { + + /* Semaphore error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* At this point, we need to resume thread 2 and relinquish in order to get that thread suspended on the + semaphore as well. */ + tx_thread_resume(&thread_2); + tx_thread_relinquish(); + + /* Perform 2 semaphore put operations to resume both threads. */ + status = tx_semaphore_ceiling_put(&semaphore_0, 2); + status += tx_semaphore_ceiling_put(&semaphore_0, 2); + + /* Let both threads run again. */ + tx_thread_relinquish(); + + /* Check the status and the run counter of the other thread. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 5) || (thread_2_counter != 3)) + { + + /* Semaphore error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Now turn off the semaphore notification. */ + status = tx_semaphore_put_notify(&semaphore_0, TX_NULL); + +#ifdef TX_DISABLE_NOTIFY_CALLBACKS + + /* Clear the status since we know this feature is disabled and will return an error. */ + status = TX_SUCCESS; +#endif + + /* Put a semaphore on a semaphore that does not have suspension. */ + status += tx_semaphore_ceiling_put(&semaphore_1, 2); + + /* Repeat the semaphore ceiling put without notification process! */ + + /* Place an instance on the semaphore, this should resume the other thread + but not preempt this thread. */ + status += tx_semaphore_ceiling_put(&semaphore_0, 2); + + /* Check the status and the run counter of the other thread. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 5)) + { + + /* Semaphore error. */ + printf("ERROR #9a\n"); + test_control_return(1); + } + + /* Relinquish to allow the other thread to run. */ + tx_thread_relinquish(); + + /* Make sure the other thread has run. */ + if (thread_1_counter != 7) + { + + /* Semaphore error. */ + printf("ERROR #10a\n"); + test_control_return(1); + } + + /* At this point, we need to resume thread 2 and relinquish in order to get that thread suspended on the + semaphore as well. */ + tx_thread_resume(&thread_2); + tx_thread_relinquish(); + + /* Perform 2 semaphore put operations to resume both threads. */ + status = tx_semaphore_ceiling_put(&semaphore_0, 2); + status += tx_semaphore_ceiling_put(&semaphore_0, 2); + + /* Let both threads run again. */ + tx_thread_relinquish(); + + /* Check the status and the run counter of the other thread. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 9) || (thread_2_counter != 5)) + { + + /* Semaphore error. */ + printf("ERROR #11a\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + while(1) + { + + /* Increment thread run counter. */ + thread_1_counter++; + + /* Suspend on the semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; + + while(1) + { + + /* Increment thread run counter. */ + thread_2_counter++; + + /* Suspend on the semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_2_counter++; + } +} diff --git a/test/tx/regression/threadx_semaphore_delete_test.c b/test/tx/regression/threadx_semaphore_delete_test.c new file mode 100644 index 00000000..f18d31dc --- /dev/null +++ b/test/tx/regression/threadx_semaphore_delete_test.c @@ -0,0 +1,213 @@ +/* This test is designed to test the semaphore suspension and semaphore delete with + suspended threads. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + + +static TX_SEMAPHORE semaphore_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void put_notify(TX_SEMAPHORE *semaphore_ptr) +{ + + /* Don't need to do anything in here... */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_semaphore_delete_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Delete Test....................................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Delete Test....................................... ERROR #2!\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Delete Test....................................... ERROR #3\n"); + test_control_return(1); + } + + /* Create a semaphore with an initial count of 0. */ + status = tx_semaphore_create(&semaphore_0, "semaphore 0", 0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Delete Test....................................... ERROR #4\n"); + test_control_return(1); + } + + /* Setup the semaphore notify callback. */ + status = tx_semaphore_put_notify(&semaphore_0, put_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Delete Test....................................... ERROR #5\n"); + test_control_return(1); + } +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Semaphore Delete Test....................................... ERROR #6\n"); + test_control_return(1); + } + +#endif +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Semaphore Delete Test....................................... "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Relinquish to let other threads run. */ + tx_thread_relinquish(); + + /* Other threads should now be suspended on the semaphore. */ + + /* Delete the semaphore to test it out! */ + status = tx_semaphore_delete(&semaphore_0); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Semaphore error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Relinquish to allow other threads to run again before we return. */ + tx_thread_relinquish(); + + /* Now check the run counter of each thread. */ + if ((thread_1_counter != 1) || (thread_2_counter != 1)) + { + + /* Semaphore error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + /* Suspend on the semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + /* Did we get the right status? */ + if (status == TX_DELETED) + thread_1_counter++; +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; + + + /* Suspend on the semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + /* Did we get the right status? */ + if (status == TX_DELETED) + thread_2_counter++; +} diff --git a/test/tx/regression/threadx_semaphore_information_test.c b/test/tx/regression/threadx_semaphore_information_test.c new file mode 100644 index 00000000..a8f6d242 --- /dev/null +++ b/test/tx/regression/threadx_semaphore_information_test.c @@ -0,0 +1,418 @@ +/* This test is designed to test the semaphore information services. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_semaphore.h" + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static TX_SEMAPHORE semaphore_0; +static TX_SEMAPHORE semaphore_1; +static TX_SEMAPHORE semaphore_2; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +UINT _tx_semaphore_performance_info_get(TX_SEMAPHORE *semaphore_ptr, ULONG *puts, ULONG *gets, + ULONG *suspensions, ULONG *timeouts); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_semaphore_information_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Information Test.................................. ERROR #1\n"); + test_control_return(1); + } + + /* Create a semaphore with an initial count of 1. */ + status = tx_semaphore_create(&semaphore_0, "semaphore 0", 1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Information Test.................................. ERROR #2\n"); + test_control_return(1); + } + + /* Create a semaphore with an initial count of 0. */ + status = tx_semaphore_create(&semaphore_1, "semaphore 1", 1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Information Test.................................. ERROR #3\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +CHAR *name; +ULONG current_value; +TX_THREAD *first_suspended; +ULONG suspended_count; +TX_SEMAPHORE *next_semaphore; +ULONG puts; +ULONG gets; +ULONG suspensions; +ULONG timeouts; + + + /* Inform user. */ + printf("Running Semaphore Information Test.................................. "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to get semaphore information from a non-semaphore. */ + status = tx_semaphore_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Attempt to get semaphore information from a non-created semaphore. */ + semaphore_2.tx_semaphore_id = 0; + status = tx_semaphore_info_get(&semaphore_2, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #5\n"); + test_control_return(1); + } +#endif + + /* Attempt to get from semaphore with an instance. Should be successful! */ + status = tx_semaphore_get(&semaphore_0, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Semaphore error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Attempt to get from semaphore without an instance. Should be unsuccessful. */ + status = tx_semaphore_get(&semaphore_0, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_NO_INSTANCE) + { + + /* Semaphore error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Put to semaphore that has an instance already. Should now be 2! */ + status = tx_semaphore_put(&semaphore_1); + + /* Check status. */ + if ((status != TX_SUCCESS) || (semaphore_1.tx_semaphore_count != 2)) + { + + /* Semaphore error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + + /* Attempt to get from semaphore with an instance. Should be successful! */ + status = tx_semaphore_get(&semaphore_1, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Semaphore error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to get from semaphore with an instance. Should be successful. */ + status = tx_semaphore_get(&semaphore_1, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Semaphore error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Get semaphore information. */ + status = tx_semaphore_info_get(&semaphore_0, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_semaphore_info_get(&semaphore_0, &name, ¤t_value, &first_suspended, &suspended_count, &next_semaphore); + + /* Check status. */ + if ((status != TX_SUCCESS) || (current_value != semaphore_0.tx_semaphore_count) || + (first_suspended != semaphore_0.tx_semaphore_suspension_list) || (suspended_count != semaphore_0.tx_semaphore_suspended_count) || + (next_semaphore != semaphore_0.tx_semaphore_created_next)) + { + + /* Semaphore error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO + + /* Get semaphore performance information with NULL pointer. */ + status = _tx_semaphore_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for error. */ + if (status != TX_PTR_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Get semaphore performance information. */ + status = tx_semaphore_performance_info_get(&semaphore_0, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_semaphore_performance_info_get(&semaphore_0, &puts, &gets, &suspensions, &timeouts); + + /* Check status. */ + if ((status != TX_SUCCESS) || (puts != semaphore_0.tx_semaphore_performance_put_count) || (gets != semaphore_0.tx_semaphore_performance_get_count) || + (suspensions != semaphore_0.tx_semaphore_performance_suspension_count) || (timeouts != semaphore_0.tx_semaphore_performance_timeout_count)) + { + + /* Semaphore error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Get semaphore system performance information. */ + status = tx_semaphore_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_semaphore_performance_system_info_get(&puts, &gets, &suspensions, &timeouts); + + /* Check status. */ + if ((status != TX_SUCCESS) || (puts != _tx_semaphore_performance_put_count) || (gets != _tx_semaphore_performance_get_count) || + (suspensions != _tx_semaphore_performance_suspension_count) || (timeouts != _tx_semaphore_performance_timeout_count)) + { + + /* Semaphore error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + +#else + + /* Get semaphore performance information. */ + status = tx_semaphore_performance_info_get(&semaphore_0, &puts, &gets, &suspensions, &timeouts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Semaphore error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Get semaphore performance information. */ + status = tx_semaphore_performance_info_get(TX_NULL, &puts, &gets, &suspensions, &timeouts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Semaphore error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Get semaphore performance information. */ + status = tx_semaphore_performance_info_get(TX_NULL, TX_NULL, &gets, &suspensions, &timeouts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Semaphore error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Get semaphore performance information. */ + status = tx_semaphore_performance_info_get(TX_NULL, TX_NULL, TX_NULL, &suspensions, &timeouts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Semaphore error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Get semaphore performance information. */ + status = tx_semaphore_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, &timeouts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Semaphore error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Get semaphore performance information. */ + status = tx_semaphore_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Semaphore error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Get semaphore system performance information. */ + status = tx_semaphore_performance_system_info_get(&puts, &gets, &suspensions, &timeouts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Semaphore error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + /* Get semaphore system performance information. */ + status = tx_semaphore_performance_system_info_get(TX_NULL, &gets, &suspensions, &timeouts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Semaphore error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + /* Get semaphore system performance information. */ + status = tx_semaphore_performance_system_info_get(TX_NULL, TX_NULL, &suspensions, &timeouts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Semaphore error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Get semaphore system performance information. */ + status = tx_semaphore_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, &timeouts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Semaphore error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Get semaphore system performance information. */ + status = tx_semaphore_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Semaphore error. */ + printf("ERROR #25\n"); + test_control_return(1); + } +#endif + + /* Delete semaphores. */ + status = tx_semaphore_delete(&semaphore_0); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Semaphore error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + status = tx_semaphore_delete(&semaphore_1); + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Semaphore error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} diff --git a/test/tx/regression/threadx_semaphore_non_preemption_test.c b/test/tx/regression/threadx_semaphore_non_preemption_test.c new file mode 100644 index 00000000..40219546 --- /dev/null +++ b/test/tx/regression/threadx_semaphore_non_preemption_test.c @@ -0,0 +1,271 @@ +/* This test is designed to test the semaphore suspension and another thread resuming the + same priority thread by doing a semaphore put. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + + +static TX_SEMAPHORE semaphore_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void put_notify(TX_SEMAPHORE *semaphore_ptr) +{ + + /* Don't need to do anything in here... */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_semaphore_non_preemption_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Non Preemption Test............................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Non Preemption Test............................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Non Preemption Test............................... ERROR #3\n"); + test_control_return(1); + } + + /* Create a semaphore with an initial count of 0. */ + status = tx_semaphore_create(&semaphore_0, "semaphore 0", 0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Non Preemption Test............................... ERROR #4\n"); + test_control_return(1); + } + + /* Setup the semaphore notify callback. */ + status = tx_semaphore_put_notify(&semaphore_0, put_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Non Preemption Test............................... ERROR #5\n"); + test_control_return(1); + } + +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Semaphore Non Preemption Test............................... ERROR #6\n"); + test_control_return(1); + } + +#endif +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Semaphore Non Preemption Test............................... "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Perform a semaphore put and get, just to exercise the notify path of a non-resumption + semaphore put. */ + status = tx_semaphore_put(&semaphore_0); + status += tx_semaphore_get(&semaphore_0, TX_NO_WAIT); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Semaphore error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Relinquish to make the other thread suspend on the semaphore. */ + tx_thread_relinquish(); + + /* Make sure the other thread has run. */ + if (thread_1_counter != 1) + { + + /* Semaphore error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Place an instance on the semaphore, this should resume the other thread + but not preempt this thread. */ + status = tx_semaphore_put(&semaphore_0); + + /* Check the status and the run counter of the other thread. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1)) + { + + /* Semaphore error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Relinquish to allow the other thread to run. */ + tx_thread_relinquish(); + + /* Make sure the other thread has run. */ + if (thread_1_counter != 3) + { + + /* Semaphore error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* At this point, we need to resume thread 2 and relinquish in order to get that thread suspended on the + semaphore as well. */ + tx_thread_resume(&thread_2); + tx_thread_relinquish(); + + /* Perform 2 semaphore put operations to resume both threads. */ + status = tx_semaphore_put(&semaphore_0); + status += tx_semaphore_put(&semaphore_0); + + /* Let both threads run again. */ + tx_thread_relinquish(); + + /* Check the status and the run counter of the other thread. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 5) || (thread_2_counter != 3)) + { + + /* Semaphore error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + while(1) + { + + /* Increment thread run counter. */ + thread_1_counter++; + + /* Suspend on the semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; + + while(1) + { + + /* Increment thread run counter. */ + thread_2_counter++; + + /* Suspend on the semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_2_counter++; + } +} + diff --git a/test/tx/regression/threadx_semaphore_preemption_test.c b/test/tx/regression/threadx_semaphore_preemption_test.c new file mode 100644 index 00000000..347042bc --- /dev/null +++ b/test/tx/regression/threadx_semaphore_preemption_test.c @@ -0,0 +1,179 @@ +/* This test is designed to test the semaphore suspension and another thread resuming the + higher priority thread by doing a semaphore put. Higher-priority thread should preempt. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + + +static TX_SEMAPHORE semaphore_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void put_notify(TX_SEMAPHORE *semaphore_ptr) +{ + + /* Don't need to do anything in here... */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_semaphore_preemption_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Preemption Test................................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Preemption Test................................... ERROR #2\n"); + test_control_return(1); + } + + /* Create a semaphore with an initial count of 0. */ + status = tx_semaphore_create(&semaphore_0, "semaphore 0", 0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Preemption Test................................... ERROR #3\n"); + test_control_return(1); + } + + /* Setup the semaphore notify callback. */ + status = tx_semaphore_put_notify(&semaphore_0, put_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Preemption Test................................... ERROR #4\n"); + test_control_return(1); + } +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Semaphore Preemption Test................................... ERROR #5\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Semaphore Preemption Test................................... "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* The other thread should now be suspended on the semaphore. */ + if (thread_1_counter != 1) + { + + /* Semaphore error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Place an instance on the semaphore, this should cause the other thread + to preempt. */ + status = tx_semaphore_put(&semaphore_0); + + /* Check status and run counter of other thread. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 2)) + { + + /* Semaphore error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + /* Increment thread run counter. */ + thread_1_counter++; + + /* Suspend on the semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + /* Did we get the right status? */ + if (status == TX_SUCCESS) + thread_1_counter++; +} + diff --git a/test/tx/regression/threadx_semaphore_prioritize.c b/test/tx/regression/threadx_semaphore_prioritize.c new file mode 100644 index 00000000..79622667 --- /dev/null +++ b/test/tx/regression/threadx_semaphore_prioritize.c @@ -0,0 +1,525 @@ +/* This test is designed to test semaphore prioritize. */ + +#include <stdio.h> +#include "tx_api.h" + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +/* Define the external reference for the preempt disable flag. */ + +extern volatile UINT _tx_thread_preempt_disable; + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + +static unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; + +static unsigned long thread_5_counter = 0; +static TX_THREAD thread_5; + +static unsigned long thread_6_counter = 0; +static TX_THREAD thread_6; + +static TX_SEMAPHORE semaphore_0; +static TX_SEMAPHORE semaphore_1; + +static int test_status; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +static void thread_5_entry(ULONG thread_input); +static void thread_6_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + + /* Determine if the test case we are looking for is present. */ + if ((_tx_thread_preempt_disable) && (test_status == 1)) + { + + /* Determine if thread 3 is at the front of the suspension list. */ + if (semaphore_0.tx_semaphore_suspension_list == &thread_3) + { + + /* Abort the wait of thread 3. */ + tx_thread_wait_abort(&thread_3); + } + else + { + + /* Abort the wait of thread 5. */ + tx_thread_wait_abort(&thread_5); + + /* End the ISR processing. */ + test_status = 2; + test_isr_dispatch = TX_NULL; + } + } +} + + +static void put_notify(TX_SEMAPHORE *semaphore_ptr) +{ + + /* Don't need to do anything in here... */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_semaphore_prioritize_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Prioritize Test................................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Prioritize Test................................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Prioritize Test................................... ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 3, 3, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Prioritize Test................................... ERROR #4\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 4, 4, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Prioritize Test................................... ERROR #5\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, + pointer, TEST_STACK_SIZE_PRINTF, + 5, 5, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Prioritize Test................................... ERROR #6\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_6, "thread 6", thread_6_entry, 6, + pointer, TEST_STACK_SIZE_PRINTF, + 6, 6, 100, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Prioritize Test................................... ERROR #7\n"); + test_control_return(1); + } + + /* Create the semaphore with no instances. */ + status = tx_semaphore_create(&semaphore_0, "semaphore 0", 0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Prioritize Test................................... ERROR #8\n"); + test_control_return(1); + } + + /* Setup the semaphore notify callback. */ + status = tx_semaphore_put_notify(&semaphore_0, put_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Prioritize Test................................... ERROR #9\n"); + test_control_return(1); + } + +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Semaphore Prioritize Test................................... ERROR #10\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Semaphore Prioritize Test................................... "); + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to prioritize a non-semaphore. */ + status = tx_semaphore_prioritize(TX_NULL); + + /* Check status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Attempt to prioritize a non-created semaphore. */ + semaphore_1.tx_semaphore_id = 0; + status = tx_semaphore_prioritize(&semaphore_1); + + /* Check status. */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #12\n"); + test_control_return(1); + } +#endif + + /* Prioritize the semaphore suspension list - empty list case! */ + status = tx_semaphore_prioritize(&semaphore_0); + + /* Check status and make sure thread 1 is terminated. */ + if ((status != TX_SUCCESS) || (semaphore_0.tx_semaphore_suspension_list != TX_NULL)) + { + + /* Semaphore error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + + /* Increment the thread counter. */ + thread_0_counter++; + + /* Make sure thread 1 and 2 are suspended on the semaphore. */ + if ((thread_1.tx_thread_state != TX_SEMAPHORE_SUSP) || (thread_2.tx_thread_state != TX_SEMAPHORE_SUSP) || + (semaphore_0.tx_semaphore_suspension_list != &thread_1)) + { + + /* Semaphore error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Prioritize the semaphore suspension list. */ + status = tx_semaphore_prioritize(&semaphore_0); + + /* Check status and make sure thread 2 is not at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (semaphore_0.tx_semaphore_suspension_list != &thread_2)) + { + + /* Semaphore error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Prioritize the semaphore suspension list again - in this case, the list is already prioritized. */ + status = tx_semaphore_prioritize(&semaphore_0); + + /* Check status and make sure thread 2 is not at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (semaphore_0.tx_semaphore_suspension_list != &thread_2)) + { + + /* Semaphore error. */ + printf("ERROR #15a\n"); + test_control_return(1); + } + + /* At this point we are going to get more than 2 threads suspended. */ + tx_thread_resume(&thread_1); + tx_thread_resume(&thread_2); + tx_thread_resume(&thread_3); + tx_thread_resume(&thread_4); + tx_thread_resume(&thread_5); + tx_thread_resume(&thread_6); + + /* Prioritize the semaphore suspension list. */ + status = tx_semaphore_prioritize(&semaphore_0); + + /* Check status and make sure thread 3 is now at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (semaphore_0.tx_semaphore_suspension_list != &thread_3)) + { + + /* Semaphore error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Now loop to test the interrupt of the prioritize loop logic. */ + test_status = 1; + test_isr_dispatch = test_isr; + do + { + + /* Prioritize the semaphore suspension list. */ + status = tx_semaphore_prioritize(&semaphore_0); + + /* Check status and make sure thread 1 is terminated. */ + if (status != TX_SUCCESS) + { + + /* Semaphore error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + } while (test_status == 1); + + /* Check status and make sure thread 3 is now at the front of the suspension list. */ + if ((status != TX_SUCCESS) || (semaphore_0.tx_semaphore_suspension_list != &thread_4)) + { + + /* Semaphore error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ +UINT status; + + /* Loop forever! */ + while(1) + { + + + /* Get semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + + +static void thread_2_entry(ULONG thread_input) +{ +UINT status; + + + /* Loop forever! */ + while(1) + { + + + /* Get semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_2_counter++; + } +} + + +static void thread_3_entry(ULONG thread_input) +{ +UINT status; + + + /* Loop forever! */ + while(1) + { + + + /* Get semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_3_counter++; + } +} + + +static void thread_4_entry(ULONG thread_input) +{ +UINT status; + + + /* Loop forever! */ + while(1) + { + + + /* Get semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_4_counter++; + } +} + + +static void thread_5_entry(ULONG thread_input) +{ +UINT status; + + + /* Loop forever! */ + while(1) + { + + + /* Get semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_5_counter++; + } +} + + +static void thread_6_entry(ULONG thread_input) +{ +UINT status; + + + /* Loop forever! */ + while(1) + { + + + /* Get semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + break; + + /* Increment the thread counter. */ + thread_6_counter++; + } +} + diff --git a/test/tx/regression/threadx_semaphore_thread_terminate_test.c b/test/tx/regression/threadx_semaphore_thread_terminate_test.c new file mode 100644 index 00000000..b8beeff2 --- /dev/null +++ b/test/tx/regression/threadx_semaphore_thread_terminate_test.c @@ -0,0 +1,224 @@ +/* This test is designed to test thread terminate calls when threads are suspended on + a semaphore. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + + +static TX_SEMAPHORE semaphore_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void put_notify(TX_SEMAPHORE *semaphore_ptr) +{ + + /* Don't need to do anything in here... */ +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_semaphore_thread_terminate_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Thread Terminate Test............................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Thread Terminate Test............................. ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Thread Terminate Test............................. ERROR #3\n"); + test_control_return(1); + } + + /* Create a semaphore with an initial count of 0. */ + status = tx_semaphore_create(&semaphore_0, "semaphore 0", 0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Thread Terminate Test............................. ERROR #4\n"); + test_control_return(1); + } + + /* Setup the semaphore notify callback. */ + status = tx_semaphore_put_notify(&semaphore_0, put_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Thread Terminate Test............................. ERROR #5\n"); + test_control_return(1); + } +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Semaphore Thread Terminate Test............................. ERROR #6\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Semaphore Thread Terminate Test............................. "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Relinquish to let other threads run. */ + tx_thread_relinquish(); + + /* Other threads should now be suspended on the semaphore. */ + if ((thread_1_counter != 1) || (thread_2_counter != 1)) + { + + /* Semaphore error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Terminate the other threads to make sure the semaphore gets + cleaned up. */ + status = tx_thread_terminate(&thread_1); + + /* Check status and run counters of other threads. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 1)) + { + + /* Semaphore error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Terminate the other thread. */ + status = tx_thread_terminate(&thread_2); + + /* Relinquish just to make sure. */ + tx_thread_relinquish(); + + /* Check status and run counters of other threads. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 1)) + { + + /* Semaphore error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + + /* Increment thread run counter. */ + thread_1_counter++; + + /* Suspend on the semaphore. */ + tx_semaphore_get(&semaphore_0, 33); + + /* Should never get here! */ + thread_1_counter++; +} + + +static void thread_2_entry(ULONG thread_input) +{ + + /* Increment thread run counter. */ + thread_2_counter++; + + /* Suspend on the semaphore. */ + tx_semaphore_get(&semaphore_0, 44); + + /* Should never get here! */ + thread_2_counter++; +} diff --git a/test/tx/regression/threadx_semaphore_timeout_test.c b/test/tx/regression/threadx_semaphore_timeout_test.c new file mode 100644 index 00000000..ec16a7c0 --- /dev/null +++ b/test/tx/regression/threadx_semaphore_timeout_test.c @@ -0,0 +1,167 @@ +/* This test is designed to test the semaphore suspension and timeout functionality. */ + +#include <stdio.h> +#include "tx_api.h" + +//static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static TX_SEMAPHORE semaphore_0; +static TX_SEMAPHORE semaphore_1; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void put_notify(TX_SEMAPHORE *semaphore_ptr) +{ + + /* Don't need to do anything in here... */ +} + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_semaphore_timeout_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Suspension Timeout Test........................... ERROR #1\n"); + test_control_return(1); + } + + /* Create a semaphore with an initial count of 0. */ + status = tx_semaphore_create(&semaphore_0, "semaphore 0", 0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Suspension Timeout Test........................... ERROR #2\n"); + test_control_return(1); + } + + /* Setup the semaphore notify callback. */ + status = tx_semaphore_put_notify(&semaphore_0, put_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Semaphore Suspension Timeout Test........................... ERROR #3\n"); + test_control_return(1); + } + +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Semaphore Suspension Timeout Test........................... ERROR #4\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG now; + + /* Inform user. */ + printf("Running Semaphore Suspension Timeout Test........................... "); + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to setup semaphore notify callback on non-semaphore. */ + status = tx_semaphore_put_notify(TX_NULL, put_notify); + + /* Check status */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Attempt to setup semaphore notify callback on non-created semaphore. */ + semaphore_1.tx_semaphore_id = 0; + status = tx_semaphore_put_notify(&semaphore_1, put_notify); + + /* Check status */ + if (status != TX_SEMAPHORE_ERROR) + { + + /* Semaphore error. */ + printf("ERROR #6\n"); + test_control_return(1); + } +#endif + + /* Sleep for 2 ticks for fresh timer. */ + tx_thread_sleep(2); + + /* Set clock to 0. */ + tx_time_set(0); + + /* Suspend on the semaphore. */ + status = tx_semaphore_get(&semaphore_0, 33); + + /* Did we get the right status at the right time? */ + now = tx_time_get(); + if ((status != TX_NO_INSTANCE) || (now != 33)) + { + + /* Semaphore error. */ + printf("ERROR #7, now = %lu\n", now); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + diff --git a/test/tx/regression/threadx_thread_basic_execution_test.c b/test/tx/regression/threadx_thread_basic_execution_test.c new file mode 100644 index 00000000..7a5ae864 --- /dev/null +++ b/test/tx/regression/threadx_thread_basic_execution_test.c @@ -0,0 +1,979 @@ +/* This test is designed to see if one thread can be created and executed. + It thread_0_entry is hit, then the thread was successfully scheduled. + On success, thread_0_counter gets incremented. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_block_pool.h" +#include "tx_byte_pool.h" +#include "tx_event_flags.h" +#include "tx_mutex.h" +#include "tx_queue.h" +#include "tx_semaphore.h" +#include "tx_thread.h" + + +typedef struct THREAD_MEMORY_TEST_STRUCT +{ + ULONG first; + ULONG second; + TX_THREAD thread_block; + ULONG first_middle; + ULONG second_middle; + ULONG stack[2048/sizeof(ULONG)]; + ULONG next_to_last; + ULONG last; + +} THREAD_MEMORY_TEST; + +static THREAD_MEMORY_TEST thread_memory; + + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static TX_THREAD thread_1; +static TX_THREAD thread_2; +static TX_THREAD thread_3; +static TX_THREAD test_thread; + +static TX_TIMER timer_0; + + +static UCHAR not_used_stack[TEST_STACK_SIZE_PRINTF]; + +static unsigned long error = 0; +static unsigned long timer_executed = 0; +static unsigned long isr_executed = 0; + + +/* Define task prototypes. */ + +static void thread_0_entry(ULONG task_input); + +UINT _txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, + VOID (*entry_function)(ULONG), ULONG entry_input, + VOID *stack_start, ULONG stack_size, + UINT priority, UINT preempt_threshold, + ULONG time_slice, UINT auto_start, UINT thread_control_block_size); + +#ifndef TX_INLINE_THREAD_RESUME_SUSPEND +#ifndef TX_NOT_INTERRUPTABLE + +static TX_THREAD thread_4; +static ULONG thread_4_counter = 0; +static ULONG isr1_counter = 0; +static ULONG test_case_found = TX_FALSE; +static void thread_4_entry(ULONG task_input); + +#endif +#endif + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define the timer for this test. */ + +static void timer_entry(ULONG i) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +UINT status; +CHAR *pointer; + + /* Attempt to create a thread from a timer. */ + pointer = (CHAR *) 0x3000; + status = tx_thread_create(&thread_1, "thread 1", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_DONT_START); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt a thread reset from a timer. */ + status = tx_thread_reset(&thread_0); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + timer_executed = 1; +#endif +} + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +CHAR *pointer; +UINT status; +UINT old_value; +ULONG old_time_slice; + + + /* Call tx_thread_relinquish from ISR to make sure the error checking discards the call. */ + tx_thread_relinquish(); + + /* Attempt to create a thread from a timer. */ + pointer = (CHAR *) not_used_stack; + status = tx_thread_create(&thread_1, "thread 1", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_DONT_START); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to delete a thread from an ISR. */ + status = tx_thread_delete(&thread_0); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to change preemption from an ISR. */ + status = tx_thread_preemption_change(&thread_0, 1, &old_value); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to change priority from an ISR. */ + status = tx_thread_priority_change(&thread_0, 1, &old_value); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt a thread reset from an ISR. */ + status = tx_thread_reset(&thread_0); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt a thread terminate from an ISR. */ + status = tx_thread_terminate(&thread_0); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt a thread time slice change from an ISR. */ + status = tx_thread_time_slice_change(&thread_0, 1, &old_time_slice); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + isr_executed = 1; +#endif + + /* Test thread sleep call from ISR. */ + status = tx_thread_sleep(11); + + /* Check for status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } +} + +#ifndef TX_INLINE_THREAD_RESUME_SUSPEND +#ifndef TX_NOT_INTERRUPTABLE + +static void test_isr1(void) +{ + +UINT status; +TX_THREAD *current_thread; + + + /* Suspend thread 4 while preempt disable is set. */ + + /* Increment the ISR counter. */ + isr1_counter++; + + /* Pickup the current thread. */ + current_thread = tx_thread_identify(); + + /* Determine if the condition is present. */ + if ((current_thread == &thread_4) && (_tx_thread_preempt_disable) && (thread_4.tx_thread_state == TX_READY)) + { + + /* Suspend the currently running thread 4 with the preemption-threshold flag set to ensure tx_thread_suspend from an ISR works + in this case. */ + status = tx_thread_suspend(&thread_4); + + /* Check for error. */ + if (status != TX_SUCCESS) + { + + /* Set error flag. */ + error++; + } + + /* Resume thread 4. */ + tx_thread_resume(&thread_4); + + /* Indicate the test case has been found. */ + test_case_found = TX_TRUE; + } +} + +#endif +#endif + + +#if 0 +static void test_thread_entry(ULONG thread_input) +{ + /* Do nothing here! */ +} +#endif + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_basic_execution_application_define(void *first_unused_memory) +#endif +{ + +INT status; +CHAR *pointer; +TX_THREAD fake_thread; + + + /* Setup a pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Adjust it forward just to make sure there is some space for the test below. */ + pointer = pointer + 200; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + +#ifndef TX_INLINE_THREAD_RESUME_SUSPEND +#ifndef TX_NOT_INTERRUPTABLE + + status += tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + +#endif +#endif + + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Basic Execution Test................................. ERROR #1\n"); + test_control_return(1); + } + + +#ifndef TX_NOT_INTERRUPTABLE + + /* Now setup a fake thread to generate the other NULL pointer test in the cleanup routines. */ + fake_thread.tx_thread_suspend_control_block = TX_NULL; + _tx_semaphore_cleanup(&fake_thread, 0); + _tx_queue_cleanup(&fake_thread, 0); + _tx_mutex_cleanup(&fake_thread, 0); + _tx_event_flags_cleanup(&fake_thread, 0); + _tx_byte_pool_cleanup(&fake_thread, 0); + _tx_block_pool_cleanup(&fake_thread, 0); +#endif +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING +UINT status; +CHAR *pointer; +UINT old_value; +ULONG old_time_slice; +#endif + +VOID (*temp_mutex_release)(TX_THREAD *thread_ptr); + + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Inform user of success getting to this test. */ + printf("Running Thread Basic Execution Test................................. "); + + /* Setup test thread to make sure _tx_thread_wait_abort can handle a NULL cleanup. */ + test_thread.tx_thread_state = TX_IO_DRIVER; + test_thread.tx_thread_suspend_cleanup = TX_NULL; + test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL; + test_thread.tx_thread_suspending = TX_TRUE; + test_thread.tx_thread_delayed_suspend = TX_TRUE; + if(_tx_thread_wait_abort(&test_thread) != TX_WAIT_ABORT_ERROR) + { + printf("ERROR #XX\n"); + test_control_return(1); + } + + /* Setup test thread to make sure _tx_thread_timeout can handle a NULL cleanup. */ + test_thread.tx_thread_state = TX_IO_DRIVER; + test_thread.tx_thread_suspend_cleanup = TX_NULL; + test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL; + test_thread.tx_thread_suspending = TX_TRUE; + test_thread.tx_thread_delayed_suspend = TX_TRUE; + _tx_thread_timeout((ULONG) &test_thread); + + /* Setup test thread to make sure _tx_thread_terminate can handle a NULL mutex release function pointer. */ + temp_mutex_release = _tx_thread_mutex_release; + _tx_thread_mutex_release = TX_NULL; + test_thread.tx_thread_state = TX_TERMINATED; + test_thread.tx_thread_suspend_cleanup = TX_NULL; + test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL; + test_thread.tx_thread_suspending = TX_TRUE; + test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL; + test_thread.tx_thread_delayed_suspend = TX_TRUE; + status = _tx_thread_terminate(&test_thread); + _tx_thread_mutex_release = temp_mutex_release; /* Recover Mutex release pointer. */ + + /* Perform thread memory test. */ + thread_memory.first = 0x11223344; + thread_memory.second = 0x55667788; + thread_memory.first_middle = 0x21314151; + thread_memory.second_middle= 0x61718191; + thread_memory.next_to_last = 0x99aabbcc; + thread_memory.last = 0xddeeff00; + + /* Create the thread. */ + status += tx_thread_create(&thread_memory.thread_block, "thread memory", thread_0_entry, 1, + &thread_memory.stack[0], (2048*sizeof(ULONG))/sizeof(ULONG), + 16, 16, TX_NO_TIME_SLICE, TX_DONT_START); + tx_thread_delete(&thread_memory.thread_block); + + /* Check for status. */ + if ((status != TX_SUCCESS) || + (thread_memory.first != 0x11223344) || + (thread_memory.second != 0x55667788) || + (thread_memory.first_middle != 0x21314151) || + (thread_memory.second_middle != 0x61718191) || + (thread_memory.next_to_last != 0x99aabbcc) || + (thread_memory.last != 0xddeeff00)) + { + + /* Memory overwrite error. */ + printf("ERROR #2\n"); + test_control_return(1); + } + + + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to create a thread with a null pointer. */ + pointer = (CHAR *) not_used_stack; + status = tx_thread_create(TX_NULL, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #3\n"); + test_control_return(1); + } + + /* Attempt to create a thread with a bad control block size. */ + pointer = (CHAR *) not_used_stack; + status = _txe_thread_create(&thread_3, "thread 3", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START, (sizeof(TX_THREAD)+1)); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Attempt to create a thread with a NULL entry function. */ + pointer = (CHAR *) not_used_stack; + status = tx_thread_create(&thread_3, "thread 3", TX_NULL, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_PTR_ERROR) + { + + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Attempt to create a thread that has already been created. */ + pointer = (CHAR *) not_used_stack; + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Attempt to create a thread with an overlapping stack. */ + status = tx_thread_create(&thread_1, "thread 1", thread_0_entry, 1, + thread_0.tx_thread_stack_ptr, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_PTR_ERROR) + { + + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Attempt to create a thread with another variation of an overlapping stack. */ + pointer = thread_0.tx_thread_stack_start; + pointer = pointer - 20; + status = tx_thread_create(&thread_1, "thread 1", TX_NULL, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_PTR_ERROR) + { + + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Attempt to create a thread an extra small stack. */ + pointer = (CHAR *) not_used_stack; + status = tx_thread_create(&thread_1, "thread 1", thread_0_entry, 1, + pointer, 1, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_SIZE_ERROR) + { + + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to create a thread with an invalid thread priority. */ + pointer = (CHAR *) not_used_stack; + status = tx_thread_create(&thread_1, "thread 1", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 5000, 5000, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_PRIORITY_ERROR) + { + + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Attempt to create a thread with an invalid preemption-threshold. */ + pointer = (CHAR *) not_used_stack; + status = tx_thread_create(&thread_1, "thread 1", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 17, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_THRESH_ERROR) + { + + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Attempt to create a thread with an invalid auto start. */ + pointer = (CHAR *) not_used_stack; + status = tx_thread_create(&thread_1, "thread 1", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, 3456); + + /* Check for status. */ + if (status != TX_START_ERROR) + { + + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Attempt to delete a non-thread. */ + status = tx_thread_delete(TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Attempt to delete a non-created thread. */ + thread_2.tx_thread_id = 0; + status = tx_thread_delete(&thread_2); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Attempt to register a entry/exit callback on a non-thread. */ + status = tx_thread_entry_exit_notify(TX_NULL, TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Attempt to register a entry/exit callback on a non-created thread. */ + thread_2.tx_thread_id = 0; + status = tx_thread_entry_exit_notify(&thread_2, TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Attempt to get info on a non-thread. */ + status = tx_thread_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Attempt to get info on a non-created thread. */ + thread_2.tx_thread_id = 0; + status = tx_thread_info_get(&thread_2, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Attempt to change preemption of a non-thread. */ + status = tx_thread_preemption_change(TX_NULL, 1, TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Attempt to change preemption of a non-created thread. */ + thread_2.tx_thread_id = 0; + status = tx_thread_preemption_change(&thread_2, 1, TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Attempt to change preemption with a NULL return value. */ + status = tx_thread_preemption_change(&thread_0, 1, TX_NULL); + + /* Check for status. */ + if (status != TX_PTR_ERROR) + { + + printf("ERROR #21\n"); + test_control_return(1); + } + + /* Attempt to change preemption with a bad threshold value. */ + status = tx_thread_preemption_change(&thread_0, 17, &old_value); + + /* Check for status. */ + if (status != TX_THRESH_ERROR) + { + + printf("ERROR #22\n"); + test_control_return(1); + } + + + /* Attempt to change priority of a non-thread. */ + status = tx_thread_priority_change(TX_NULL, 1, TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Attempt to change priority of a non-created thread. */ + thread_2.tx_thread_id = 0; + status = tx_thread_priority_change(&thread_2, 1, TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Attempt to change priority with a NULL return value. */ + status = tx_thread_priority_change(&thread_0, 1, TX_NULL); + + /* Check for status. */ + if (status != TX_PTR_ERROR) + { + + printf("ERROR #25\n"); + test_control_return(1); + } + + /* Attempt to change priority with a bad priority value. */ + status = tx_thread_priority_change(&thread_0, 2046, &old_value); + + /* Check for status. */ + if (status != TX_PRIORITY_ERROR) + { + + printf("ERROR #26\n"); + test_control_return(1); + } + + /* Attempt a thread reset for a non-thread. */ + status = tx_thread_reset(TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Attempt a thread reset from same thread. */ + status = tx_thread_reset(&thread_0); + + /* Check for status. */ + if (status != TX_NOT_DONE) + { + + printf("ERROR #28\n"); + test_control_return(1); + } + + /* Attempt a thread reset for a non-created thread. */ + thread_2.tx_thread_id = 0; + status = tx_thread_reset(&thread_2); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #29\n"); + test_control_return(1); + } + + /* Attempt a thread resume with a NULL pointer. */ + status = tx_thread_resume(TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #30\n"); + test_control_return(1); + } + + /* Attempt a thread resume on a non-created thread. */ + thread_2.tx_thread_id = 0; + status = tx_thread_resume(&thread_2); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #31\n"); + test_control_return(1); + } + + /* Attempt a thread suspend with a NULL pointer. */ + status = tx_thread_suspend(TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #32\n"); + test_control_return(1); + } + + /* Attempt a thread suspend on a non-created thread. */ + thread_2.tx_thread_id = 0; + status = tx_thread_suspend(&thread_2); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #33\n"); + test_control_return(1); + } + + /* Attempt a thread termiante with a NULL pointer. */ + status = tx_thread_terminate(TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #34\n"); + test_control_return(1); + } + + /* Attempt a thread terminate on a non-created thread. */ + thread_2.tx_thread_id = 0; + status = tx_thread_terminate(&thread_2); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #35\n"); + test_control_return(1); + } + + /* Attempt a thread time-slice chagne with a NULL pointer. */ + status = tx_thread_time_slice_change(TX_NULL, 1, &old_time_slice); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #36\n"); + test_control_return(1); + } + + /* Attempt a thread time-slice change on a non-created thread. */ + thread_2.tx_thread_id = 0; + status = tx_thread_time_slice_change(&thread_2, 1, &old_time_slice); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #37\n"); + test_control_return(1); + } + + /* Attempt a thread time-slice change with a null return pointer. */ + status = tx_thread_time_slice_change(&thread_0, 1, TX_NULL); + + /* Check for status. */ + if (status != TX_PTR_ERROR) + { + + printf("ERROR #38\n"); + test_control_return(1); + } + + /* Attempt a thread wait abort with a NULL pointer. */ + status = tx_thread_wait_abort(TX_NULL); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #39\n"); + test_control_return(1); + } + + /* Attempt a thread wait abort on a non-created thread. */ + thread_2.tx_thread_id = 0; + status = tx_thread_wait_abort(&thread_2); + + /* Check for status. */ + if (status != TX_THREAD_ERROR) + { + + printf("ERROR #40\n"); + test_control_return(1); + } + + /* Create a timer for the test. */ + tx_timer_create(&timer_0, "timer 0", timer_entry, 0, 1, 1, TX_AUTO_ACTIVATE); + + /* Setup the ISR. */ + test_isr_dispatch = test_isr; + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Clear the ISR. */ + test_isr_dispatch = TX_NULL; + + /* Test for error. */ + if ((error) || (timer_executed != 1) || (isr_executed != 1)) + { + + /* Thread error. */ + printf("ERROR #41\n"); + test_control_return(1); + } + +#endif + +#ifndef TX_INLINE_THREAD_RESUME_SUSPEND +#ifndef TX_NOT_INTERRUPTABLE + + /* At this point setup the ISR. */ + test_isr_dispatch = test_isr1; + + /* Resume thread 4. */ + tx_thread_resume(&thread_4); + + /* Clear the ISR. */ + test_isr_dispatch = TX_NULL; + + /* Now check for an error. */ + if ((error) || (test_case_found == TX_FALSE)) + { + + /* Basic execution error. */ + printf("ERROR #42\n"); + test_control_return(1); + } + +#endif +#endif + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +#ifndef TX_INLINE_THREAD_RESUME_SUSPEND +#ifndef TX_NOT_INTERRUPTABLE + +static void thread_4_entry(ULONG thread_input) +{ + +TX_INTERRUPT_SAVE_AREA + + + /* Loop until we achieve as suspend request while inside of the tx_thread_resume API. */ + while (test_case_found == TX_FALSE) + { + + /* Temporarily disable preemption for the test. */ + TX_DISABLE + _tx_thread_preempt_disable++; + TX_RESTORE + + /* Increment the run counter for this test. */ + thread_4_counter++; + + TX_DISABLE + _tx_thread_preempt_disable--; + TX_RESTORE + } +} + +#endif +#endif + + diff --git a/test/tx/regression/threadx_thread_basic_time_slice_test.c b/test/tx/regression/threadx_thread_basic_time_slice_test.c new file mode 100644 index 00000000..9da8350c --- /dev/null +++ b/test/tx/regression/threadx_thread_basic_time_slice_test.c @@ -0,0 +1,73 @@ +/* This test is designed to see if a thread can be created with a time-slice. + No time-slice occurs, only the processing to check for time-slicing. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_basic_time_slice_application_define(void *first_unused_memory) +#endif +{ + +UINT status; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + first_unused_memory, TEST_STACK_SIZE_PRINTF, + 16, 16, 1, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Basic Time-Slice Test................................ ERROR #1\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + + + /* Inform user. */ + printf("Running Thread Basic Time-Slice Test................................ "); + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Determine if we are done. */ + if (tx_time_get() > 18) + { + + /* Successful Time-slice test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } + } +} diff --git a/test/tx/regression/threadx_thread_completed_test.c b/test/tx/regression/threadx_thread_completed_test.c new file mode 100644 index 00000000..068058d0 --- /dev/null +++ b/test/tx/regression/threadx_thread_completed_test.c @@ -0,0 +1,258 @@ +/* This test is designed to see if one thread can be created, executed, and + return to the thread shell function. The thread shell function places + the thread in a finished state. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_thread.h" + + +static unsigned long thread_0_counter = 0; +static unsigned long thread_0_enter = 0; +static unsigned long thread_0_exit = 0; +static unsigned long thread_1_counter = 0; + +static TX_THREAD thread_0; +static TX_THREAD thread_1; +static TX_THREAD thread_2; +static TX_THREAD *saved_ptr; +static ULONG saved_count; + +/* Define task prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void entry_exit_notify(TX_THREAD *thread_ptr, UINT type) +{ + + /* Check for the appropriate thread. */ + if (thread_ptr != &thread_0) + return; + + /* Check for type. */ + if (type == TX_THREAD_ENTRY) + thread_0_enter++; + else if (type == TX_THREAD_EXIT) + thread_0_exit++; +} + + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_completed_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Setup the notify call to test that logic. */ + status += tx_thread_entry_exit_notify(&thread_0, entry_exit_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Completed Test....................................... ERROR #1\n"); + test_control_return(1); + } + +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Thread Completed Test....................................... ERROR #2\n"); + test_control_return(1); + } + +#endif + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Completed Test....................................... ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Completed Test....................................... ERROR #4\n"); + test_control_return(1); + } + + /* Move the created pointer to thread 1 to test the delete path fully. */ + saved_ptr = _tx_thread_created_ptr; + _tx_thread_created_ptr = &thread_0; +} + + + +/* Define the test thread. */ + +static void thread_0_entry(ULONG thread_input) +{ + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Fall through to the return in order to place the thread in a finished + state. */ +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Thread Completed Test....................................... "); + + /* Increment thread 1 counter. */ + thread_1_counter++; + + /* Attempt to delete thread 2, which is in the wrong stat for deleting. */ + status = tx_thread_delete(&thread_2); + + /* Check for the proper status. */ + if (status != TX_DELETE_ERROR) + { + + /* Thread delete error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Attempt to suspend thread 0, which is in a completed state. */ + status = tx_thread_suspend(&thread_0); + + /* Check for the correct status. */ + if (status != TX_SUSPEND_ERROR) + { + + /* Thread suspend error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Attempt to delete thread 0. */ + status = tx_thread_delete(&thread_0); + + /* Check for the proper status. */ + if (status != TX_SUCCESS) + { + + /* Thread delete error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Sleep to let thread 2 run. */ + tx_thread_sleep(2); + + /* Save the created count. */ + saved_count = _tx_thread_created_count; + + /* Now setup things so we can fake a delete of one thread. */ + _tx_thread_created_ptr = &thread_2; + thread_2.tx_thread_created_next = &thread_2; + thread_2.tx_thread_created_previous = &thread_2; + _tx_thread_created_count = 1; + + /* Attempt to delete thread 2. */ + status = tx_thread_delete(&thread_2); + + /* Check for the proper status. */ + if (status != TX_SUCCESS) + { + + /* Thread delete error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* if still okay, restore the saved thread pointer. */ + if (saved_ptr -> tx_thread_id == TX_THREAD_ID) + { + /* Restore. */ + _tx_thread_created_ptr = saved_ptr; + + /* Setup the link pointers again. */ + saved_ptr -> tx_thread_created_previous = &thread_1; + thread_1.tx_thread_created_next = saved_ptr; + + /* Setup the created count. */ + _tx_thread_created_count = saved_count - 1; + } + + /* Determine if the first Thread has run and if it's current state is + finished. */ + if ((thread_0.tx_thread_state == TX_COMPLETED) && (thread_0_counter == 1) && +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + (thread_0_enter == 1) && (thread_0_exit == 1)) +#else + (thread_0_enter == 0) && (thread_0_exit == 0)) +#endif + { + + /* Successful thread finish test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } + else + { + + /* Thread Finish error. */ + printf("ERROR #9\n"); + test_control_return(1); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + + /* Fall through to the return in order to place the thread in a finished + state. */ +} diff --git a/test/tx/regression/threadx_thread_create_preemption_threshold_test.c b/test/tx/regression/threadx_thread_create_preemption_threshold_test.c new file mode 100644 index 00000000..ad0d1d4e --- /dev/null +++ b/test/tx/regression/threadx_thread_create_preemption_threshold_test.c @@ -0,0 +1,140 @@ +/* This test is designed to test for preemption-threshold use during thread creation during initialization. */ + +#include <stdio.h> +#include "tx_api.h" + +//static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_create_preemption_threshold_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 0, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Create Preemption-Threshold from Init Test........... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 0, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Create Preemption-Threshold from Init Test........... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 0, 100, TX_DONT_START); + status += tx_thread_resume(&thread_0); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Create Preemption-Threshold from Init Test........... ERROR #3\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + + /* Inform user. */ + printf("Running Thread Create Preemption-Threshold from Init Test........... "); + + /* If either of the other threads have run, an error is present. */ + if ((thread_1_counter) || (thread_2_counter)) + { + + /* Test error! */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Sleep for two ticks (one is insufficient to guarantee the other + tasks will run, if this executes too close to the tick interrupt. */ + tx_thread_sleep(2); + + + /* Now, both threads should have run. */ + if ((thread_1_counter != 1) || (thread_2_counter != 1)) + { + + /* Test error! */ + printf("ERROR #5\n"); + test_control_return(2); + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + + /* Increment this thread's counter. */ + thread_1_counter++; +} + + +static void thread_2_entry(ULONG thread_input) +{ + + /* Increment the thread counter. */ + thread_2_counter++; +} + diff --git a/test/tx/regression/threadx_thread_delayed_suspension_test.c b/test/tx/regression/threadx_thread_delayed_suspension_test.c new file mode 100644 index 00000000..6d6d27d0 --- /dev/null +++ b/test/tx/regression/threadx_thread_delayed_suspension_test.c @@ -0,0 +1,390 @@ +/* This test checks out the delayed suspension clear from tx_thread_resume. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" + + +#define DEMO_STACK_SIZE TEST_STACK_SIZE_PRINTF + + +/* Define the ThreadX object control blocks... */ + +static TX_THREAD thread_0; +static TX_THREAD thread_1; +static TX_SEMAPHORE semaphore_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define the ISR dispatch routine. */ + +#ifndef TX_NOT_INTERRUPTABLE + +#if defined(TX_WIN32_MEMORY_SIZE) || defined(TX_LINUX_MEMORY_SIZE) +/* Use larger array size when running on Win32 test platform because of greater speed. */ +#define ARRAY_SIZE 100 +#else +#define ARRAY_SIZE 10 +#endif + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); +static void thread_2_entry(ULONG thread_input); + +static UINT delayed_suspend_set; + +static ULONG thread_2_counter; +static ULONG thread_2_counter_capture; + +static ULONG min_loop_count; +static ULONG max_loop_count; +static ULONG loop_count; +static volatile ULONG count; +static volatile ULONG destination = 0; +static ULONG start_time; +static ULONG lower_bound; +static ULONG upper_bound; +static ULONG current_itterations; +#ifdef DEBUG_1 +static ULONG last_loop_count; +#endif +static TX_THREAD thread_2; +static TX_SEMAPHORE semaphore_1; + +static ULONG array_delay[ARRAY_SIZE]; + +static ULONG delay_function(void) +{ + +ULONG accumulator; +ULONG i; + + for (i = 0; i < ARRAY_SIZE; i++) + array_delay[i] = i; + + for (i = 0; i < ARRAY_SIZE-4; i++) + { + array_delay[i] = (array_delay[i+1] * array_delay[i+2]) * (array_delay[i+3] * array_delay[i+4]); + } + + accumulator = 0; + for (i = 0; i < ARRAY_SIZE; i++) + accumulator = accumulator + array_delay[i]; + + return(accumulator); +} + + +static void test_isr(void) +{ +ULONG i; + + /* Determine if we are in calibration mode. */ + if (loop_count != 0xFFFFFFFF) + { + if (loop_count < min_loop_count) + min_loop_count = loop_count; + if (loop_count > max_loop_count) + max_loop_count = loop_count; + + lower_bound = loop_count - 1; + upper_bound = loop_count + 1; + if (lower_bound < min_loop_count) + lower_bound = min_loop_count; + if (upper_bound > max_loop_count) + lower_bound = max_loop_count; + + if ((current_itterations < lower_bound) || (current_itterations > upper_bound)) + current_itterations = lower_bound; + +#ifdef DEBUG_1 + /* Last loop count. */ + last_loop_count = loop_count; +#endif + + /* Reset the loop count to all ones! */ + loop_count = 0xFFFFFFFF; + } + count++; + for (i = 0; i < (count%32); i++) + destination++; + + /* Check to see if the interrupt occurred in the middle of the suspension. */ + if ((thread_2.tx_thread_suspending) && (delayed_suspend_set == 0)) + { + + /* Yes, we have taken the interrupt in the middle of a thread suspension. */ + + /* Indicate we have got the condition. */ + delayed_suspend_set = 1; + + /* Capture the current thread 2 counter. */ + thread_2_counter_capture = thread_2_counter; + + /* Now attempt to set the delayed suspension. */ + tx_thread_suspend(&thread_2); + + /* Check for the delayed suspension flag being set. */ + if (thread_2.tx_thread_delayed_suspend != 1) + { + + /* Error! Setup the counters to indicate an error. */ + thread_2_counter = 0xEEEEEEEE; + thread_2_counter_capture = 0xFFFFFFFF; + } + + /* Now, abort the suspension for thread 2... the thread should switch to a pure suspended state. */ + tx_thread_wait_abort(&thread_2); + + /* Check for the proper state. */ + if (thread_2.tx_thread_state != TX_SUSPENDED) + { + + /* Error! Setup the counters to indicate an error. */ + thread_2_counter = 0xEEEEEEEE; + thread_2_counter_capture = 0xFFFFFFFF; + } + } + +} +#endif + + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_delayed_suspension_application_define(void *first_unused_memory) +#endif +{ + +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + /* Create the main thread. */ + tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, DEMO_STACK_SIZE, + 2, 2, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + DEMO_STACK_SIZE; + + /* Create threads 1 and 2. */ + tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, DEMO_STACK_SIZE, + 2, 2, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + DEMO_STACK_SIZE; + + /* Create the semaphore. */ + tx_semaphore_create(&semaphore_0, "semaphore 0", 0); + +#ifndef TX_NOT_INTERRUPTABLE + + tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, DEMO_STACK_SIZE, + 1, 1, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + DEMO_STACK_SIZE; + + tx_semaphore_create(&semaphore_1, "semaphore 1", 0); + + thread_2_counter = 0; + thread_2_counter_capture = 0; + min_loop_count = 0xFFFFFFFF; + max_loop_count = 0; + loop_count = 0xFFFFFFFF; +#ifdef DEBUG_1 + last_loop_count = 0; +#endif +#endif +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Thread Delayed Suspension Clearing Test..................... "); + + /* Relinquish to the other thread. */ + tx_thread_relinquish(); + + /* At this point thread 1 has suspended on the semaphore. */ + + /* Suspend the already suspended thread. */ + tx_thread_suspend(&thread_1); + + /* Set the semaphore, which should make it go into a suspend state. */ + tx_semaphore_put(&semaphore_0); + + /* Resume the other thread so it runs again. */ + tx_thread_resume(&thread_1); + + /* Relinquish so it can run again. */ + tx_thread_relinquish(); + + /* Suspend the already suspended thread. */ + tx_thread_suspend(&thread_1); + + /* Now, clear the delayed suspension. */ + status = tx_thread_resume(&thread_1); + + if (status != TX_SUSPEND_LIFTED) + { + + /* Delayed suspension error. */ + printf("ERROR #1\n"); + test_control_return(1); + } + +#ifndef TX_NOT_INTERRUPTABLE + + /* Setup the test ISR. */ + test_isr_dispatch = test_isr; + + /* Resume the test thread. */ + tx_thread_resume(&thread_2); + + /* Wait until we see the delayed suspension set flag. */ + while(delayed_suspend_set == 0) + { + + /* Abort the suspension for thread 2. */ + tx_thread_wait_abort(&thread_2); + + /* Just relinquish. */ + tx_thread_relinquish(); + } + + /* Relinquish one more time to make sure thread 2 could run if it is ready. */ + tx_thread_relinquish(); + + /* At this point, check for an error. */ + if (thread_2_counter != thread_2_counter_capture) + { + + /* Delayed suspension error... thread kept running! */ + printf("ERROR #2\n"); + test_control_return(1); + } +#endif + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + /* This thread simply gets the semaphore... */ + while(1) + { + + /* Get semaphore. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + /* Check completion status. */ + if (status != TX_SUCCESS) + break; + } +} + + +#ifndef TX_NOT_INTERRUPTABLE + + +static void thread_2_entry(ULONG thread_input) +{ + +ULONG i; + + /* Callibrate the loop count from thread sleep. */ + for (i = 0; i < 10; i++) + { + + /* Sleep to get a fresh time. */ + tx_thread_sleep(1); + + start_time = _tx_timer_system_clock; + do + { + + /* Call delay function. */ + delay_function(); + loop_count++; + } while (start_time == _tx_timer_system_clock); + + /* Wait to reset the loop count. */ + tx_thread_sleep(1); + } + + /* Setup the lower and upper bounds. */ + lower_bound = min_loop_count; + if (lower_bound > 5) + lower_bound = lower_bound - 5; + upper_bound = max_loop_count + 5; + + current_itterations = lower_bound; + + /* This thread simply suspends over and over... */ + while(1) + { + + /* Sleep to get a fresh starting time. */ + tx_thread_sleep(1); + + loop_count = 0; + start_time = _tx_timer_system_clock; + do + { + /* Call delay function. */ + delay_function(); + loop_count++; + } while (loop_count < current_itterations); + + /* Suspend this thread. */ + tx_semaphore_get(&semaphore_1, TX_WAIT_FOREVER); + + /* Adjust the current itterations. */ + current_itterations++; + if (current_itterations > upper_bound) + { + if (lower_bound > min_loop_count) + lower_bound--; + if (upper_bound < max_loop_count) + upper_bound++; + current_itterations = lower_bound; + } + + /* Increment the thread counter. */ + thread_2_counter++; + } +} + +#endif diff --git a/test/tx/regression/threadx_thread_information_test.c b/test/tx/regression/threadx_thread_information_test.c new file mode 100644 index 00000000..b72a2363 --- /dev/null +++ b/test/tx/regression/threadx_thread_information_test.c @@ -0,0 +1,474 @@ +/* This test is for the thread information services. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_thread.h" + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +/* Define task prototypes. */ + +static void thread_0_entry(ULONG task_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_information_application_define(void *first_unused_memory) +#endif +{ + +INT status; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + first_unused_memory, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Information Test..................................... ERROR #1\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +CHAR *name; +UINT state; +ULONG run_count; +UINT priority; +UINT preemption_threshold; +ULONG time_slice; +TX_THREAD *next_thread; +TX_THREAD *suspended_thread; +ULONG resumptions; +ULONG suspensions; +ULONG solicited_preemptions; +ULONG interrupt_preemptions; +ULONG priority_inversions; +ULONG time_slices; +ULONG relinquishes; +ULONG timeouts; +ULONG wait_aborts; +TX_THREAD *last_preempted_by; +ULONG non_idle_returns; +ULONG idle_returns; + + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Inform user of success getting to this test. */ + printf("Running Thread Information Test..................................... "); + + /* Get information about this thread. */ + status = tx_thread_info_get(&thread_0, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_thread_info_get(&thread_0, &name, &state, &run_count, &priority, &preemption_threshold, &time_slice, &next_thread, &suspended_thread); + + /* Check for error status. */ + if ((status != TX_SUCCESS) || (state != TX_READY) || (run_count != thread_0.tx_thread_run_count) || (priority != 16) || (preemption_threshold != 16) || + (time_slice != 0) || (next_thread != thread_0.tx_thread_created_next) || (suspended_thread != thread_0.tx_thread_suspended_next)) + { + + /* Thread error. */ + printf("ERROR #2\n"); + test_control_return(1); + } + + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Get the performance information about a NULL thread pointer. */ + status = _tx_thread_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_PTR_ERROR) + { + + /* Thread error. */ + printf("ERROR #3\n"); + test_control_return(1); + } + + /* Get the performance information about this thread. */ + status = tx_thread_performance_info_get(&thread_0, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_thread_performance_info_get(&thread_0, &resumptions, &suspensions, &solicited_preemptions, &interrupt_preemptions, &priority_inversions, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &last_preempted_by); + + /* Check for error. */ + if ((status != TX_SUCCESS) || (resumptions != thread_0.tx_thread_performance_resume_count) || (suspensions != thread_0.tx_thread_performance_suspend_count) || + (solicited_preemptions != thread_0.tx_thread_performance_solicited_preemption_count) || (interrupt_preemptions != thread_0.tx_thread_performance_interrupt_preemption_count) || + (priority_inversions != thread_0.tx_thread_performance_priority_inversion_count) || (time_slices != thread_0.tx_thread_performance_time_slice_count) || + (relinquishes != thread_0.tx_thread_performance_relinquish_count) || (timeouts != thread_0.tx_thread_performance_timeout_count) || (wait_aborts != thread_0.tx_thread_performance_wait_abort_count) || + (last_preempted_by != thread_0.tx_thread_performance_last_preempting_thread)) + { + + /* Thread error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Get the system performance information. */ + status = tx_thread_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_thread_performance_system_info_get(&resumptions, &suspensions, &solicited_preemptions, &interrupt_preemptions, &priority_inversions, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &non_idle_returns, &idle_returns); + + /* Check for error. */ + if ((status != TX_SUCCESS) || (resumptions != _tx_thread_performance_resume_count) || (suspensions != _tx_thread_performance_suspend_count) || + (solicited_preemptions != _tx_thread_performance_solicited_preemption_count) || (interrupt_preemptions != _tx_thread_performance_interrupt_preemption_count) || + (priority_inversions != _tx_thread_performance_priority_inversion_count) || (time_slices != _tx_thread_performance_time_slice_count) || + (relinquishes != _tx_thread_performance_relinquish_count) || (timeouts != _tx_thread_performance_timeout_count) || (wait_aborts != _tx_thread_performance_wait_abort_count) || + (non_idle_returns != _tx_thread_performance_non_idle_return_count) || (idle_returns != _tx_thread_performance_idle_return_count)) + { + + /* Thread error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + else + { + + /* Success! */ + printf("SUCCESS!\n"); + test_control_return(0); + } +#else + + /* Get the performance information about this thread. */ + status = tx_thread_performance_info_get(&thread_0, &resumptions, &suspensions, &solicited_preemptions, &interrupt_preemptions, &priority_inversions, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &last_preempted_by); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Get the performance information about this thread. */ + status = tx_thread_performance_info_get(TX_NULL, &resumptions, &suspensions, &solicited_preemptions, &interrupt_preemptions, &priority_inversions, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &last_preempted_by); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Get the performance information about this thread. */ + status = tx_thread_performance_info_get(TX_NULL, TX_NULL, &suspensions, &solicited_preemptions, &interrupt_preemptions, &priority_inversions, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &last_preempted_by); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Get the performance information about this thread. */ + status = tx_thread_performance_info_get(TX_NULL, TX_NULL, TX_NULL, &solicited_preemptions, &interrupt_preemptions, &priority_inversions, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &last_preempted_by); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Get the performance information about this thread. */ + status = tx_thread_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, &interrupt_preemptions, &priority_inversions, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &last_preempted_by); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Get the performance information about this thread. */ + status = tx_thread_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &priority_inversions, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &last_preempted_by); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Get the performance information about this thread. */ + status = tx_thread_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &last_preempted_by); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Get the performance information about this thread. */ + status = tx_thread_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, + &relinquishes, &timeouts, &wait_aborts, &last_preempted_by); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Get the performance information about this thread. */ + status = tx_thread_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, + TX_NULL, &timeouts, &wait_aborts, &last_preempted_by); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Get the performance information about this thread. */ + status = tx_thread_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, + TX_NULL, TX_NULL, &wait_aborts, &last_preempted_by); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Get the performance information about this thread. */ + status = tx_thread_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, + TX_NULL, TX_NULL, TX_NULL, &last_preempted_by); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Get the performance information about this thread. */ + status = tx_thread_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, + TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Get the system performance information. */ + status = tx_thread_performance_system_info_get(&resumptions, &suspensions, &solicited_preemptions, &interrupt_preemptions, &priority_inversions, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &non_idle_returns, &idle_returns); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Get the system performance information. */ + status = tx_thread_performance_system_info_get(TX_NULL, &suspensions, &solicited_preemptions, &interrupt_preemptions, &priority_inversions, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &non_idle_returns, &idle_returns); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Get the system performance information. */ + status = tx_thread_performance_system_info_get(TX_NULL, TX_NULL, &solicited_preemptions, &interrupt_preemptions, &priority_inversions, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &non_idle_returns, &idle_returns); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Get the system performance information. */ + status = tx_thread_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, &interrupt_preemptions, &priority_inversions, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &non_idle_returns, &idle_returns); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + /* Get the system performance information. */ + status = tx_thread_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, &priority_inversions, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &non_idle_returns, &idle_returns); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + /* Get the system performance information. */ + status = tx_thread_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &time_slices, + &relinquishes, &timeouts, &wait_aborts, &non_idle_returns, &idle_returns); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Get the system performance information. */ + status = tx_thread_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, + &relinquishes, &timeouts, &wait_aborts, &non_idle_returns, &idle_returns); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Get the system performance information. */ + status = tx_thread_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, + TX_NULL, &timeouts, &wait_aborts, &non_idle_returns, &idle_returns); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + + /* Get the system performance information. */ + status = tx_thread_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, + TX_NULL, TX_NULL, &wait_aborts, &non_idle_returns, &idle_returns); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + /* Get the system performance information. */ + status = tx_thread_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, + TX_NULL, TX_NULL, TX_NULL, &non_idle_returns, &idle_returns); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Get the system performance information. */ + status = tx_thread_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, + TX_NULL, TX_NULL, TX_NULL, TX_NULL, &idle_returns); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #28\n"); + test_control_return(1); + } + + /* Get the system performance information. */ + status = tx_thread_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, + TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Thread error. */ + printf("ERROR #29\n"); + test_control_return(1); + } + + /* Success! */ + printf("SUCCESS!\n"); + test_control_return(0); + +#endif + +} diff --git a/test/tx/regression/threadx_thread_multi_level_preemption_threshold_test.c b/test/tx/regression/threadx_thread_multi_level_preemption_threshold_test.c new file mode 100644 index 00000000..a65410fa --- /dev/null +++ b/test/tx/regression/threadx_thread_multi_level_preemption_threshold_test.c @@ -0,0 +1,982 @@ +/* This test is designed to test multi-level preemption threshold. The protection placed + by a thread must be preserved after higher-priority thread preemption that is above the threshold. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_thread.h" + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_1; +static TX_THREAD thread_2; +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_2a_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +static unsigned long thread_1_counter = 0; + +static unsigned long thread_2_counter = 0; + +static unsigned long thread_2a_counter = 0; +static TX_THREAD thread_2a; + +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + +static unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; + +#endif + +static TX_THREAD thread_0; + + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + +/* Define new preemption-threshold threads for complete bit map checking. */ + +static TX_THREAD thread_1_0; +static TX_THREAD thread_2_1; +static TX_THREAD thread_3_2; +static TX_THREAD thread_4_3; +static TX_THREAD thread_6_5; +static TX_THREAD thread_8_7; +static TX_THREAD thread_10_9; +static TX_THREAD thread_12_11; +static TX_THREAD thread_14_13; +static TX_THREAD thread_16_15; +static TX_THREAD thread_18_17; +static TX_THREAD thread_20_19; +static TX_THREAD thread_22_21; +static TX_THREAD thread_24_23; +static TX_THREAD thread_26_25; +static TX_THREAD thread_28_27; +static TX_THREAD thread_30_29; + + +/* Define timer for preemption of priority 1 test. */ + +static TX_TIMER timer_0; + + +/* Define counters. */ + +static unsigned long timer_0_counter = 0; +static unsigned long thread_1_0_counter = 0; +static unsigned long thread_2_1_counter = 0; +static unsigned long thread_3_2_counter = 0; +static unsigned long thread_4_3_counter = 0; +static unsigned long thread_6_5_counter = 0; +static unsigned long thread_8_7_counter = 0; +static unsigned long thread_10_9_counter = 0; +static unsigned long thread_12_11_counter = 0; +static unsigned long thread_14_13_counter = 0; +static unsigned long thread_16_15_counter = 0; +static unsigned long thread_18_17_counter = 0; +static unsigned long thread_20_19_counter = 0; +static unsigned long thread_22_21_counter = 0; +static unsigned long thread_24_23_counter = 0; +static unsigned long thread_26_25_counter = 0; +static unsigned long thread_28_27_counter = 0; +static unsigned long thread_30_29_counter = 0; + + +/* Define new preemption-threshold test thread entry points. */ + +static void thread_1_0_entry(ULONG thread_input); +static void thread_2_1_entry(ULONG thread_input); +static void thread_3_2_entry(ULONG thread_input); +static void thread_4_3_entry(ULONG thread_input); +static void thread_6_5_entry(ULONG thread_input); +static void thread_8_7_entry(ULONG thread_input); +static void thread_10_9_entry(ULONG thread_input); +static void thread_12_11_entry(ULONG thread_input); +static void thread_14_13_entry(ULONG thread_input); +static void thread_16_15_entry(ULONG thread_input); +static void thread_18_17_entry(ULONG thread_input); +static void thread_20_19_entry(ULONG thread_input); +static void thread_22_21_entry(ULONG thread_input); +static void thread_24_23_entry(ULONG thread_input); +static void thread_26_25_entry(ULONG thread_input); +static void thread_28_27_entry(ULONG thread_input); +static void thread_30_29_entry(ULONG thread_input); + +/* Define timer 1 entry. */ + +static void timer_0_entry(ULONG id); + + +#endif + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_multi_level_preemption_threshold_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + (TX_MAX_PRIORITIES-1), (TX_MAX_PRIORITIES/2), TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #1\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD /* skip this test and pretend it passed */ + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + (TX_MAX_PRIORITIES/2), (TX_MAX_PRIORITIES/2), TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 10, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2a, "thread 2a", thread_2a_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #4\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 11, 11, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #5\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 9, 9, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #6\n"); + test_control_return(1); + } + + /* Create new cascading preemption-threshold test threads. */ + + status = tx_thread_create(&thread_30_29, "thread 30-29", thread_30_29_entry, 30, + pointer, TEST_STACK_SIZE_PRINTF, + 30, 29, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #7\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_28_27, "thread 28-27", thread_28_27_entry, 28, + pointer, TEST_STACK_SIZE_PRINTF, + 28, 27, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #8\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_26_25, "thread 26-25", thread_26_25_entry, 26, + pointer, TEST_STACK_SIZE_PRINTF, + 26, 25, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #9\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_24_23, "thread 24-23", thread_24_23_entry, 24, + pointer, TEST_STACK_SIZE_PRINTF, + 24, 23, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #10\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_22_21, "thread 22-21", thread_22_21_entry, 22, + pointer, TEST_STACK_SIZE_PRINTF, + 22, 21, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #11\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_20_19, "thread 20-19", thread_20_19_entry, 20, + pointer, TEST_STACK_SIZE_PRINTF, + 20,19, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #12\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_18_17, "thread 18-17", thread_18_17_entry, 18, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 17, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #13\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_16_15, "thread 16-15", thread_16_15_entry, 16, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 15, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #14\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_14_13, "thread 14-13", thread_14_13_entry, 14, + pointer, TEST_STACK_SIZE_PRINTF, + 14, 13, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #15\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_12_11, "thread 12-11", thread_12_11_entry, 12, + pointer, TEST_STACK_SIZE_PRINTF, + 12, 11, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #16\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_10_9, "thread 10-9", thread_10_9_entry, 10, + pointer, TEST_STACK_SIZE_PRINTF, + 10, 9, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #17\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_8_7, "thread 8-7", thread_8_7_entry, 8, + pointer, TEST_STACK_SIZE_PRINTF, + 8, 7, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #18\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_6_5, "thread 6-5", thread_6_5_entry, 6, + pointer, TEST_STACK_SIZE_PRINTF, + 6, 5, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #19\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_4_3, "thread 4-3", thread_4_3_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 4, 3, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #20\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_3_2, "thread 3-2", thread_3_2_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 3, 2, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #21\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2_1, "thread 2-1", thread_2_1_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 2, 1, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #22\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1_0, "thread 1-0", thread_1_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 1, 1, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #23\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_0, "timer 0", timer_0_entry, 0, 1, 0, TX_NO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multi-Level Preemption Threshold Test................ ERROR #24\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD +UINT status; +UINT old_preempt; +#endif + + + /* Inform user. */ + printf("Running Thread Multi-Level Preemption Threshold Test................ "); + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD /* skip this test and pretend it passed */ + + /* Wakeup Thread 1. It has a higher-priority but should be blocked by + preemption threshold. */ + status = tx_thread_resume(&thread_1); + + /* Check status and make sure the other run counters are proper. */ + if ((status != TX_SUCCESS) || (thread_1_counter) || (thread_2_counter) || + (thread_3_counter) || (thread_4_counter)) + { + + /* Thread Preempt Threshold error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + + /* Resume thread 2 which will preempt this thread. */ + status = tx_thread_resume(&thread_2); + + /* Check for good status and proper run counters. All other threads except for + thread 1 should have executed. */ + if ((status != TX_SUCCESS) || (thread_1_counter) || (thread_2_counter != 1) || + (thread_3_counter != 1) || (thread_4_counter != 1)) + { + + /* Thread Preempt Threshold error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + /* Set preemption threshold low enough to allow thread 1 to execute. */ + status = tx_thread_preemption_change(&thread_0, ((TX_MAX_PRIORITIES/2)+1), &old_preempt); + + /* Check for good status and proper run counters. All other threads except for + thread 1 should have executed. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 1) || + (thread_3_counter != 1) || (thread_4_counter != 1) || + (_tx_thread_preempted_maps[0]) || (_tx_thread_preempt_disable)) + { + + /* Thread Preempt Threshold error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Set preemption threshold to keep new test threads from running. */ + status = tx_thread_preemption_change(&thread_0, 17, &old_preempt); + + /* Now wakup the lowest priority preemption-threshold thread. */ + status += tx_thread_resume(&thread_30_29); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Thread Preempt Threshold error. */ + printf("ERROR #28\n"); + test_control_return(1); + } + + /* Now, self suspend. */ + status = tx_thread_suspend(&thread_0); + + /* Check to make sure all the preemption-threshold threads ran. */ + if ((thread_1_0_counter != 1) || + (thread_2_1_counter != 1) || + (thread_3_2_counter != 1) || + (thread_4_3_counter != 1) || + (thread_6_5_counter != 1) || + (thread_8_7_counter != 1) || + (thread_10_9_counter != 1) || + (thread_12_11_counter != 1) || + (thread_14_13_counter != 1) || + (thread_16_15_counter != 1) || + (thread_18_17_counter != 1) || + (thread_20_19_counter != 1) || + (thread_22_21_counter != 1) || + (thread_24_23_counter != 1) || + (thread_26_25_counter != 1) || + (thread_28_27_counter != 1) || + (thread_30_29_counter != 1)) + { + + /* Thread Preempt Threshold error. */ + printf("ERROR #29\n"); + test_control_return(1); + } + +#endif + + /* Successful Thread Suspend non-current thread test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + +static void thread_1_entry(ULONG thread_input) +{ + + thread_1_counter++; +} + + +static void thread_2_entry(ULONG thread_input) +{ + +UINT status; + + /* Resume thread 3 which will not preempt because of thread 2's preemption + threshold. */ + status = tx_thread_resume(&thread_3); + + /* Resume thread 2a which will not preempt this thread because it is at + the same priority. */ + status += tx_thread_resume(&thread_2a); + + /* Check status and run counters. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 0) || (thread_3_counter) || + (thread_4_counter)) + return; + + /* Resume thread 4 which will preempt. We should get back here before thread + three runs because of preemption threshold. */ + status = tx_thread_resume(&thread_4); + + /* Check status and run counters. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 0) || (thread_3_counter) || + (thread_4_counter != 1)) + return; + + /* Relinquish to the other thread at this priority level. This should + clear the preemption threshold condition and allow thread 3 to run. */ + tx_thread_relinquish(); + + /* Check status and run counters. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 0) || (thread_2a_counter != 1) || + (thread_3_counter != 1) || (thread_4_counter != 1)) + return; + + /* If all is okay, increment thread 2's counter. */ + thread_2_counter++; +} + + +static void thread_2a_entry(ULONG thread_input) +{ + + if (thread_3_counter == 1) + thread_2a_counter++; +} + + +static void thread_3_entry(ULONG thread_input) +{ + + thread_3_counter++; +} + + +static void thread_4_entry(ULONG thread_input) +{ + + thread_4_counter++; +} + + + +static void timer_0_entry(ULONG id) +{ + + /* Pretend like a preemption occurred on a thread priority of 1 with preemption-threshold set to 0. */ + _tx_thread_preempted_maps[0] = _tx_thread_preempted_maps[0] | 2; + + /* Set the thread's preemption threshold as well. */ + thread_1_0.tx_thread_preempt_threshold = 0; + + /* Increment timer 0 counter. */ + timer_0_counter++; +} + + +static void thread_1_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Activate the timer to force a priority 0 thread to interrupt. */ + status = tx_timer_activate(&timer_0); + + /* Loop to wait until timer 0 runs. */ + while (timer_0_counter == 0) + { + } + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_1_0_counter++; + } +} + + +static void thread_2_1_entry(ULONG thread_input) +{ + + /* Increment this thread's counter. */ + thread_2_1_counter++; +} + + +static void thread_3_2_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_1_0); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_3_2_counter++; + } +} + + +static void thread_4_3_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_2_1); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_4_3_counter++; + } +} + + +static void thread_6_5_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_4_3); + + /* In this particular case, we have two different preemptions to make + sure we exercise all the code. */ + + /* Now resume next highest priority thread. */ + status = tx_thread_resume(&thread_3_2); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_6_5_counter++; + } +} + + +static void thread_8_7_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_6_5); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_8_7_counter++; + } +} + + +static void thread_10_9_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_8_7); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_10_9_counter++; + } +} + +static void thread_12_11_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_10_9); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_12_11_counter++; + } +} + + +static void thread_14_13_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_12_11); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_14_13_counter++; + } +} + + +static void thread_16_15_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_14_13); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_16_15_counter++; + } +} + + +static void thread_18_17_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_16_15); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_18_17_counter++; + } +} + + +static void thread_20_19_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_18_17); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_20_19_counter++; + } +} + + +static void thread_22_21_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_20_19); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_22_21_counter++; + } +} + + +static void thread_24_23_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_22_21); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_24_23_counter++; + } +} + +static void thread_26_25_entry(ULONG thread_input)\ +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_24_23); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_26_25_counter++; + } +} + +static void thread_28_27_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_26_25); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_28_27_counter++; + } +} + +static void thread_30_29_entry(ULONG thread_input) +{ + +UINT status; + + + /* Resume next highest priority thread. */ + status = tx_thread_resume(&thread_28_27); + + /* Check for good status. */ + if (status == TX_SUCCESS) + { + + /* Increment this thread's counter. */ + thread_30_29_counter++; + } + + /* Resume thread_0. */ + tx_thread_resume(&thread_0); +} + + +#endif diff --git a/test/tx/regression/threadx_thread_multiple_non_current_test.c b/test/tx/regression/threadx_thread_multiple_non_current_test.c new file mode 100644 index 00000000..51212b3b --- /dev/null +++ b/test/tx/regression/threadx_thread_multiple_non_current_test.c @@ -0,0 +1,222 @@ +/* This test is designed to see if multiple non-current threads can be suspended. + The order the suspension and resumption occurs makes sure everything is working + right. Thread execution should remain predictable even after suspension and + resumption of threads within a priority group. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + +static unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_multiple_non_current_suspension_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Non-Current Suspend Test............................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Non-Current Suspend Test............................. ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Non-Current Suspend Test............................. ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Non-Current Suspend Test............................. ERROR #4\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Non-Current Suspend Test............................. ERROR #5\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + /* Inform user. */ + printf("Running Thread Non-Current Suspend Test............................. "); + + /* Wakeup all other threads at same priority. */ + status = tx_thread_resume(&thread_1); + status += tx_thread_resume(&thread_2); + + /* Check for good status. */ + if (status != TX_SUCCESS) + { + + /* Thread Suspend error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Wakeup thread with preempt. */ + status = tx_thread_resume(&thread_3); + + /* Check for good status and proper counters. */ + if ((status != TX_SUCCESS) || (thread_3_counter != 1) || (thread_1_counter) || + (thread_2_counter) || (thread_4_counter)) + { + + /* Thread Suspend error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Suspend thread 1. */ + status = tx_thread_suspend(&thread_1); + + /* Resume thread 4. */ + status += tx_thread_resume(&thread_4); + + /* Check for good status and proper counters. */ + if ((status != TX_SUCCESS) || (thread_3_counter != 1) || (thread_1_counter) || + (thread_2_counter) || (thread_4_counter)) + { + + /* Thread Suspend error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Relinquish to thread 2 and 4 before we get back. */ + tx_thread_relinquish(); + + /* Check for good status and proper counters. */ + if ((status != TX_SUCCESS) || (thread_3_counter != 1) || (thread_1_counter) || + (thread_2_counter != 1) || (thread_4_counter != 1)) + { + + /* Thread Suspend error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Successful Thread Suspend non-current thread test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + +static void thread_1_entry(ULONG thread_input) +{ + + thread_1_counter++; +} + +static void thread_2_entry(ULONG thread_input) +{ + if (thread_4_counter == 0) + thread_2_counter++; +} + +static void thread_3_entry(ULONG thread_input) +{ + + thread_3_counter++; +} + +static void thread_4_entry(ULONG thread_input) +{ + + if (thread_2_counter == 1) + thread_4_counter++; +} + diff --git a/test/tx/regression/threadx_thread_multiple_sleep_test.c b/test/tx/regression/threadx_thread_multiple_sleep_test.c new file mode 100644 index 00000000..9a876295 --- /dev/null +++ b/test/tx/regression/threadx_thread_multiple_sleep_test.c @@ -0,0 +1,184 @@ +/* This test is designed to test multiple threads sleeping for 33 ticks. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; +//static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_multiple_sleep_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Sleep for 33 Test.................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Sleep for 33 Test.................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Sleep for 33 Test.................... ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, 3, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Sleep for 33 Test.................... ERROR #4\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Sleep for a couple ticks. */ + tx_thread_sleep(33); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 1 counter. */ + thread_1_counter++; + + /* Sleep for a couple ticks. */ + tx_thread_sleep(33); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 0 counter. */ + thread_2_counter++; + + /* Sleep for a couple ticks. */ + tx_thread_sleep(33); + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + + + /* Inform user. */ + printf("Running Thread Multiple Thread Sleep for 33 Test.................... "); + + /* Clear the tick count. */ + tx_time_set(0); + + /* Sleep for 100 ticks (+1 in case tick before threads 0,1,2 have run). */ + tx_thread_sleep(101); + + /* Determine if the sleep was accurate. */ + if ((thread_0_counter == 4) && (thread_1_counter == 4) && + (thread_2_counter == 4)) + { + + /* Successful Multiple Sleep test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } + else + { + + /* Thread Multiple Sleep error. */ + printf("ERROR #5\n"); + test_control_return(1); + } +} + diff --git a/test/tx/regression/threadx_thread_multiple_suspension_test.c b/test/tx/regression/threadx_thread_multiple_suspension_test.c new file mode 100644 index 00000000..0e4e5c06 --- /dev/null +++ b/test/tx/regression/threadx_thread_multiple_suspension_test.c @@ -0,0 +1,432 @@ +/* This test is designed to see if multiple threads can be created and suspend. + The order the suspension and resumption occurs makes sure everything is working + right. All the counters should increment at the same rate. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_thread.h" + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + +static unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; + +static unsigned long thread_5_counter = 0; +static TX_THREAD thread_5; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +static void thread_5_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_multiple_suspension_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + /* Create thread 0. */ + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 13, 13, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Suspend/Resume Test.................. ERROR #1\n"); + test_control_return(1); + } + + /* Create thread 1. */ + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + (TX_MAX_PRIORITIES/2), (TX_MAX_PRIORITIES/2), TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Suspend/Resume Test.................. ERROR #2\n"); + test_control_return(1); + } + + /* Create thread 2. */ + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + (TX_MAX_PRIORITIES/2), (TX_MAX_PRIORITIES/2), TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Suspend/Resume Test.................. ERROR #3\n"); + test_control_return(1); + } + + /* Create thread 3. */ + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + (TX_MAX_PRIORITIES/2), (TX_MAX_PRIORITIES/2), TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Suspend/Resume Test.................. ERROR #4\n"); + test_control_return(1); + } + + /* Create thread 4. */ + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Suspend/Resume Test.................. ERROR #5\n"); + test_control_return(1); + } + + /* Create thread 5. Make this thread non-preemptable for the range of priorities here... */ + status = tx_thread_create(&thread_5, "thread 5", thread_5_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + (TX_MAX_PRIORITIES-1), 13, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Suspend/Resume Test.................. ERROR #6\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Suspend this thread... */ + tx_thread_suspend(&thread_0); + + /* Resume thread 5... */ + tx_thread_resume(&thread_5); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 1 counter. */ + thread_1_counter++; + + /* Suspend this thread. */ + tx_thread_suspend(&thread_1); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 2 counter. */ + thread_2_counter++; + + /* Suspend this thread. */ + tx_thread_suspend(&thread_2); + } +} + +static void thread_3_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 3 counter. */ + thread_3_counter++; + + /* Suspend this thread. */ + tx_thread_suspend(&thread_3); + } +} + +static void thread_4_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 4 counter. */ + thread_4_counter++; + + /* Suspend this thread. */ + tx_thread_suspend(&thread_4); + } +} + +static void thread_5_entry(ULONG thread_input) +{ + +UINT status; + + /* Inform user. */ + printf("Running Thread Multiple Thread Suspend/Resume Test.................. "); + + /* Determine if all the other threads are in a suspended state. */ + if ((thread_0.tx_thread_state != TX_SUSPENDED) || (thread_1.tx_thread_state != TX_SUSPENDED) || + (thread_2.tx_thread_state != TX_SUSPENDED) || (thread_3.tx_thread_state != TX_SUSPENDED) || + (thread_4.tx_thread_state != TX_SUSPENDED)) + { + + /* Thread Suspend error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Make sure that each thread has run once. */ + if ((thread_0_counter != 1) || (thread_1_counter != 1) || + (thread_2_counter != 1) || (thread_3_counter != 1) || + (thread_4_counter != 1)) + { + + /* Thread Suspend error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Resume all of the threads. */ + status = tx_thread_resume(&thread_0); + + /* Determine if all the other threads are in the proper state. */ + if ((thread_0.tx_thread_state != TX_READY) || (thread_1.tx_thread_state != TX_SUSPENDED) || + (thread_2.tx_thread_state != TX_SUSPENDED) || (thread_3.tx_thread_state != TX_SUSPENDED) || + (thread_4.tx_thread_state != TX_SUSPENDED) || (status != TX_SUCCESS)) + { + + /* Thread Suspend error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Make sure that each thread has run once. */ + if ((thread_0_counter != 1) || (thread_1_counter != 1) || + (thread_2_counter != 1) || (thread_3_counter != 1) || + (thread_4_counter != 1)) + { + + /* Thread Suspend error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + status = tx_thread_resume(&thread_1); + + /* Determine if all the other threads are in the proper state. */ + if ((thread_0.tx_thread_state != TX_READY) || (thread_1.tx_thread_state != TX_READY) || + (thread_2.tx_thread_state != TX_SUSPENDED) || (thread_3.tx_thread_state != TX_SUSPENDED) || + (thread_4.tx_thread_state != TX_SUSPENDED) || (status != TX_SUCCESS)) + { + + /* Thread Suspend error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Make sure that each thread has run once. */ + if ((thread_0_counter != 1) || (thread_1_counter != 1) || + (thread_2_counter != 1) || (thread_3_counter != 1) || + (thread_4_counter != 1)) + { + + /* Thread Suspend error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + status = tx_thread_resume(&thread_2); + + /* Determine if all the other threads are in the proper state. */ + if ((thread_0.tx_thread_state != TX_READY) || (thread_1.tx_thread_state != TX_READY) || + (thread_2.tx_thread_state != TX_READY) || (thread_3.tx_thread_state != TX_SUSPENDED) || + (thread_4.tx_thread_state != TX_SUSPENDED) || (status != TX_SUCCESS)) + { + + /* Thread Suspend error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Make sure that each thread has run once. */ + if ((thread_0_counter != 1) || (thread_1_counter != 1) || + (thread_2_counter != 1) || (thread_3_counter != 1) || + (thread_4_counter != 1)) + { + + /* Thread Suspend error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + status = tx_thread_resume(&thread_3); + + /* Determine if all the other threads are in the proper state. */ + if ((thread_0.tx_thread_state != TX_READY) || (thread_1.tx_thread_state != TX_READY) || + (thread_2.tx_thread_state != TX_READY) || (thread_3.tx_thread_state != TX_READY) || + (thread_4.tx_thread_state != TX_SUSPENDED) || (status != TX_SUCCESS)) + { + + /* Thread Suspend error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Make sure that each thread has run once. */ + if ((thread_0_counter != 1) || (thread_1_counter != 1) || + (thread_2_counter != 1) || (thread_3_counter != 1) || + (thread_4_counter != 1)) + { + + /* Thread Suspend error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + status = tx_thread_resume(&thread_4); + + /* Determine if all the other threads are in the proper state. */ + if ((thread_0.tx_thread_state != TX_READY) || (thread_1.tx_thread_state != TX_READY) || + (thread_2.tx_thread_state != TX_READY) || (thread_3.tx_thread_state != TX_READY) || + (thread_4.tx_thread_state != TX_READY) || (status != TX_SUCCESS)) + { + + /* Thread Suspend error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Make sure that each thread has run once. */ + if ((thread_0_counter != 1) || (thread_1_counter != 1) || + (thread_2_counter != 1) || (thread_3_counter != 1) || + (thread_4_counter != 1)) + { + + /* Thread Suspend error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Relinquish to allow other threads to run. */ + tx_thread_relinquish(); + + /* Determine if all the other threads are in a suspended state. */ + if ((thread_0.tx_thread_state != TX_SUSPENDED) || (thread_1.tx_thread_state != TX_SUSPENDED) || + (thread_2.tx_thread_state != TX_SUSPENDED) || (thread_3.tx_thread_state != TX_SUSPENDED) || + (thread_4.tx_thread_state != TX_SUSPENDED)) + { + + /* Thread Suspend error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Make sure that each thread has run twice. */ + if ((thread_0_counter != 2) || (thread_1_counter != 2) || + (thread_2_counter != 2) || (thread_3_counter != 2) || + (thread_4_counter != 2)) + { + + /* Thread Suspend error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Suspend a thread that is already suspended. */ + status = tx_thread_suspend(&thread_4); + + /* Check for error condition. */ + if (status != TX_SUCCESS) + { + /* Thread Suspend error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + else + { + + /* Increment thread 5 counter. */ + thread_5_counter++; + + /* Successful Thread Suspend test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + diff --git a/test/tx/regression/threadx_thread_multiple_time_slice_test.c b/test/tx/regression/threadx_thread_multiple_time_slice_test.c new file mode 100644 index 00000000..6e1f61fd --- /dev/null +++ b/test/tx/regression/threadx_thread_multiple_time_slice_test.c @@ -0,0 +1,269 @@ +/* This test is designed to see if two threads can be created and execute with a time-slice. + Thread 7 should run twice as long because it has more of a time-slice. */ + +#include <stdio.h> +#include "tx_api.h" + +static volatile unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static volatile unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; +static volatile unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD +static volatile unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; +static volatile unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; +#endif + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +#endif + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_multiple_time_slice_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 2, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Time-Slice Test...................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 4, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Time-Slice Test...................... ERROR #2\n"); + test_control_return(1); + } + + /* Create control thread. */ + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Time-Slice Test...................... ERROR #3\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Create threads with preemption-threshold and time-slice, such and make sure time-slice is defeated by + preemption-threshold. */ + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 17, 2, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Time-Slice Test...................... ERROR #4\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, 4, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Multiple Thread Time-Slice Test...................... ERROR #5\n"); + test_control_return(1); + } +#endif +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Call thread identify for Win32 test case. */ + tx_thread_identify(); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 1 counter. */ + thread_1_counter++; + + /* Call thread identify for Win32 test case. */ + tx_thread_identify(); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + +unsigned long counter_sum; +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD +UINT status; +#endif + + + /* Inform user. */ + printf("Running Thread Multiple Thread Time-Slice Test...................... "); + + /* Sleep for some multiple of 6. */ + tx_thread_sleep(48); + + /* Increment thread 2 counter. */ + thread_2_counter++; + + /* Compute the delta. Should be twice as much, but some test environments (Windows/Linux) are + not as good in terms of real time processing. */ + counter_sum = thread_0_counter; + counter_sum = counter_sum + (thread_0_counter/4); + if (thread_1_counter <= counter_sum) + { + + /* Thread Time-slice error. */ + printf("ERROR #6\n"); + test_control_return(1); + } +#ifdef TX_DISABLE_PREEMPTION_THRESHOLD + else + { + /* Successful Thread Time-slice test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +#else + /* Now suspend threads 0 and 1 so we can let 3 and 4 run. */ + status = tx_thread_suspend(&thread_0); + status += tx_thread_suspend(&thread_1); + + /* Check status. */ + if (status) + { + /* Thread Time-slice error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Now sleep and see if thread 4 ever runs. */ + tx_thread_sleep(4); + + /* Determine if thread 3 ran and thread 4 didn't. */ + if ((thread_3_counter) && (thread_4_counter == 0)) + { + /* Successful Thread Time-slice test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } + else + { + + /* Thread Time-slice error. */ + printf("ERROR #8\n"); + test_control_return(1); + } +#endif +} + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + +/* Define the test threads. */ + +static void thread_3_entry(ULONG thread_input) +{ + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 3 counter. */ + thread_3_counter++; + + /* Call thread identify for Win32 test case. */ + tx_thread_identify(); + } +} + + +static void thread_4_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* We should never get here! */ + + /* Increment thread 4 counter. */ + thread_4_counter++; + + /* Call thread identify for Win32 test case. */ + tx_thread_identify(); + } +} +#endif + diff --git a/test/tx/regression/threadx_thread_preemptable_suspension_test.c b/test/tx/regression/threadx_thread_preemptable_suspension_test.c new file mode 100644 index 00000000..b1c1bc52 --- /dev/null +++ b/test/tx/regression/threadx_thread_preemptable_suspension_test.c @@ -0,0 +1,416 @@ +/* This test is designed to see if multiple threads can be created and suspended. + The order the suspension and resumption occurs makes sure everything is working right. + All the counters should increment at the same rate. This test differs from test 4 in + that thread 5 is preemptable. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + +static unsigned long thread_4_counter = 0; +static TX_THREAD thread_4; + +static unsigned long thread_5_counter = 0; +static TX_THREAD thread_5; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); +static void thread_5_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_preemptable_suspension_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + /* Create thread 0. */ + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 13, 13, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Suspend/Resume W/Preemption Test..................... ERROR #1\n"); + test_control_return(1); + } + + /* Create thread 1. */ + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Suspend/Resume W/Preemption Test..................... ERROR #2\n"); + test_control_return(1); + } + + /* Create thread 2. */ + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Suspend/Resume W/Preemption Test..................... ERROR #3\n"); + test_control_return(1); + } + + /* Create thread 3. */ + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Suspend/Resume W/Preemption Test..................... ERROR #4\n"); + test_control_return(1); + } + + /* Create thread 4. */ + status = tx_thread_create(&thread_4, "thread 4", thread_4_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Suspend/Resume W/Preemption Test..................... ERROR #5\n"); + test_control_return(1); + } + + /* Create thread 5. Make this thread fully preemptable... */ + status = tx_thread_create(&thread_5, "thread 5", thread_5_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Suspend/Resume W/Preemption Test..................... ERROR #6\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Suspend this thread... */ + tx_thread_suspend(&thread_0); + + /* Resume thread 5... */ + tx_thread_resume(&thread_5); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 1 counter. */ + thread_1_counter++; + + /* Suspend this thread. */ + tx_thread_suspend(&thread_1); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 2 counter. */ + thread_2_counter++; + + /* Suspend this thread. */ + tx_thread_suspend(&thread_2); + } +} + +static void thread_3_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 3 counter. */ + thread_3_counter++; + + /* Suspend this thread. */ + tx_thread_suspend(&thread_3); + } +} + +static void thread_4_entry(ULONG thread_input) +{ + + + /* Enter into a forever loop. */ + while(1) + { + + /* Increment thread 4 counter. */ + thread_4_counter++; + + /* Suspend this thread. */ + tx_thread_suspend(&thread_4); + } +} + +static void thread_5_entry(ULONG thread_input) +{ + +UINT status; + + /* Inform user. */ + printf("Running Thread Suspend/Resume W/Preemption Test..................... "); + + /* Determine if all the other threads are in a suspended state. */ + if ((thread_0.tx_thread_state != TX_SUSPENDED) || (thread_1.tx_thread_state != TX_SUSPENDED) || + (thread_2.tx_thread_state != TX_SUSPENDED) || (thread_3.tx_thread_state != TX_SUSPENDED) || + (thread_4.tx_thread_state != TX_SUSPENDED)) + { + + /* Thread Suspend error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Make sure that each thread has run once. */ + if ((thread_0_counter != 1) || (thread_1_counter != 1) || + (thread_2_counter != 1) || (thread_3_counter != 1) || + (thread_4_counter != 1)) + { + + /* Thread Suspend error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Resume all of the threads. */ + status = tx_thread_resume(&thread_0); + + /* Determine if all the other threads are in the proper state. */ + if ((thread_0.tx_thread_state != TX_SUSPENDED) || (thread_1.tx_thread_state != TX_SUSPENDED) || + (thread_2.tx_thread_state != TX_SUSPENDED) || (thread_3.tx_thread_state != TX_SUSPENDED) || + (thread_4.tx_thread_state != TX_SUSPENDED) || (status != TX_SUCCESS)) + { + + /* Thread Suspend error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Make sure that each thread has run the proper amount. */ + if ((thread_0_counter != 2) || (thread_1_counter != 1) || + (thread_2_counter != 1) || (thread_3_counter != 1) || + (thread_4_counter != 1)) + { + + /* Thread Suspend error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + status = tx_thread_resume(&thread_1); + + /* Determine if all the other threads are in the proper state. */ + if ((thread_0.tx_thread_state != TX_SUSPENDED) || (thread_1.tx_thread_state != TX_SUSPENDED) || + (thread_2.tx_thread_state != TX_SUSPENDED) || (thread_3.tx_thread_state != TX_SUSPENDED) || + (thread_4.tx_thread_state != TX_SUSPENDED) || (status != TX_SUCCESS)) + { + + /* Thread Suspend error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Make sure that each thread has run the proper amount. */ + if ((thread_0_counter != 2) || (thread_1_counter != 2) || + (thread_2_counter != 1) || (thread_3_counter != 1) || + (thread_4_counter != 1)) + { + + /* Thread Suspend error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + status = tx_thread_resume(&thread_2); + + /* Determine if all the other threads are in the proper state. */ + if ((thread_0.tx_thread_state != TX_SUSPENDED) || (thread_1.tx_thread_state != TX_SUSPENDED) || + (thread_2.tx_thread_state != TX_SUSPENDED) || (thread_3.tx_thread_state != TX_SUSPENDED) || + (thread_4.tx_thread_state != TX_SUSPENDED) || (status != TX_SUCCESS)) + { + + /* Thread Suspend error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Make sure that each thread has the proper amount. */ + if ((thread_0_counter != 2) || (thread_1_counter != 2) || + (thread_2_counter != 2) || (thread_3_counter != 1) || + (thread_4_counter != 1)) + { + + /* Thread Suspend error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + status = tx_thread_resume(&thread_3); + + /* Determine if all the other threads are in the proper state. */ + if ((thread_0.tx_thread_state != TX_SUSPENDED) || (thread_1.tx_thread_state != TX_SUSPENDED) || + (thread_2.tx_thread_state != TX_SUSPENDED) || (thread_3.tx_thread_state != TX_SUSPENDED) || + (thread_4.tx_thread_state != TX_SUSPENDED) || (status != TX_SUCCESS)) + { + + /* Thread Suspend error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Make sure that each thread has run the proper amount. */ + if ((thread_0_counter != 2) || (thread_1_counter != 2) || + (thread_2_counter != 2) || (thread_3_counter != 2) || + (thread_4_counter != 1)) + { + + /* Thread Suspend error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + status = tx_thread_resume(&thread_4); + + /* Determine if all the other threads are in the proper state. */ + if ((thread_0.tx_thread_state != TX_SUSPENDED) || (thread_1.tx_thread_state != TX_SUSPENDED) || + (thread_2.tx_thread_state != TX_SUSPENDED) || (thread_3.tx_thread_state != TX_SUSPENDED) || + (thread_4.tx_thread_state != TX_SUSPENDED) || (status != TX_SUCCESS)) + { + + /* Thread Suspend error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Make sure that each thread has run once. */ + if ((thread_0_counter != 2) || (thread_1_counter != 2) || + (thread_2_counter != 2) || (thread_3_counter != 2) || + (thread_4_counter != 2)) + { + + /* Thread Suspend error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Relinquish - this should not do anything! */ + tx_thread_relinquish(); + + /* Determine if all the other threads are in a suspended state. */ + if ((thread_0.tx_thread_state != TX_SUSPENDED) || (thread_1.tx_thread_state != TX_SUSPENDED) || + (thread_2.tx_thread_state != TX_SUSPENDED) || (thread_3.tx_thread_state != TX_SUSPENDED) || + (thread_4.tx_thread_state != TX_SUSPENDED)) + { + + /* Thread Suspend error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Make sure that each thread has run twice. */ + if ((thread_0_counter != 2) || (thread_1_counter != 2) || + (thread_2_counter != 2) || (thread_3_counter != 2) || + (thread_4_counter != 2)) + { + + /* Thread Suspend error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Increment thread 5 counter. */ + thread_5_counter++; + + /* Successful Thread Suspend test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} diff --git a/test/tx/regression/threadx_thread_preemption_change_test.c b/test/tx/regression/threadx_thread_preemption_change_test.c new file mode 100644 index 00000000..1633ef92 --- /dev/null +++ b/test/tx/regression/threadx_thread_preemption_change_test.c @@ -0,0 +1,363 @@ +/* This test is designed to test the change preemption service call. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_initialize.h" + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD +static unsigned long thread_0_counter = 0; +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static TX_MUTEX mutex_0; +#endif + +static TX_THREAD thread_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_preemption_change_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Preemption Change Test............................... ERROR #1\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD /* skip this test and pretend it passed */ + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Preemption Change Test............................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 14, 14, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Preemption Change Test............................... ERROR #3\n"); + test_control_return(1); + } + + status = tx_mutex_create(&mutex_0, "mutex 0", TX_INHERIT); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Preemption Change Test............................... ERROR #4\n"); + test_control_return(1); + } +#endif +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD +UINT old_threshold; +UINT status; +UINT i; +#endif + + + /* Inform user. */ + printf("Running Thread Preemption Change Test............................... "); + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD /* skip this test and pretend it passed */ + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Resume thread 1, which has a higher priority. Preemption is disabled + though so thread 1 should not run yet. */ + status = tx_thread_resume(&thread_1); + + /* Check status and run counters of other threads. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 0) || (thread_2_counter != 0)) + { + + /* Thread error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Change the preemption-threshold such that thread 1 doesn't run yet... just for code coverage. */ + status = tx_thread_preemption_change(&thread_0, 15, &old_threshold); + + /* Change the preemption threshold. This should cause thread 1 to execute! */ + status += tx_thread_preemption_change(&thread_0, 16, &old_threshold); + + /* Check status and run counters of other threads. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 0) || + (old_threshold != 15)) + { + + /* Thread error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Change the preemption threshold of another thread. */ + status = tx_thread_preemption_change(&thread_2, 11, &old_threshold); + + /* Check status and run counters of other threads. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 0) || + (old_threshold != 14)) + { + + /* Thread error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Change the preemption threshold back to 15. */ + status = tx_thread_preemption_change(&thread_0, 15, &old_threshold); + + /* Check status and run counters of other threads. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 0) || + (old_threshold != 16)) + { + + /* Thread error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Resume thread 2. This should preempt because it is priority 14 and the + current preemption threshold is 15. */ + status = tx_thread_resume(&thread_2); + + /* Check status and run counters of other threads. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 1)) + { + + /* Thread error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* At this point, we are going to loop through preemption changes that result in + preemption. */ + for (i = 0; i < (TX_THREAD_EXECUTE_LOG_SIZE*3); i++) + { + + /* Change the preemption threshold back to 14. */ + status = tx_thread_preemption_change(&thread_0, 14, &old_threshold); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Thread error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Resume thread 2 again. */ + status = tx_thread_resume(&thread_2); + + /* Check status an thread 2 run counter. */ + if ((status != TX_SUCCESS) && (thread_2_counter != (i+1))) + { + + /* Thread error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Change the preemption threshold back to 15 to allow thread 2 to run. */ + status = tx_thread_preemption_change(&thread_0, 15, &old_threshold); + + /* Check status an thread 2 run counter. */ + if ((status != TX_SUCCESS) && (thread_2_counter != (i+2))) + { + + /* Thread error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + } + + /* Change the priority of threads 0 and 1. */ + status = tx_thread_priority_change(&thread_0, 7, &old_threshold); + status += tx_thread_priority_change(&thread_1, 5, &old_threshold); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Thread error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Change the preemption-threshold of this thread. */ + status = tx_thread_preemption_change(&thread_0, 0, &old_threshold); + + /* Check status. */ + if ((status != TX_SUCCESS) || (old_threshold != 7)) + { + + /* Thread error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Get the mutex that has priority inheritance. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Thread error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Resume thread 1 so that it can suspend on the mutex and automatically raise its priority. */ + tx_thread_resume(&thread_1); + + /* Self suspend so that thread 1 and run. */ + tx_thread_suspend(&thread_0); + + /* Restore the preemption-threshold of this thread. */ + status = tx_thread_preemption_change(&thread_0, old_threshold, &old_threshold); + + /* Check status. */ + if ((status != TX_SUCCESS) || (old_threshold != 0) || (thread_0.tx_thread_priority != 5) || (thread_0.tx_thread_preempt_threshold != 5)) + { + + /* Thread error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Let thread 1 run again so it can release the mutex and undo the priority inheritance. */ + status = tx_mutex_put(&mutex_0); + + /* Check status. */ + if ((status != TX_SUCCESS) || (thread_0.tx_thread_priority != 7) || (thread_0.tx_thread_preempt_threshold != 7)) + { + + /* Thread error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Test direct call to the thread preemption change routine with a threshold greater than the current priority. */ + status = _tx_thread_preemption_change(&thread_0, 8, &old_threshold); + + /* Check status. */ + if (status != TX_THRESH_ERROR) + { + + /* Thread error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + +#endif + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + +} + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD +static void thread_1_entry(ULONG thread_input) +{ + + /* Self suspend after initial run. */ + tx_thread_suspend(&thread_1); + + /* Increment the thread counter. */ + thread_1_counter++; + + /* Self suspend. */ + tx_thread_suspend(&thread_1); + + /* Resume thread 0. */ + tx_thread_resume(&thread_0); + + /* Get the mutex, which will cause suspension. */ + tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Release the mutex. */ + tx_mutex_put(&mutex_0); +} + + +static void thread_2_entry(ULONG thread_input) +{ + + while(1) + { + + /* Increment thread counter. */ + thread_2_counter++; + + /* Self suspend. */ + tx_thread_suspend(&thread_2); + } +} +#endif diff --git a/test/tx/regression/threadx_thread_priority_change.c b/test/tx/regression/threadx_thread_priority_change.c new file mode 100644 index 00000000..a7649b8e --- /dev/null +++ b/test/tx/regression/threadx_thread_priority_change.c @@ -0,0 +1,378 @@ +/* This test is designed to test the change priority service call. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_thread.h" + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static TX_THREAD thread_3; +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_4; +static unsigned long thread_4_counter = 0; + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); +static void thread_4_entry(ULONG thread_input); + + +extern unsigned long _tx_thread_priority_map; + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + +UINT saved_preempt_disable; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Determine if we have the interrupt condition we are looking for. */ + if ((thread_3.tx_thread_priority == 6) && + (thread_3.tx_thread_state == TX_READY) && + (_tx_thread_priority_list[6] != &thread_3) && + (thread_3_counter > 100)) + { + + /* Save the preempt disable flag. */ + saved_preempt_disable = _tx_thread_preempt_disable; + + /* Clear the preempt disable flag to ensure the API works correctly. */ + _tx_thread_preempt_disable = 0; + + /* Suspend the thread to generate the condition. */ + tx_thread_suspend(&thread_3); + + /* Restore the preempt disable flag. */ + _tx_thread_preempt_disable = saved_preempt_disable; + + /* Done trying to generate this test condition. */ + test_isr_dispatch = TX_NULL; + } +#else + + /* Can't get the interrupt inside the code wit TX_NOT_INTERRUPTABLE defined, so simply stop after thread_3_counter > 100. */ + if (thread_3_counter > 100) + { + + /* Done trying to generate this test condition. */ + test_isr_dispatch = TX_NULL; + } +#endif +} + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_priority_change_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Priority Change Test................................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 22, 22, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Priority Change Test................................. ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 30, 1, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 5, 5, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4, + pointer, TEST_STACK_SIZE_PRINTF, + 6, 6, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Priority Change Test................................. ERROR #3\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +//ULONG current_time; +UINT old_priority; +UINT status; + + + /* Inform user. */ + printf("Running Thread Priority Change Test................................. "); + + /* Resume thread 3. */ + tx_thread_resume(&thread_3); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Change priority to 22, to match that of the next highest priority ready thread. + This is to test the update of the priority list when a thread is moved to a + priority with already ready threads. */ + status = tx_thread_priority_change(&thread_0, 22, &old_priority); + + /* Check status, return priority, and run count of other thread. */ + if ((status != TX_SUCCESS) || (old_priority != 16) || (thread_1_counter != 0)) + { + + /* Thread error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Restore original priority. */ + tx_thread_priority_change(&thread_0, old_priority, &old_priority); + + /* See if we can change priority of this thread. */ + status = tx_thread_priority_change(&thread_0, 7, &old_priority); + + /* Check status, return priority, and run count of other thread. */ + if ((status != TX_SUCCESS) || (old_priority != 16) || (thread_1_counter != 0)) + { + + /* Thread error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* See if we can change priority of another ready thread. */ + status = tx_thread_priority_change(&thread_1, 21, &old_priority); + + /* Check status, return priority, and run count of other thread. */ + if ((status != TX_SUCCESS) || (old_priority != 22) || (thread_1_counter != 0)) + { + + /* Thread error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* See if we can cause preemption by lowering this thread's priority. */ + status = tx_thread_priority_change(&thread_0, 22, &old_priority); + + /* Check status, return priority, and run count of other thread. */ + if ((status != TX_SUCCESS) || (old_priority != 7) || (thread_1_counter != 1)) + { + + /* Thread error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Thread 1 should have run already... Raise this threads priority + back up. */ + status = tx_thread_priority_change(&thread_0, 8, &old_priority); + + /* Check status, return priority, and run count of other thread. */ + if ((status != TX_SUCCESS) || (old_priority != 22) || (thread_1_counter != 1)) + { + + /* Thread error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* See if we can change the priority of a suspended thread. */ + status = tx_thread_priority_change(&thread_1, 19, &old_priority); + + /* Check status, return priority, and run count of other thread. */ + if ((status != TX_SUCCESS) || (old_priority != 21) || (thread_1_counter != 1)) + { + + /* Thread error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Resume the suspended thread so it is in a ready condition. */ + status = tx_thread_resume(&thread_1); + + /* Check status, return priority, and run count of other thread. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1)) + { + + /* Thread error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Should not have run yet. Raise its priority to 8 still should not run yet! */ + status = tx_thread_priority_change(&thread_1, 8, &old_priority); + + /* Check status, return priority, and run count of other thread. */ + if ((status != TX_SUCCESS) || (old_priority != 19) || (thread_1_counter != 1)) + { + + /* Thread error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Raise its priority to 7, now it should run. */ + status = tx_thread_priority_change(&thread_1, 7, &old_priority); + + /* Check status, return priority, and run count of other thread. */ + if ((status != TX_SUCCESS) || (old_priority != 8) || (thread_1_counter != 2) || (thread_2_counter != 0)) + { + + /* Thread error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Now thread 1 should be suspended. Let's change thread 0's priority and make sure thread 2 doesn't run yet! */ + status = tx_thread_priority_change(&thread_0, 7, &old_priority); + + /* Check status, return priority, and run count of other thread. */ + if ((status != TX_SUCCESS) || (old_priority != 8) || (thread_1_counter != 2) || (thread_2_counter != 0)) + { + + /* Thread error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + +static void thread_1_entry(ULONG thread_input) +{ + + while(1) + { + + /* Increment the thread counter. */ + thread_1_counter++; + + /* Suspend self and wait for upper thread to resume. */ + tx_thread_suspend(&thread_1); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + + while(1) + { + + /* This thread should never run! */ + + /* Increment the thread counter. */ + thread_2_counter++; + + /* Self suspend. */ + tx_thread_suspend(&thread_2); + } +} + + +static void thread_3_entry(ULONG thread_input) +{ + +UINT old_priority; +UINT loop; + + + /* Resume threads 4. */ + tx_thread_resume(&thread_4); + + /* Setup the ISR. */ + test_isr_dispatch = test_isr; + do + { + + loop = rand() % 100; + while (loop--) + { + thread_3_counter++; + } + + /* Raise priority of thread 3 for code coverage. */ + tx_thread_priority_change(&thread_3, 6, &old_priority); + tx_thread_priority_change(&thread_3, 5, &old_priority); + + /* Check to see if thread 4 has run... it should not have executed + yet. If it does, set the thread_1_counter to indicate an error! */ + if (thread_4_counter) + thread_1_counter++; + + } while (test_isr_dispatch); +} + + +static void thread_4_entry(ULONG thread_input) +{ + thread_4_counter++; +} + diff --git a/test/tx/regression/threadx_thread_relinquish_test.c b/test/tx/regression/threadx_thread_relinquish_test.c new file mode 100644 index 00000000..e8b4ada7 --- /dev/null +++ b/test/tx/regression/threadx_thread_relinquish_test.c @@ -0,0 +1,193 @@ +/* This test is designed to see if multiple threads can be created and relinquish control between them. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static unsigned long thread_3_counter = 0; +static TX_THREAD thread_3; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_relinquish_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + /* Create thread 0. */ + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Relinquish Test...................................... ERROR #1\n"); + test_control_return(1); + } + + /* Create thread 1. */ + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Relinquish Test...................................... ERROR #2\n"); + test_control_return(1); + } + + /* Create thread 2. */ + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Relinquish Test...................................... ERROR #3\n"); + test_control_return(1); + } + + /* Create thread 3. */ + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Relinquish Test...................................... ERROR #4\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + + /* Check for correct input value and execution of other threads. */ + if ((thread_input != 0) || (thread_1_counter) || (thread_2_counter) || + (thread_3_counter)) + return; + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Relinquish to other thread(s). */ + tx_thread_relinquish(); +} + + +static void thread_1_entry(ULONG thread_input) +{ + + /* Check for correct input value and execution of other threads. */ + if ((thread_input != 1) || (thread_0_counter != 1) || (thread_2_counter) || + (thread_3_counter)) + return; + + /* Increment thread 1 counter. */ + thread_1_counter++; + + /* Relinquish to other thread(s). */ + tx_thread_relinquish(); +} + + +static void thread_2_entry(ULONG thread_input) +{ + + /* Check for correct input value and execution of other threads. */ + if ((thread_input != 2) || (thread_0_counter != 1) || (thread_1_counter != 1) || + (thread_3_counter)) + return; + + /* Increment thread 2 counter. */ + thread_2_counter++; + + /* Relinquish to other thread(s). */ + tx_thread_relinquish(); +} + + +static void thread_3_entry(ULONG thread_input) +{ + + /* Inform user. */ + printf("Running Thread Relinquish Test...................................... "); + + /* Check for correct input value and execution of other threads. */ + if ((thread_input != 3) || (thread_0_counter != 1) || (thread_1_counter != 1) || + (thread_2_counter != 1) || (thread_0.tx_thread_state != TX_READY) || + (thread_1.tx_thread_state != TX_READY) || (thread_2.tx_thread_state != TX_READY)) + return; + + /* Increment thread 3 counter. */ + thread_3_counter++; + + /* Immediate response relinquish. */ + tx_thread_relinquish(); + + /* All other threads should be completed now. */ + if ((thread_0.tx_thread_state != TX_COMPLETED) || (thread_1.tx_thread_state != TX_COMPLETED) || + (thread_2.tx_thread_state != TX_COMPLETED)) + { + + /* Thread Relinquish error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Execute immediate response relinquish. */ + tx_thread_relinquish(); + + /* Successful thread relinquish test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + diff --git a/test/tx/regression/threadx_thread_reset_test.c b/test/tx/regression/threadx_thread_reset_test.c new file mode 100644 index 00000000..ff3531a5 --- /dev/null +++ b/test/tx/regression/threadx_thread_reset_test.c @@ -0,0 +1,248 @@ +/* This test is designed to test the tx_thread_reset function. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_thread.h" + + +static unsigned long thread_0_counter = 0; +static unsigned long thread_0_enter = 0; +static unsigned long thread_0_exit = 0; +static unsigned long thread_1_counter = 0; +static unsigned long thread_2_counter = 0; + + +static TX_THREAD thread_0; +static TX_THREAD thread_1; +static TX_THREAD thread_2; + + +/* Define task prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void entry_exit_notify(TX_THREAD *thread_ptr, UINT type) +{ + + /* Check for the appropriate thread. */ + if (thread_ptr != &thread_0) + return; + + /* Check for type. */ + if (type == TX_THREAD_ENTRY) + thread_0_enter++; + else if (type == TX_THREAD_EXIT) + thread_0_exit++; +} + + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_reset_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Setup the notify call to test that logic. */ + status += tx_thread_entry_exit_notify(&thread_0, entry_exit_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Reset Test........................................... ERROR #1\n"); + test_control_return(1); + } + +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Thread Reset Test........................................... ERROR #2\n"); + test_control_return(1); + } + +#endif + + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Reset Test........................................... ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Reset Test........................................... ERROR #4\n"); + test_control_return(1); + } +} + + + +/* Define the test thread. */ + +static void thread_0_entry(ULONG thread_input) +{ + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Fall through to the return in order to place the thread in a finished + state. */ +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Thread Reset Test........................................... "); + + /* Increment thread 1 counter. */ + thread_1_counter++; + + /* Attempt to delete thread 2, which is in the wrong stat for deleting. */ + status = tx_thread_delete(&thread_2); + + /* Check for the proper status. */ + if (status != TX_DELETE_ERROR) + { + + /* Thread delete error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Determine if the first Thread has run and if it's current state is + finished. */ + if ((thread_0.tx_thread_state != TX_COMPLETED) || (thread_0_counter != 1) || +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + (thread_0_enter != 1) || (thread_0_exit != 1) || (thread_2_counter != 0)) +#else + (thread_0_enter != 0) || (thread_0_exit != 0) || (thread_2_counter != 0)) +#endif + { + + /* Thread reset error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Call thread reset on thread 2, which should result in an error. */ + status = tx_thread_reset(&thread_2); + + /* Check for proper status. */ + if (status != TX_NOT_DONE) + { + + /* Thread reset error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Now call the thread reset function on thread 0. */ + status = tx_thread_reset(&thread_0); + + /* Determine if the first Thread has been reset but not executed. */ + if ((thread_0.tx_thread_state != TX_SUSPENDED) || (thread_0_counter != 1) || +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + (thread_0_enter != 1) || (thread_0_exit != 1) || (thread_2_counter != 0)) +#else + (thread_0_enter != 0) || (thread_0_exit != 0) || (thread_2_counter != 0)) +#endif + { + + /* Thread reset error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Terminate thread 0. */ + status = tx_thread_terminate(&thread_0); + status += tx_thread_reset(&thread_0); + + + /* Now resume thread 0 to let it run. */ + status += tx_thread_resume(&thread_0); + + /* Determine if the first Thread has run and if it's current state is + finished. */ + if ((thread_0.tx_thread_state != TX_COMPLETED) || (thread_0_counter != 2) || +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + (thread_0_enter != 2) || (thread_0_exit != 3) || (thread_2_counter != 0)) +#else + (thread_0_enter != 0) || (thread_0_exit != 0) || (thread_2_counter != 0)) +#endif + { + + /* Thread reset error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + else + { + + + /* Successful thread finish test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_2_entry(ULONG thread_input) +{ + + /* Increment thread 2 counter. */ + thread_2_counter++; + + /* Fall through to the return in order to place the thread in a finished + state. */ +} diff --git a/test/tx/regression/threadx_thread_simple_sleep_non_clear_test.c b/test/tx/regression/threadx_thread_simple_sleep_non_clear_test.c new file mode 100644 index 00000000..f406924c --- /dev/null +++ b/test/tx/regression/threadx_thread_simple_sleep_non_clear_test.c @@ -0,0 +1,92 @@ +/* This test is designed to test a simple sleep for 18 ticks, with something in the + remaining field of the thread control block. */ + +#include <stdio.h> +#include "tx_api.h" + +//static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_simple_sleep_non_clear_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Place a 1 in the thread control block to simulate a control block created in + random memory. */ + thread_0.tx_thread_timer.tx_timer_internal_re_initialize_ticks = 1; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Sleep with non-zero TX_THREAD........................ ERROR #1\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ +ULONG now; + + + /* Inform user. */ + printf("Running Thread Sleep with non-zero TX_THREAD........................ "); + + /* Clear the tick count. */ + tx_time_set(0); + + /* Sleep for 18 ticks. */ + tx_thread_sleep(9); + tx_thread_sleep(9); + + /* Determine if the sleep was accurate. */ + now = tx_time_get(); + if ((now == 18) || + (now == 19)) + { + + /* Successful Simple Sleep test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } + else + { + + /* Thread Simple Sleep error. */ + printf("ERROR #2, now = %lu\n", now); + test_control_return(1); + } +} + diff --git a/test/tx/regression/threadx_thread_simple_sleep_test.c b/test/tx/regression/threadx_thread_simple_sleep_test.c new file mode 100644 index 00000000..6b7afbe1 --- /dev/null +++ b/test/tx/regression/threadx_thread_simple_sleep_test.c @@ -0,0 +1,87 @@ +/* This test is designed to test a simple sleep for 18 ticks. */ + +#include <stdio.h> +#include "tx_api.h" + +//static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_simple_sleep_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Simple Sleep for 18 Ticks Test....................... ERROR #1\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ +ULONG now; + + + /* Inform user. */ + printf("Running Thread Simple Sleep for 18 Ticks Test....................... "); + + /* Clear the tick count. */ + tx_time_set(0); + + /* Sleep for 18 ticks. */ + tx_thread_sleep(18); + + /* Determine if the sleep was accurate. */ + now = tx_time_get(); + if ((now == 18) || + (now == 19)) + { + + /* Successful Simple Sleep test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } + else + { + + /* Thread Simple Sleep error. */ + printf("ERROR #2, now = %lu\n", now); + test_control_return(1); + } +} + diff --git a/test/tx/regression/threadx_thread_simple_suspend_test.c b/test/tx/regression/threadx_thread_simple_suspend_test.c new file mode 100644 index 00000000..52215a75 --- /dev/null +++ b/test/tx/regression/threadx_thread_simple_suspend_test.c @@ -0,0 +1,116 @@ +/* This test is designed to see if a thread can successfully suspend itself in a single + thread system. This also tests a thread created that is not automatically enabled. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static TX_THREAD thread_1; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_simple_supsend_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Simple Suspend Test.................................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Simple Suspend Test.................................. ERROR #2\n"); + test_control_return(1); + } +} + + + +/* Define the test thread. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + /* Resume the test control thread. */ + status = tx_thread_resume(&thread_1); + + /* Check status. */ + if (status != TX_SUCCESS) + return; + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Suspend the running thread. */ + tx_thread_suspend(&thread_0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + + /* Inform user. */ + printf("Running Thread Simple Suspend Test.................................. "); + + /* The other thread should be in a suspended state now. */ + if ((thread_0.tx_thread_state != TX_SUSPENDED) || (thread_0_counter != 1)) + { + + /* Thread Suspend error. */ + printf("ERROR #3\n"); + test_control_return(1); + } + else + { + + /* Successful Thread Suspend test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + diff --git a/test/tx/regression/threadx_thread_sleep_for_100ticks_test.c b/test/tx/regression/threadx_thread_sleep_for_100ticks_test.c new file mode 100644 index 00000000..69eadbc6 --- /dev/null +++ b/test/tx/regression/threadx_thread_sleep_for_100ticks_test.c @@ -0,0 +1,435 @@ +/* This test is designed to test a simple sleep for 100 ticks. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" + +//#define DEBUG + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + + +static TX_THREAD thread_0; + +static int error = 0; + +static int isr_count = 0; + +#ifdef TEST_INTERRUPT_CONDITION +#ifndef TX_NOT_INTERRUPTABLE + +#if defined(TX_WIN32_MEMORY_SIZE) || defined(TX_LINUX_MEMORY_SIZE) +/* Use larger array size when running on Win32 test platform because of greater speed. */ +#define ARRAY_SIZE 100 +#else +#define ARRAY_SIZE 10 +#endif + + +static UINT isr_test_suspend_interrupt = TX_TRUE; +static UINT isr_test_suspend_interrupted_condition = TX_FALSE; +static ULONG min_loop_count; +static ULONG max_loop_count; +static TX_SEMAPHORE test_semaphore; +static ULONG loop_count; +static volatile ULONG count; +static volatile ULONG destination = 0; +static ULONG array_delay[ARRAY_SIZE]; +static ULONG start_time; +static ULONG lower_bound; +static ULONG upper_bound; +static ULONG current_itterations; +#ifdef DEBUG_1 +static ULONG last_loop_count; +#endif +static ULONG delay_function(void) +{ + +ULONG accumulator; +ULONG i; + + for (i = 0; i < ARRAY_SIZE; i++) + array_delay[i] = i; + + for (i = 0; i < ARRAY_SIZE-4; i++) + { + array_delay[i] = (array_delay[i+1] * array_delay[i+2]) * (array_delay[i+3] * array_delay[i+4]); + } + + accumulator = 0; + for (i = 0; i < ARRAY_SIZE; i++) + accumulator = accumulator + array_delay[i]; + + return(accumulator); +} + +#endif +#endif + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + +UINT status; + +#ifdef TEST_INTERRUPT_CONDITION +#ifndef TX_NOT_INTERRUPTABLE +ULONG i; + + /* Determine if we are in calibration mode. */ + if ((loop_count) && (loop_count != 0xFFFFFFFF)) + { + if (loop_count < min_loop_count) + min_loop_count = loop_count; + if (loop_count > max_loop_count) + max_loop_count = loop_count; + + lower_bound = loop_count - 1; + upper_bound = loop_count + 1; + if (lower_bound < min_loop_count) + lower_bound = min_loop_count; + if (upper_bound > max_loop_count) + lower_bound = max_loop_count; + + if ((current_itterations < lower_bound) || (current_itterations > upper_bound)) + current_itterations = lower_bound; + +#ifdef DEBUG_1 + /* Last loop count. */ + last_loop_count = loop_count; +#endif + + /* Reset the loop count to all ones! */ + loop_count = 0xFFFFFFFF; + } + count++; + for (i = 0; i < (count%32); i++) + destination++; + + /* Determine if the ISR is in the mode to wakeup the thread suspending with a timeout. */ + if (isr_test_suspend_interrupt) + { + + /* Determine if the thread is suspended on the semaphore... */ + if (thread_0.tx_thread_state == TX_SEMAPHORE_SUSP) + { + + /* Determine if the test condition is present... */ + if ((_tx_thread_preempt_disable) && + (thread_0.tx_thread_timer.tx_timer_internal_list_head == TX_NULL)) + { + + /* Set the flag showing the condition is present. */ + isr_test_suspend_interrupted_condition = TX_TRUE; + + /* All done with the test. */ + isr_test_suspend_interrupt = TX_FALSE; + } + + /* Post to the semaphore to wakeup the thread. */ + tx_semaphore_put(&test_semaphore); + } + + return; + } +#endif +#endif + + /* Increment the ISR count. */ + isr_count++; + + /* Call sleep from ISR to check for error! */ + status = tx_thread_sleep(100); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + + error = 1; + } + + /* End the ISR. */ + test_isr_dispatch = TX_NULL; +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_sleep_for_100ticks_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Sleep for 100 Ticks Test............................. ERROR #1\n"); + test_control_return(1); + } + +#ifdef TEST_INTERRUPT_CONDITION +#ifndef TX_NOT_INTERRUPTABLE + + status = tx_semaphore_create(&test_semaphore, "test semaphore", 0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Sleep for 100 Ticks Test............................. ERROR #2\n"); + test_control_return(1); + } + + min_loop_count = 0xFFFFFFFF; + max_loop_count = 0; + loop_count = 0xFFFFFFFF; + current_itterations = 0; +#ifdef DEBUG_1 + last_loop_count = 0x0; +#endif +#endif +#endif +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +#ifdef TEST_INTERRUPT_CONDITION +#ifndef TX_NOT_INTERRUPTABLE +ULONG i; +volatile ULONG value = 0; +#endif +#endif + + /* Inform user. */ + printf("Running Thread Sleep for 100 Ticks Test............................. "); + + /* Call sleep with an expiration of 0 and test error code. */ + status = tx_thread_sleep(0); + + /* Check error code. */ + if (status != TX_SUCCESS) + { + + /* Thread Simple Sleep error. */ + printf("ERROR #3\n"); + test_control_return(1); + } + +#ifdef TEST_INTERRUPT_CONDITION +#ifndef TX_NOT_INTERRUPTABLE + + + isr_test_suspend_interrupt = TX_TRUE; + isr_test_suspend_interrupted_condition = TX_FALSE; +#endif +#endif + + /* Setup the test ISR. */ + test_isr_dispatch = test_isr; + +#ifdef TEST_INTERRUPT_CONDITION +#ifndef TX_NOT_INTERRUPTABLE + + /* Callibrate the loop count from thread sleep. */ + for (i = 0; i < 180; i++) + { + + /* Sleep to get a fresh time. */ + tx_thread_sleep(1); + + /* Set the loop count to 0 and start counting.... */ + loop_count = 0; + start_time = _tx_timer_system_clock; + do + { + + /* Call delay function. */ + delay_function(); + loop_count++; + } while (start_time == _tx_timer_system_clock); + + /* Wait to reset the loop count. */ + tx_thread_sleep(1); + } + +#if 1 + /* Setup the lower and upper bounds. */ + lower_bound = min_loop_count; + if (lower_bound > 5) + lower_bound = lower_bound - 5; + upper_bound = max_loop_count + 5; +#else + /* Setup the lower and upper bounds. */ + lower_bound = min_loop_count; + upper_bound = max_loop_count; +#endif + + current_itterations = lower_bound; +#ifdef DEBUG + i = 0; +#endif + while (isr_test_suspend_interrupted_condition != TX_TRUE) + { + + /* Sleep to get a frest timer slot. */ + tx_thread_sleep(1); + + /* Loop to delay to next interrupt. */ + loop_count = 0; + start_time = _tx_timer_system_clock; + do + { + /* Call delay function. */ + delay_function(); + loop_count++; + } while (loop_count < current_itterations); + + /* Check for a timer interrupt... if so, just skip the semaphore get. */ + if (start_time != _tx_timer_system_clock) + continue; + + /* Suspend on the semaphore for 20 ticks... */ + tx_semaphore_get(&test_semaphore, 20); + + /* Adjust the current itterations. */ + current_itterations++; + if (current_itterations > upper_bound) + { + if (lower_bound > min_loop_count) + lower_bound--; + if (upper_bound < max_loop_count) + upper_bound++; + current_itterations = lower_bound; + } + + /* Set the tick count simply to use value. */ + tx_time_set(value); +#ifdef DEBUG + /* Debug block. */ + i++; + if ((i % 180) == 0) + { + printf("*** update ***\n"); + if (loop_count == 0xFFFFFFFF) + printf("loop count: NA\n"); + else + printf("loop count: %lu\n", loop_count); + printf("current: %lu\n", current_itterations); + printf("last loop count: %lu\n", last_loop_count); + printf("minimum: %lu\n", min_loop_count); + printf("maximum: %lu\n", max_loop_count); + printf("lower bound: %lu\n", lower_bound); + printf("upper bound: %lu\n", upper_bound); + printf("count: %lu\n", i); + } +#endif + } + +#ifdef DEBUG + /* Debug block */ + printf("*** final ***\n"); + if (loop_count == 0xFFFFFFFF) + printf("loop count: NA\n"); + else + printf("loop count: %lu\n", loop_count); + printf("current: %lu\n", current_itterations); + printf("last loop count: %lu\n", last_loop_count); + printf("minimum: %lu\n", min_loop_count); + printf("maximum: %lu\n", max_loop_count); + printf("lower bound: %lu\n", lower_bound); + printf("upper bound: %lu\n", upper_bound); + printf("count: %lu\n", i); +#endif + + /* Clear the tick count. */ + tx_time_set(0); + + /* Sleep for 100 ticks. */ + tx_thread_sleep(100); + + /* Check for error. */ + if (tx_time_get() < 100) + { + + /* Thread Simple Sleep error. */ + printf("ERROR #4\n"); + test_control_return(1); + } +#endif +#endif + + /* Clear the tick count. */ + tx_time_set(0); + + + /* Sleep for 100 ticks. */ + status = tx_thread_sleep(100); + + /* Determine if the sleep was accurate. */ + if ((status != TX_SUCCESS) || (tx_time_get() < 100) || + (tx_time_get() > 101)) + { + + /* Thread Simple Sleep error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Check to make sure the ISR happened and the proper return value was present. */ + if ((isr_count == 0) || (error)) + { + + /* Thread Simple Sleep error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + else + { + + /* Successful Simple Sleep test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + diff --git a/test/tx/regression/threadx_thread_sleep_terminate_test.c b/test/tx/regression/threadx_thread_sleep_terminate_test.c new file mode 100644 index 00000000..871fc6e2 --- /dev/null +++ b/test/tx/regression/threadx_thread_sleep_terminate_test.c @@ -0,0 +1,187 @@ +/* This test is designed to test thread termination of a thread in a sleep condition. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static unsigned long thread_1_counter = 0; +static unsigned long thread_1_enter = 0; +static unsigned long thread_1_exit = 0; +static TX_THREAD thread_1; + +extern UINT _tx_thread_preempt_disable; + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + + +static void entry_exit_notify(TX_THREAD *thread_ptr, UINT type) +{ + + /* Check for the appropriate thread. */ + if (thread_ptr != &thread_1) + return; + + /* Check for type. */ + if (type == TX_THREAD_ENTRY) + thread_1_enter++; + else if (type == TX_THREAD_EXIT) + thread_1_exit++; +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_sleep_terminate_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Suspend Terminate Test............................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Suspend Terminate Test............................... ERROR #2\n"); + test_control_return(1); + } + + /* Setup the notify call to test that logic. */ + status += tx_thread_entry_exit_notify(&thread_1, entry_exit_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Suspend Terminate Test............................... ERROR #3\n"); + test_control_return(1); + } + +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Thread Suspend Terminate Test............................... ERROR #4\n"); + test_control_return(1); + } + +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Thread Suspend Terminate Test............................... "); + + /* Increment run counter. */ + thread_0_counter++; + + /* Sleep to allow lower-priority thread 1 to run. */ + tx_thread_sleep(5); + + /* Now terminate thread 1. */ + status = tx_thread_terminate(&thread_1); + + /* Check status. */ + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (_tx_thread_preempt_disable)) + { + + /* Terminate error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Now try to suspend a terminated thread. */ + status = tx_thread_suspend(&thread_1); + + /* Check status. */ + if (status != TX_SUSPEND_ERROR) + { + + /* Suspend error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + while(1) + { + + /* Increment run counter. */ + thread_1_counter++; + + /* Suspend thread 1. */ + status = tx_thread_sleep(100); + + /* Check status. */ + if (status != TX_SUCCESS) + { + thread_1_counter = 0; /* Make an error! */ + return; + } + } +} + + diff --git a/test/tx/regression/threadx_thread_stack_checking_test.c b/test/tx/regression/threadx_thread_stack_checking_test.c new file mode 100644 index 00000000..3ffe3841 --- /dev/null +++ b/test/tx/regression/threadx_thread_stack_checking_test.c @@ -0,0 +1,224 @@ +/* This test is for the thread stack checking services. */ + +#include <stdio.h> +#include "tx_api.h" + + +/* Prototype for direct call. */ + +VOID _tx_thread_stack_analyze(TX_THREAD *thread_ptr); + + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; +static CHAR *thread_2_stack_start; +static UINT stack_error = 0; + + +/* Define task prototypes. */ + +static void thread_0_entry(ULONG task_input); +static void thread_1_entry(ULONG task_input); +static void thread_2_entry(ULONG task_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define the stack checking error handler. */ + +void stack_error_handler(TX_THREAD *thread_ptr) +{ + + /* Check for the right thread. */ + if (thread_ptr == &thread_2) + stack_error = 1; +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_stack_checking_application_define(void *first_unused_memory) +#endif +{ + +INT status; +CHAR *pointer; + + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Stack Checking Test.................................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Stack Checking Test.................................. ERROR #2\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, TX_NO_TIME_SLICE, TX_DONT_START); + thread_2_stack_start = pointer; + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Stack Checking Test.................................. ERROR #3\n"); + test_control_return(1); + } + + /* Register the stack checking handler. */ + status = tx_thread_stack_error_notify(stack_error_handler); + +#ifdef TX_ENABLE_STACK_CHECKING + /* Check for status. */ + if (status != TX_SUCCESS) +#else + if (status != TX_FEATURE_NOT_ENABLED) +#endif + + { + + printf("Running Thread Stack Checking Test.................................. ERROR #4\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Inform user of success getting to this test. */ + printf("Running Thread Stack Checking Test.................................. "); + + /* Resume thread 1 to get the stack checking to take place. */ + status = tx_thread_resume(&thread_1); + + /* Suspend to allow thread 1 to run. */ + tx_thread_suspend(&thread_0); + + /* Terminate thread 1. */ + status = tx_thread_terminate(&thread_1); + + /* Check error code. */ +#ifdef TX_ENABLE_STACK_CHECKING + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 0) || (stack_error != 1)) +#else + if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 0) || (stack_error != 0)) +#endif + { + + /* Thread error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + else + { + + /* Success! */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +TX_THREAD fake_thread; + + /* Call stack analyze with a NULL pointer. */ + _tx_thread_stack_analyze(TX_NULL); + + /* Call the stack analyze with a fake stack just to test that path. */ + fake_thread.tx_thread_id = 0; + _tx_thread_stack_analyze(&fake_thread); + + /* Call the stack analyze with a NULL stack pointer. */ + fake_thread.tx_thread_id = ((ULONG) 0x54485244); + fake_thread.tx_thread_stack_start = TX_NULL; + _tx_thread_stack_analyze(&fake_thread); + + /* Call the stack analyze with a NULL highest stack pointer. */ + fake_thread.tx_thread_id = ((ULONG) 0x54485244); + fake_thread.tx_thread_stack_start = (void *) 0x1000; + fake_thread.tx_thread_stack_highest_ptr = TX_NULL; + _tx_thread_stack_analyze(&fake_thread); + + /* Clear the pattern in thread 2's stack. */ + TX_MEMSET(thread_2_stack_start, (CHAR) 0x11, TEST_STACK_SIZE_PRINTF); + + /* Resume thread 2, which should cause the stack error to occur. */ + tx_thread_resume(&thread_2); + + /* Suspend thread 2. */ + tx_thread_suspend(&thread_2); + + /* Increment thread 1 counter. */ + thread_1_counter++; + + /* Now, deregister the stack error handler and get into a spin condition. We will then + want to terminate thread 1 from thread 0 when it awakes! */ + tx_thread_stack_error_notify(TX_NULL); + + /* Now resume thread 2 again to cause the stack error! */ + tx_thread_resume(&thread_2); + + /* Now suspend thread 2 again. */ + tx_thread_suspend(&thread_2); + + /* Resume thread 0. */ + tx_thread_resume(&thread_0); +} + + +static void thread_2_entry(ULONG thread_input) +{ + + /* Increment thread 1 counter. */ + thread_2_counter++; +} diff --git a/test/tx/regression/threadx_thread_terminate_delete_test.c b/test/tx/regression/threadx_thread_terminate_delete_test.c new file mode 100644 index 00000000..dbe919f3 --- /dev/null +++ b/test/tx/regression/threadx_thread_terminate_delete_test.c @@ -0,0 +1,341 @@ +/* This test is designed to test thread terminate (self, and other), thread delete, + and thread identify services. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static unsigned long thread_1_enter = 0; +static unsigned long thread_1_exit = 0; +static TX_THREAD thread_1; + +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_2; + +static TX_THREAD thread_3; +static unsigned long thread_3_enter = 0; +static unsigned long thread_3_exit = 0; + + +static TX_SEMAPHORE semaphore_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void thread_2_entry(ULONG thread_input); +static void thread_3_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void entry_exit_notify(TX_THREAD *thread_ptr, UINT type) +{ + + /* Check for the appropriate thread. */ + if (thread_ptr != &thread_1) + return; + + /* Check for type. */ + if (type == TX_THREAD_ENTRY) + thread_1_enter++; + else if (type == TX_THREAD_EXIT) + thread_1_exit++; +} + + +static void entry_exit_notify3(TX_THREAD *thread_ptr, UINT type) +{ + + /* Check for the appropriate thread. */ + if (thread_ptr != &thread_3) + return; + + /* Check for type. */ + if (type == TX_THREAD_ENTRY) + thread_3_enter++; + else if (type == TX_THREAD_EXIT) + thread_3_exit++; +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_terminate_delete_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Terminate and Delete Test............................ ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Terminate and Delete Test............................ ERROR #2\n"); + test_control_return(1); + } + + /* Setup the notify call to test that logic. */ + status = tx_thread_entry_exit_notify(&thread_1, entry_exit_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Terminate and Delete Test............................ ERROR #3\n"); + test_control_return(1); + } + +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Thread Terminate and Delete Test............................ ERROR #4\n"); + test_control_return(1); + } + + +#endif + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Terminate and Delete Test............................ ERROR #5\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3, + pointer, TEST_STACK_SIZE_PRINTF, + 12, 12, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Terminate and Delete Test............................ ERROR #6\n"); + test_control_return(1); + } + + /* Setup the notify call to test that logic. */ + status = tx_thread_entry_exit_notify(&thread_3, entry_exit_notify3); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Terminate and Delete Test............................ ERROR #7\n"); + test_control_return(1); + } + +#else + + /* Check for status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Thread Terminate and Delete Test............................ ERROR #8\n"); + test_control_return(1); + } + +#endif + + + /* Create a semaphore for thread 3 to suspend on. */ + status = tx_semaphore_create(&semaphore_0, "semaphore 0", 0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Terminate and Delete Test............................ ERROR #9\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Thread Terminate and Delete Test............................ "); + + /* Let other threads execute. */ + tx_thread_relinquish(); + + /* Make sure thread 1 is terminated and thread 2 is suspended. */ + if ((thread_1.tx_thread_state != TX_TERMINATED) || +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + (thread_1_enter != 1) || (thread_1_exit != 1) || +#else + (thread_1_enter != 0) || (thread_1_exit != 0) || +#endif + (thread_2.tx_thread_state != TX_SUSPENDED)) + { + + /* Thread error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* At this point, terminate thread 2 which should be in a suspended state + right now. */ + status = tx_thread_terminate(&thread_2); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Thread error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Delete thread 1 (thread 1 alread terminated) and 2. */ + status = tx_thread_delete(&thread_2); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Thread error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + status = tx_thread_delete(&thread_1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Thread error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* At this point, terminate thread 3 which should be in a suspended state + on the semaphore right now. */ + status = tx_thread_terminate(&thread_3); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Thread error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Delete thread 3. */ + status = tx_thread_delete(&thread_3); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Thread error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + +static void thread_1_entry(ULONG thread_input) +{ + + /* Test identity. */ + if (tx_thread_identify() != &thread_1) + return; + + /* Increment the thread counter. */ + thread_1_counter++; + + /* Terminate self. */ + tx_thread_terminate(&thread_1); +} + +static void thread_2_entry(ULONG thread_input) +{ + + /* Test identity. */ + if (tx_thread_identify() != &thread_2) + return; + + /* Increment thread counter. */ + thread_2_counter++; + + /* Suspend thread. */ + tx_thread_suspend(&thread_2); +} + + +static void thread_3_entry(ULONG thread_input) +{ + + /* Get the semaphore with wait forever! */ + tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + /* Increment thread counter. */ + thread_2_counter++; +} + diff --git a/test/tx/regression/threadx_thread_time_slice_change_test.c b/test/tx/regression/threadx_thread_time_slice_change_test.c new file mode 100644 index 00000000..8ee7df3b --- /dev/null +++ b/test/tx/regression/threadx_thread_time_slice_change_test.c @@ -0,0 +1,149 @@ +/* This test is designed to test the change time-slice service call. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +extern unsigned long _tx_timer_time_slice; + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_time_slice_change_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Time-Slice Change Test............................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 22, 22, 200, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Time-Slice Change Test............................... ERROR #2\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +ULONG old_time_slice = 0; + + + /* Inform user. */ + printf("Running Thread Time-Slice Change Test............................... "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Change the time-slice of other thread. */ + status = tx_thread_time_slice_change(&thread_1, 33, &old_time_slice); + + /* Check status and the time sice of specified thread. */ + if ((status != TX_SUCCESS) || (old_time_slice != 200) || (thread_1.tx_thread_new_time_slice != 33)) + { + + /* Thread error. */ + printf("ERROR #3\n"); + test_control_return(1); + } + + /* Sleep to get a fresh timer. */ + tx_thread_sleep(1); + + /* Change the time-slice of this thread. */ + status = tx_thread_time_slice_change(&thread_0, 66, &old_time_slice); + + /* Check status and the time sice of specified thread. */ + if ((status != TX_SUCCESS) || (old_time_slice != 100) || (thread_0.tx_thread_new_time_slice != 66) || + (_tx_timer_time_slice != 66)) + { + + /* Thread error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Change the time-slice of this thread. */ + status = tx_thread_time_slice_change(&thread_1, 2, &old_time_slice); + + /* Sleep for 8 ticks just to allow thread 1 to run and time-slice with no other thread ready. */ + tx_thread_sleep(8); + + if (status != TX_SUCCESS) + { + + /* Thread error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + +static void thread_1_entry(ULONG thread_input) +{ + + while(1) + { + + /* Identify. */ + tx_thread_identify(); + + /* Increment the thread counter. */ + thread_1_counter++; + } +} + diff --git a/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c b/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c new file mode 100644 index 00000000..56fef596 --- /dev/null +++ b/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c @@ -0,0 +1,271 @@ +/* This test is designed to test for simultaneous thread suspension lifting AND thread wait abort calls. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + +static unsigned long timer_0_counter = 0; +static TX_TIMER timer_0; + + +static unsigned long semaphore_put_counter = 0; +static unsigned long condition_count = 0; +extern UINT _tx_timer_system_clock; + +static TX_SEMAPHORE semaphore_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void timer_0_entry(ULONG timer_input); + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +/* Define the external reference for the preempt disable flag. */ + +extern volatile UINT _tx_thread_preempt_disable; + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void isr_entry(void) +{ + +UINT status; +static volatile UINT miss_count = 0; + + + /* Attempt to sleep from a timer in order to test the error logic. */ + status = tx_thread_sleep(1); + + /* Check for proper error status. */ + if (status != TX_CALLER_ERROR) + { + + /* Blow up the test to force an error. */ + condition_count = 10000000; + semaphore_put_counter = 0xFFFF0000; + } + + /* Determine if the interrupt occurred when the preempt disable flag was set. */ + if (_tx_thread_preempt_disable) + { + + /* Yes this is the condition we are looking for, increment the test condition counter. */ + condition_count++; + } + + /* + It is possible for this test to get into a resonance condition in which + the ISR never occurs while preemption is disabled (especially if the + ISR is installed in the periodic timer interrupt handler, which is + conveniently available). Detect this condition and break out of it by + perturbing the duration of this ISR a pseudo-random amount of time. + */ + else if (++miss_count > 100) + for (miss_count = _tx_timer_system_clock % 100; miss_count != 0; --miss_count); + + /* Put the semaphore to wakeup thread 0. */ + status = tx_semaphore_put(&semaphore_0); + + /* Increment the semaphore counter. */ + if (status == TX_SUCCESS) + semaphore_put_counter++; +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_wait_abort_and_isr_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Wait Abort and ISR Resume Test....................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 17, 17, 100, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Wait Abort and ISR Resume Test....................... ERROR #2\n"); + test_control_return(1); + } + + /* Create semaphore - consumer producer semaphore. */ + status = tx_semaphore_create(&semaphore_0, "semaphore 0", 0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Wait Abort and ISR Resume Test....................... ERROR #3\n"); + test_control_return(1); + } + + /* Create a timer to ensure a context save is called for every interrupt. */ + status = tx_timer_create(&timer_0, "timer 0", timer_0_entry, 0, 1, 1, TX_AUTO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Wait Abort and ISR Resume Test....................... ERROR #4\n"); + test_control_return(1); + } + + /* Clear the condition count variable. */ + condition_count = 0; +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Setup ISR for this test. */ + test_isr_dispatch = isr_entry; + + /* Inform user. */ + printf("Running Thread Wait Abort and ISR Resume Test....................... "); + + /* Loop to exploit the probability window inside tx_thread_wait_abort. */ + while (condition_count < 10) + { + + /* Suspend on the semaphore that is going to be set via the ISR. */ + status = tx_semaphore_get(&semaphore_0, (thread_0_counter % 5) + 1); + + /* Determine if we have an unexpected result. */ + if ((status != TX_SUCCESS) && (status != TX_WAIT_ABORTED)) + { + + /* Test error! */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Check for the preempt disable flag being set. */ + if (_tx_thread_preempt_disable) + { + + /* Test error! */ + printf("ERROR #6\n"); + test_control_return(2); + } + + /* Determine if we really got the semaphore. */ + if (status == TX_SUCCESS) + { + + /* Increment the thread count. */ + thread_0_counter++; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Determine if we have a non-interruptable build of ThreadX. If so, just + get out of this loop after 100 passes. */ + + if (thread_0_counter >= 100) + break; +#endif + + } + } + + /* Clear ISR dispatch. */ + test_isr_dispatch = TX_NULL; + +#ifdef TX_NOT_INTERRUPTABLE + /* At this point, check to see if we got all the semaphores! */ + if ((thread_0_counter != (semaphore_put_counter - semaphore_0.tx_semaphore_count)) || + (condition_count != 0)) +#else + /* At this point, check to see if we got all the semaphores! */ + if (thread_0_counter != (semaphore_put_counter - semaphore_0.tx_semaphore_count)) +#endif + { + + /* Test error! */ + printf("ERROR #7\n"); + test_control_return(3); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + + /* Loop forever! */ + while(1) + { + + + /* Abort the suspension on the semaphore in thread 0. */ + tx_thread_wait_abort(&thread_0); + + /* Increment the thread counter. */ + thread_1_counter++; + + /* Let thread 0 run again! */ + tx_thread_relinquish(); + } +} + + +static void timer_0_entry(ULONG input) +{ + timer_0_counter++; +} + diff --git a/test/tx/regression/threadx_thread_wait_abort_test.c b/test/tx/regression/threadx_thread_wait_abort_test.c new file mode 100644 index 00000000..a2e8e42d --- /dev/null +++ b/test/tx/regression/threadx_thread_wait_abort_test.c @@ -0,0 +1,138 @@ +/* This test is designed to test thread wait abort. */ + +#include <stdio.h> +#include "tx_api.h" + +//static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long thread_1_counter = 0; +static TX_THREAD thread_1; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_wait_abort_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Wait Abort Test...................................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Wait Abort Test...................................... ERROR #2\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Thread Wait Abort Test...................................... "); + + /* Let other thread run. */ + tx_thread_resume(&thread_1); + + /* Make sure thread 1 is sleeping. */ + if (thread_1.tx_thread_state != TX_SLEEP) + { + + /* Thread error. */ + printf("ERROR #3\n"); + test_control_return(1); + } + + /* At this point, call tx_thread_wait_abort to abort the sleep in thread1. */ + status = tx_thread_wait_abort(&thread_1); + + /* Check for status. */ + if ((status != TX_SUCCESS) || (thread_1.tx_thread_state != TX_SUSPENDED)) + { + + /* Thread error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + /* Sleep for a long long time. */ + status = tx_thread_sleep(1000000000); + + /* Check for the proper status. */ + if (status != TX_WAIT_ABORTED) + { + + /* Thread error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Increment the thread counter. */ + thread_1_counter++; + + /* Suspend self. */ + tx_thread_suspend(&thread_1); +} + diff --git a/test/tx/regression/threadx_time_get_set_test.c b/test/tx/regression/threadx_time_get_set_test.c new file mode 100644 index 00000000..6bc2ddc1 --- /dev/null +++ b/test/tx/regression/threadx_time_get_set_test.c @@ -0,0 +1,107 @@ +/* This test is designed to test simple tx_time_get and set services. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_time_get_set_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Time Simple Get/Set Test.................................... ERROR #1\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +ULONG current_time; + + + /* Inform user. */ + printf("Running Time Simple Get/Set Test.................................... "); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Sleep for 1 tick to get a fresh timer. */ + tx_thread_sleep(1); + + /* Set time to 0. */ + tx_time_set(0); + + /* Sleep for a couple ticks. */ + tx_thread_sleep(35); + + /* Pickup the current time. */ + current_time = tx_time_get(); + + /* Check Current time. It should be 35. */ + if (current_time != 35) + { + + /* System time error. */ + printf("ERROR #2\n"); + test_control_return(1); + } + + /* Set the new time. */ + tx_time_set(7); + + /* Check the new time. */ + if (tx_time_get() != 7) + { + + /* System time error. */ + printf("ERROR #3\n"); + test_control_return(1); + } + else + { + + /* Successful time test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + diff --git a/test/tx/regression/threadx_timer_activate_deactivate_test.c b/test/tx/regression/threadx_timer_activate_deactivate_test.c new file mode 100644 index 00000000..a238ea33 --- /dev/null +++ b/test/tx/regression/threadx_timer_activate_deactivate_test.c @@ -0,0 +1,268 @@ +/* This test is designed to test application timer activation/deactivation services + from threads and the activation routines. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_timer.h" + + +static TX_THREAD thread_0; + +static unsigned long timer_0_counter = 0; +static TX_TIMER timer_0; +static TX_TIMER_INTERNAL test_timer; +static TX_TIMER_INTERNAL *list_head; +static TX_TIMER test_app_timer; + +static TX_TIMER timer_2; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void timer_0_expiration(ULONG timer_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_timer_activate_deactivate_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Activate/Deactivate Test.............................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_0, "timer 0", timer_0_expiration, 0x1234, + 13, 23, TX_NO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Activate/Deactivate Test.............................. ERROR #2\n"); + test_control_return(1); + } +} + +VOID _tx_timer_system_activate(TX_TIMER_INTERNAL *timer_ptr); + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +TX_TIMER_INTERNAL **current_list_head; + + + /* Inform user. */ + printf("Running Timer Activate/Deactivate Test.............................. "); + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Call the timer thread entry function with an invalid value to make sure the code simply returns. */ + _tx_timer_thread_entry(0); +#endif + +#ifndef TX_TIMER_PROCESS_IN_ISR + + tx_thread_resume(&_tx_timer_thread); +#endif + + /* Call the internal timer activate function with 0 remaining time. */ + test_timer.tx_timer_internal_remaining_ticks = 0; + _tx_timer_system_activate(&test_timer); + + /* Call the internal timer activate function with an existing head pointer. */ + test_timer.tx_timer_internal_remaining_ticks = 1; + list_head = TX_NULL; + test_timer.tx_timer_internal_list_head = &list_head; + _tx_timer_system_activate(&test_timer); + + /* Call the internal timer deactivate function to ensure the list head is not updated unless valid. */ + list_head = TX_NULL; + test_timer.tx_timer_internal_list_head = &list_head; + test_timer.tx_timer_internal_active_next = &test_timer; + _tx_timer_system_deactivate(&test_timer); + + /* Call timer info get with a timer setup to exercise a path not possible, in order to exercise all + conditionals. */ + test_app_timer.tx_timer_internal.tx_timer_internal_list_head = (_tx_timer_list_end + 1); + status = _tx_timer_info_get(&test_app_timer, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Deactivate and activate the timer. */ + test_app_timer.tx_timer_internal.tx_timer_internal_active_next = &test_app_timer.tx_timer_internal; + status += _tx_timer_deactivate(&test_app_timer); + + /* Change timer with a non-NULL list head, to cause processing to be skipped. */ + test_app_timer.tx_timer_internal.tx_timer_internal_list_head = (_tx_timer_list_end + 1); + status += _tx_timer_change(&test_app_timer, 0, 0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #3\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Attempt to activate the same timer again. */ + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_ACTIVATE_ERROR) + { + + /* Application timer error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Sleep for a 14 ticks. */ + tx_thread_sleep(14); + + /* At this point the initial expiration of the timer should have + happened. */ + if (timer_0_counter != 1) + { + + /* Application timer activate/deactivate error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Sleep for the reschedule time to make sure the timer doesn't hit + again! */ + tx_thread_sleep(24); + + /* At this point the timer counter should still be 1. */ + if (timer_0_counter != 1) + { + + /* Application timer activate/deactivate error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Clear timer 0's counter. */ + timer_0_counter = 0; + + /* Activate the timer. This should use the reschedule time. */ + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Test timer that is in the process of expiration - on temporary "expired" list. */ + TX_MEMSET(&timer_2, 0, (sizeof(TX_TIMER))); + + /* Setup fake timer and test for reactivate condition - current timer. */ + timer_2.tx_timer_id = TX_TIMER_ID; + timer_2.tx_timer_internal.tx_timer_internal_list_head = (TX_TIMER_INTERNAL **) ¤t_list_head; + current_list_head = (struct TX_TIMER_INTERNAL_STRUCT **) &(timer_2.tx_timer_internal); + timer_2.tx_timer_internal.tx_timer_internal_remaining_ticks = TX_TIMER_ENTRIES*2; + timer_2.tx_timer_internal.tx_timer_internal_active_next = &(timer_2.tx_timer_internal); + status = tx_timer_deactivate(&timer_2); + + /* Check for error. */ + if ((status != TX_SUCCESS) || (timer_2.tx_timer_internal.tx_timer_internal_remaining_ticks != TX_TIMER_ENTRIES)) + { + + /* Application timer error. */ + printf("ERROR #8a\n"); + test_control_return(1); + } + + + /* Sleep for twice the expiration time to make sure the timer + doesn't automatically reschedule. */ + tx_thread_sleep(47); + + /* Check for an error. */ + + /* At this point the timer counter should still be 1. */ + if (timer_0_counter != 1) + { + + /* Application timer activate/deactivate error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + else + { + + /* Application Timer test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void timer_0_expiration(ULONG timer_input) +{ + + +UINT status; + + + /* Attempt to sleep from a timer in order to test the error logic. */ + status = tx_thread_sleep(1); + + /* Check for proper error status. */ + if (status == TX_CALLER_ERROR) + { + + /* Process timer expiration. */ + timer_0_counter++; + + /* Deactivate the timer from the expiration routine. */ + tx_timer_deactivate(&timer_0); + } +} + + diff --git a/test/tx/regression/threadx_timer_deactivate_accuracy_test.c b/test/tx/regression/threadx_timer_deactivate_accuracy_test.c new file mode 100644 index 00000000..6af4bde4 --- /dev/null +++ b/test/tx/regression/threadx_timer_deactivate_accuracy_test.c @@ -0,0 +1,286 @@ +/* This test is designed to test application timer activation/deactivation services + from threads... Make sure the remaining ticks are being saved/restored properly. */ + +#include <stdio.h> +#include "tx_api.h" + +//static unsigned long expected_time; +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long timer_0_counter = 0; +static TX_TIMER timer_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void timer_0_expiration(ULONG timer_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_timer_deactivate_accuracy_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Activation/Deactivation Accuracy Test................. ERROR #1\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_0, "timer 0", timer_0_expiration, 0x1234, + 29, 31, TX_NO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Activation/Deactivation Accuracy Test................. ERROR #2\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + /* Inform user. */ + printf("Running Timer Activation/Deactivation Accuracy Test................. "); + + /* Sleep so we have to handle the wrap condition. */ + tx_thread_sleep(10); + + /* Activate the timer. */ + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #3\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(2); + + /* Deactivate and activate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(3); + + /* Deactivate and activate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(4); + + /* Deactivate and activate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(5); + + /* Deactivate and activate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(6); + + /* Deactivate and activate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(7); + + /* Deactivate and activate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if ((status != TX_SUCCESS) || (timer_0_counter)) + { + + /* Application timer error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(2); + + /* At this point the timer should have ran! */ + status = tx_timer_deactivate(&timer_0); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Check for status. */ + if ((status != TX_SUCCESS) || (timer_0_counter != 1)) + { + + /* Application timer error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + else + { + + /* Successful Re-activate test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void timer_0_expiration(ULONG timer_input) +{ + + + /* Process timer expiration. */ + timer_0_counter++; +} + diff --git a/test/tx/regression/threadx_timer_information_test.c b/test/tx/regression/threadx_timer_information_test.c new file mode 100644 index 00000000..4dbc3c9b --- /dev/null +++ b/test/tx/regression/threadx_timer_information_test.c @@ -0,0 +1,538 @@ +/* This test is designed to test timer information services. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_timer.h" + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long timer_0_counter = 0; +static TX_TIMER timer_0; + +static unsigned long timer_1_counter = 0; +static TX_TIMER timer_1; + + +static TX_TIMER timer_2; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void timer_0_expiration(ULONG timer_input); +static void timer_1_expiration(ULONG timer_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_timer_information_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Information Test...................................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_0, "timer 0", timer_0_expiration, 0x1234, + 1, 18, TX_AUTO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Information Test...................................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_1, "timer 1", timer_1_expiration, 0x1234, + 1000, 1000, TX_AUTO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Information Test...................................... ERROR #3\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +UINT interrupt_status; +CHAR *name; +UINT active; +ULONG remaining_ticks; +ULONG reschedule_ticks; +TX_TIMER *next_timer; +ULONG activates; +ULONG reactivates; +ULONG deactivates; +ULONG expirations; +ULONG expiration_adjusts; +TX_TIMER_INTERNAL **list_head; + + + /* Inform user. */ + printf("Running Timer Information Test...................................... "); + + /* Sleep for a couple ticks. */ + tx_thread_sleep(19); + + /* Check for an error. */ + if (timer_0_counter != 2) + { + + /* Application timer error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Deactivate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Sleep again. */ + tx_thread_sleep(19); + + /* Check for an error. */ + if (timer_0_counter != 2) + { + + /* Application timer error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Modify the timer. */ + status = tx_timer_change(&timer_0, 100, 1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Clear the system time. */ + tx_time_set(0); + + /* Activate the timer. */ + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Sleep for 120. */ + tx_thread_sleep(120); + + /* Check the counters to make sure everything is where it should be. */ + if ((timer_0_counter != 23) || (tx_time_get() != 120)) + { + + /* Application timer error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Get the timer information. */ + status = tx_timer_info_get(&timer_0, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &next_timer); + status += tx_timer_info_get(&timer_0, &name, &active, &remaining_ticks, &reschedule_ticks, &next_timer); + + /* Check for successful completion. */ + if ((status != TX_SUCCESS) || (active != TX_TRUE) || (remaining_ticks != 1) || (reschedule_ticks != 1) || (next_timer != &timer_1)) + { + + /* Application timer error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Now, deactivate timer 0 to get another path through the info get service. */ + status = tx_timer_deactivate(&timer_0); + status += tx_timer_info_get(&timer_0, &name, &active, &remaining_ticks, &reschedule_ticks, &next_timer); + + /* Check for successful completion. */ + if ((status != TX_SUCCESS) || (active != TX_FALSE) || (remaining_ticks != 1) || (reschedule_ticks != 1) || (next_timer != &timer_1)) + { + + /* Application timer error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Change timer 0 to a large value and get the information again. */ + status = tx_timer_change(&timer_0, 100, 200); + status += tx_timer_activate(&timer_0); + + status += tx_timer_info_get(&timer_0, &name, &active, &remaining_ticks, &reschedule_ticks, &next_timer); + + /* Check for successful completion. */ + if ((status != TX_SUCCESS) || (active != TX_TRUE) || (remaining_ticks != 100) || (reschedule_ticks != 200) || (next_timer != &timer_1)) + { + + /* Application timer error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + + /* Check for NULL pointer. */ + status = _tx_timer_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for error. */ + if (status != TX_PTR_ERROR) + { + + /* Application timer error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Now get the performance information. */ + status = tx_timer_performance_info_get(&timer_0, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_timer_performance_info_get(&timer_0, &activates, &reactivates, &deactivates, &expirations, &expiration_adjusts); + + /* Check for successful completion. */ + if ((status != TX_SUCCESS) || (activates != timer_0.tx_timer_performance_activate_count) || (reactivates != timer_0.tx_timer_performance_reactivate_count) || + (deactivates != timer_0.tx_timer_performance_deactivate_count) || (expirations != timer_0.tx_timer_performance_expiration_count) || (expiration_adjusts != timer_0.tx_timer_performance__expiration_adjust_count)) + { + + /* Application timer error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Now get the system performance information. */ + status = tx_timer_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + status += tx_timer_performance_system_info_get(&activates, &reactivates, &deactivates, &expirations, &expiration_adjusts); + + /* Check for successful completion. */ + if ((status != TX_SUCCESS) || (activates != _tx_timer_performance_activate_count) || (reactivates != _tx_timer_performance_reactivate_count) || + (deactivates != _tx_timer_performance_deactivate_count) || (expirations != _tx_timer_performance_expiration_count) || (expiration_adjusts != _tx_timer_performance__expiration_adjust_count)) + { + + /* Application timer error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + +#else + + /* Now get the performance information. */ + status = tx_timer_performance_info_get(&timer_0, &activates, &reactivates, &deactivates, &expirations, &expiration_adjusts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Application timer error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Now get the performance information. */ + status = tx_timer_performance_info_get(TX_NULL, &activates, &reactivates, &deactivates, &expirations, &expiration_adjusts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Application timer error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Now get the performance information. */ + status = tx_timer_performance_info_get(TX_NULL, TX_NULL, &reactivates, &deactivates, &expirations, &expiration_adjusts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Application timer error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Now get the performance information. */ + status = tx_timer_performance_info_get(TX_NULL, TX_NULL, TX_NULL, &deactivates, &expirations, &expiration_adjusts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Application timer error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Now get the performance information. */ + status = tx_timer_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, &expirations, &expiration_adjusts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Application timer error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Now get the performance information. */ + status = tx_timer_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, &expiration_adjusts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Application timer error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + /* Now get the performance information. */ + status = tx_timer_performance_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Application timer error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + /* Now get the system performance information. */ + status = tx_timer_performance_system_info_get(&activates, &reactivates, &deactivates, &expirations, &expiration_adjusts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Application timer error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Now get the system performance information. */ + status = tx_timer_performance_system_info_get(TX_NULL, &reactivates, &deactivates, &expirations, &expiration_adjusts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Application timer error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Now get the system performance information. */ + status = tx_timer_performance_system_info_get(TX_NULL, TX_NULL, &deactivates, &expirations, &expiration_adjusts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Application timer error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + + /* Now get the system performance information. */ + status = tx_timer_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, &expirations, &expiration_adjusts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Application timer error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + /* Now get the system performance information. */ + status = tx_timer_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, &expiration_adjusts); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Application timer error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Now get the system performance information. */ + status = tx_timer_performance_system_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check for error. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Application timer error. */ + printf("ERROR #28\n"); + test_control_return(1); + } + +#endif + + /* Test timer that is in the process of expiration - on temporary "expired" list. */ + TX_MEMSET(&timer_2, 0, (sizeof(TX_TIMER))); + + /* Setup fake timer and test for no-reactivate condition. */ + timer_2.tx_timer_id = TX_TIMER_ID; + timer_2.tx_timer_internal.tx_timer_internal_list_head = (TX_TIMER_INTERNAL **) &list_head; + list_head = (struct TX_TIMER_INTERNAL_STRUCT **) &(timer_2.tx_timer_internal); + timer_2.tx_timer_internal.tx_timer_internal_remaining_ticks = 10; + status = tx_timer_info_get(&timer_2, TX_NULL, TX_NULL, &remaining_ticks, &reschedule_ticks, TX_NULL); + + /* Check for error. */ + if ((status != TX_SUCCESS) || (remaining_ticks != 0) || (reschedule_ticks != 0)) + { + + /* Application timer error. */ + printf("ERROR #28a\n"); + test_control_return(1); + } + + /* Setup fake timer and test for reactivate condition - on temporary "expired" list. */ + timer_2.tx_timer_id = TX_TIMER_ID; + timer_2.tx_timer_internal.tx_timer_internal_list_head = (TX_TIMER_INTERNAL **) &list_head; + list_head = (struct TX_TIMER_INTERNAL_STRUCT **) &(timer_2.tx_timer_internal); + timer_2.tx_timer_internal.tx_timer_internal_remaining_ticks = TX_TIMER_ENTRIES * 2; + status = tx_timer_info_get(&timer_2, TX_NULL, TX_NULL, &remaining_ticks, &reschedule_ticks, TX_NULL); + + /* Check for error. */ + if ((status != TX_SUCCESS) || (remaining_ticks != TX_TIMER_ENTRIES) || (reschedule_ticks != 0)) + { + + /* Application timer error. */ + printf("ERROR #28a\n"); + test_control_return(1); + } + + + /* Lockout interrupts. */ + interrupt_status = tx_interrupt_control(TX_INT_DISABLE); + + /* Setup fake timer and test for reactivate condition - current timer. */ + timer_2.tx_timer_id = TX_TIMER_ID; + timer_2.tx_timer_internal.tx_timer_internal_list_head = (TX_TIMER_INTERNAL **) &list_head; + list_head = (struct TX_TIMER_INTERNAL_STRUCT **) &(timer_2.tx_timer_internal); + timer_2.tx_timer_internal.tx_timer_internal_remaining_ticks = 13; + _tx_timer_expired_timer_ptr = &timer_2.tx_timer_internal; + status = tx_timer_info_get(&timer_2, TX_NULL, TX_NULL, &remaining_ticks, &reschedule_ticks, TX_NULL); + _tx_timer_expired_timer_ptr = TX_NULL; + + /* Restore interrupts. */ + tx_interrupt_control(interrupt_status); + + /* Check for error. */ + if ((status != TX_SUCCESS) || (remaining_ticks != 0) || (reschedule_ticks != 0)) + { + + /* Application timer error. */ + printf("ERROR #28b\n"); + test_control_return(1); + } + + + /* Delete the timer... that are currently active and on the same expiration + list! */ + status = tx_timer_deactivate(&timer_0); + status += tx_timer_deactivate(&timer_1); + status += tx_timer_change(&timer_0, 100, 200); + status += tx_timer_change(&timer_1, 100, 200); + status += tx_timer_activate(&timer_0); + status += tx_timer_activate(&timer_1); + status += tx_timer_delete(&timer_0); + status += tx_timer_delete(&timer_1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #29\n"); + test_control_return(1); + } + else + { + + /* Successful Multiple Sleep test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void timer_0_expiration(ULONG timer_input) +{ + + + /* Process timer expiration. */ + timer_0_counter++; +} + + +static void timer_1_expiration(ULONG timer_input) +{ + + + /* Process timer expiration. */ + timer_1_counter++; +} diff --git a/test/tx/regression/threadx_timer_large_timer_accuracy_test.c b/test/tx/regression/threadx_timer_large_timer_accuracy_test.c new file mode 100644 index 00000000..dde97fe4 --- /dev/null +++ b/test/tx/regression/threadx_timer_large_timer_accuracy_test.c @@ -0,0 +1,286 @@ +/* This test is designed to test application timer activation/deactivation services + from threads... To make sure large timer expirations are being saved/restored properly. */ + +#include <stdio.h> +#include "tx_api.h" + +//static unsigned long expected_time; +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long timer_0_counter = 0; +static TX_TIMER timer_0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void timer_0_expiration(ULONG timer_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_timer_large_timer_accuracy_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Large Timer Activate Accuracy Test.................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_0, "timer 0", timer_0_expiration, 0x1234, + 100, 31, TX_NO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Large Timer Activate Accuracy Test.................... ERROR #2\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + /* Inform user. */ + printf("Running Timer Large Timer Activate Accuracy Test.................... "); + + /* Sleep so we have to handle the wrap condition. */ + tx_thread_sleep(10); + + /* Activate the timer. */ + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #3\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(20); + + /* Deactivate and activate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(35); + + /* Deactivate and activate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(2); + + /* Deactivate and activate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(1); + + /* Deactivate and activate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(2); + + /* Deactivate and activate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(5); + + /* Deactivate and activate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if ((status != TX_SUCCESS) || (timer_0_counter)) + { + + /* Application timer error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Sleep */ + tx_thread_sleep(35); + + /* At this point the timer should have ran! */ + status = tx_timer_deactivate(&timer_0); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Check for status. */ + if ((status != TX_SUCCESS) || (timer_0_counter != 1)) + { + + /* Application timer error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + else + { + + /* Successful Re-activate test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void timer_0_expiration(ULONG timer_input) +{ + + + /* Process timer expiration. */ + timer_0_counter++; +} + diff --git a/test/tx/regression/threadx_timer_multiple_accuracy_test.c b/test/tx/regression/threadx_timer_multiple_accuracy_test.c new file mode 100644 index 00000000..a7be91e2 --- /dev/null +++ b/test/tx/regression/threadx_timer_multiple_accuracy_test.c @@ -0,0 +1,186 @@ +/* This test is designed to test the accuracy of three free running timers. */ + +#include <stdio.h> +#include "tx_api.h" + +//static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long timer_0_counter = 0; +static TX_TIMER timer_0; +static unsigned long timer_1_counter = 0; +static TX_TIMER timer_1; +static unsigned long timer_2_counter = 0; +static TX_TIMER timer_2; + + +/* Define prototypes. */ +static void thread_0_entry(ULONG thread_input); +static void timer_0_expiration(ULONG timer_input); +static void timer_1_expiration(ULONG timer_input); +static void timer_2_expiration(ULONG timer_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_timer_multiple_accuracy_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Multiple Timer Accuracy Test.......................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_0, "timer 0", timer_0_expiration, 0x1234, + 1, 1, TX_NO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Multiple Timer Accuracy Test.......................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_1, "timer 1", timer_1_expiration, 0x1234, + 2, 2, TX_NO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Multiple Timer Accuracy Test.......................... ERROR #3\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_2, "timer 2", timer_2_expiration, 0x1234, + 3, 3, TX_NO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Multiple Timer Accuracy Test.......................... ERROR #4\n"); + test_control_return(1); + } +} + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + /* Inform user. */ + printf("Running Timer Multiple Timer Accuracy Test.......................... "); + + /* Sleep to get a fresh timer. */ + tx_thread_sleep(1); + + /* Activate all the timers. */ + status = tx_timer_activate(&timer_0); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_1); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_2); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Sleep for a some ticks. */ + tx_thread_sleep(300); + + /* Insure that each timer ran twice. */ + if ((timer_0_counter != 300) || (timer_1_counter != 150) || + (timer_2_counter != 100)) + { + + /* Application timer error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + else + { + + /* Successful timer test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void timer_0_expiration(ULONG timer_input) +{ + + + /* Process timer expiration. */ + timer_0_counter++; +} + +static void timer_1_expiration(ULONG timer_input) +{ + + + /* Process timer expiration. */ + timer_1_counter++; +} + +static void timer_2_expiration(ULONG timer_input) +{ + + + /* Process timer expiration. */ + timer_2_counter++; +} + diff --git a/test/tx/regression/threadx_timer_multiple_test.c b/test/tx/regression/threadx_timer_multiple_test.c new file mode 100644 index 00000000..3f02d5a7 --- /dev/null +++ b/test/tx/regression/threadx_timer_multiple_test.c @@ -0,0 +1,349 @@ +/* This test is designed to test a simple application timer services, + including create, activate, deactivate, change, and delete with multiple timers. */ + +#include <stdio.h> +#include "tx_api.h" + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static unsigned long timer_0_counter = 0; +static TX_TIMER timer_0; +static unsigned long timer_1_counter = 0; +static TX_TIMER timer_1; +static unsigned long timer_2_counter = 0; +static TX_TIMER timer_2; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void timer_0_expiration(ULONG timer_input); +static void timer_1_expiration(ULONG timer_input); +static void timer_2_expiration(ULONG timer_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_timer_multiple_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Multiple Timer Test................................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_0, "timer 0", timer_0_expiration, 0x1234, + 100, 200, TX_AUTO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Multiple Timer Test................................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_1, "timer 1", timer_1_expiration, 0x1234, + 100, 200, TX_AUTO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Multiple Timer Test................................... ERROR #3\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_2, "timer 2", timer_2_expiration, 0x1234, + 100, 200, TX_AUTO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Multiple Timer Test................................... ERROR #4\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + /* Inform user. */ + printf("Running Timer Multiple Timer Test................................... "); + + /* Sleep for a couple ticks. */ + tx_thread_sleep(301); + + /* Insure that each timer ran twice. */ + if ((timer_0_counter != 2) || (timer_1_counter != 2) || + (timer_2_counter != 2)) + { + + /* Application timer error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Deactivate the timers. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + status = tx_timer_deactivate(&timer_1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + status = tx_timer_deactivate(&timer_2); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Sleep again. */ + tx_thread_sleep(100); + + /* Insure that each timer haven't run again. */ + if ((timer_0_counter != 2) || (timer_1_counter != 2) || + (timer_2_counter != 2)) + { + + /* Application timer error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Modify the timer. */ + status = tx_timer_change(&timer_0, 100, 1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + status = tx_timer_change(&timer_1, 100, 2); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + status = tx_timer_change(&timer_2, 100, 3); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Activate the timer. */ + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + status = tx_timer_activate(&timer_2); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Sleep for 200. */ + tx_thread_sleep(200); + + /* Insure that each timer haven't run again. */ + if ((timer_0_counter != 103) || (timer_1_counter != 53) || + (timer_2_counter != 36)) + { + + /* Application timer error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Deactivate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + status = tx_timer_deactivate(&timer_1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + status = tx_timer_deactivate(&timer_2); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Delete the timer. */ + status = tx_timer_delete(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + status = tx_timer_delete(&timer_2); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + status = tx_timer_delete(&timer_1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Successful Multiple timer test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void timer_0_expiration(ULONG timer_input) +{ + + + /* Process timer expiration. */ + timer_0_counter++; +} + +static void timer_1_expiration(ULONG timer_input) +{ + + + /* Process timer expiration. */ + timer_1_counter++; +} + +static void timer_2_expiration(ULONG timer_input) +{ + + + /* Process timer expiration. */ + timer_2_counter++; +} + diff --git a/test/tx/regression/threadx_timer_simple_test.c b/test/tx/regression/threadx_timer_simple_test.c new file mode 100644 index 00000000..3df62caa --- /dev/null +++ b/test/tx/regression/threadx_timer_simple_test.c @@ -0,0 +1,664 @@ +/* This test is designed to test a simple application timer services, including create, + activate, deactivate, change, and delete. */ + +#include <stdio.h> +#include "tx_api.h" +#include "tx_timer.h" + +typedef struct TIMER_MEMORY_TEST_STRUCT +{ + ULONG first; + ULONG second; + TX_TIMER timer; + ULONG next_to_last; + ULONG last; + +} TIMER_MEMORY_TEST; + +static TIMER_MEMORY_TEST timer_memory; + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +/* Define external reference to status from timer create during initialization. */ + +extern UINT test_timer_create_init; + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; +static TX_THREAD thread_1; + +static unsigned long timer_0_counter = 0; +static TX_TIMER timer_0; + +static unsigned long timer_1_counter = 0; +static TX_TIMER timer_1; + +static TX_TIMER timer_2; +static TX_TIMER timer_3; + +static unsigned long error = 0; +static unsigned long timer_executed = 0; +static unsigned long isr_executed = 0; + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); +static void timer_0_expiration(ULONG timer_input); +static void timer_1_expiration(ULONG timer_input); + +UINT _txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, + VOID (*expiration_function)(ULONG), ULONG expiration_input, + ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define the timer for this test. */ + +static void timer_entry(ULONG i) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +UINT status; + + + /* Determine if the timer was able to be created durning initialization. */ + if (test_timer_create_init != TX_SUCCESS) + { + + /* Error! */ + error++; + } + + /* Attempt to delete a timer from a timer. */ + status = tx_timer_delete(&timer_0); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to create a timer from a timer. */ + status = tx_timer_create(&timer_2, "timer 2", timer_0_expiration, 0x1234, + 1, 18, TX_AUTO_ACTIVATE); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + /* Just to test another path, set this timer expired variable. */ + if (timer_executed == 0) + _tx_timer_expired = 1; +#endif + + timer_executed = 1; +#endif +} + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + +#ifndef TX_DISABLE_ERROR_CHECKING + +UINT status; + + /* Attempt to delete a timer from an ISR. */ + status = tx_timer_delete(&timer_0); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + /* Attempt to create a timer from an ISR. */ + status = tx_timer_create(&timer_2, "timer 2", timer_0_expiration, 0x1234, + 1, 18, TX_AUTO_ACTIVATE); + + /* Check status. */ + if (status != TX_CALLER_ERROR) + { + + /* Error! */ + error++; + } + + isr_executed = 1; +#endif +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_timer_simple_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, 3, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + status += tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 18, 18, 3, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Simple Test........................................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_0, "timer 0", timer_0_expiration, 0x1234, + 1, 18, TX_AUTO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Simple Test........................................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_timer_create(&timer_1, "timer 1", timer_1_expiration, 0x1234, + 1000, 1000, TX_AUTO_ACTIVATE); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Timer Simple Test........................................... ERROR #3\n"); + test_control_return(1); + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Call the timer thread entry function with a bad ID to test another path. */ + _tx_timer_thread_entry(0); +#endif + +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* Inform user. */ + printf("Running Timer Simple Test........................................... "); + + /* Perform timer memory test. */ + timer_memory.first = 0x11223344; + timer_memory.second = 0x55667788; + timer_memory.next_to_last = 0x99aabbcc; + timer_memory.last = 0xddeeff00; + + /* Create the timer. */ + status = tx_timer_create(&timer_memory.timer, "timer memory", timer_0_expiration, 0x1234, + 1000000, 100000, TX_NO_ACTIVATE); + tx_timer_delete(&timer_memory.timer); + + /* Check for status. */ + if ((status != TX_SUCCESS) || + (timer_memory.first != 0x11223344) || + (timer_memory.second != 0x55667788) || + (timer_memory.next_to_last != 0x99aabbcc) || + (timer_memory.last != 0xddeeff00)) + { + + /* Memory overwrite error. */ + printf("ERROR #4\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Attempt to activate a non-timer. */ + status = tx_timer_activate(TX_NULL); + + /* Check status. */ + if (status != TX_TIMER_ERROR) + { + + /* Application timer error. */ + printf("ERROR #5\n"); + test_control_return(1); + } + + /* Attempt to activate a non-created timer. */ + timer_2.tx_timer_id = 0; + status = tx_timer_activate(&timer_2); + + /* Check status. */ + if (status != TX_TIMER_ERROR) + { + + /* Application timer error. */ + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Attempt to activate a timer with a 0 expiration. */ + timer_2.tx_timer_id = ((ULONG) 0x4154494D); + timer_2.tx_timer_internal.tx_timer_internal_list_head = TX_NULL; + timer_2.tx_timer_internal.tx_timer_internal_remaining_ticks = 0; + status = tx_timer_activate(&timer_2); + + /* Check status. */ + if (status != TX_ACTIVATE_ERROR) + { + + /* Application timer error. */ + printf("ERROR #7\n"); + test_control_return(1); + } + + + /* Attempt to activate a timer with a wait forever expiration. */ + timer_2.tx_timer_id = ((ULONG) 0x4154494D); + timer_2.tx_timer_internal.tx_timer_internal_list_head = TX_NULL; + timer_2.tx_timer_internal.tx_timer_internal_remaining_ticks = TX_WAIT_FOREVER; + status = tx_timer_activate(&timer_2); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #8\n"); + test_control_return(1); + } + + timer_2.tx_timer_id = 0; + + /* Attempt to deactivate a non-timer. */ + status = tx_timer_deactivate(TX_NULL); + + /* Check status. */ + if (status != TX_TIMER_ERROR) + { + + /* Application timer error. */ + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to deactivate a non-created timer. */ + timer_2.tx_timer_id = 0; + status = tx_timer_deactivate(&timer_2); + + /* Check status. */ + if (status != TX_TIMER_ERROR) + { + + /* Application timer error. */ + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Attempt to change a non-timer. */ + status = tx_timer_change(TX_NULL, 1, 1); + + /* Check status. */ + if (status != TX_TIMER_ERROR) + { + + /* Application timer error. */ + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Attempt to change a non-created timer. */ + timer_2.tx_timer_id = 0; + status = tx_timer_change(&timer_2, 1, 1); + + /* Check status. */ + if (status != TX_TIMER_ERROR) + { + + /* Application timer error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Attempt to change a timer with a 0 initial ticks. */ + status = tx_timer_change(&timer_0, 0, 1); + + /* Check status. */ + if (status != TX_TICK_ERROR) + { + + /* Application timer error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + + /* Attempt to delete a non-time. */ + status = tx_timer_delete(TX_NULL); + + /* Check status. */ + if (status != TX_TIMER_ERROR) + { + + /* Application timer error. */ + printf("ERROR #14\n"); + test_control_return(1); + } + + /* Attempt to delete a non-created time. */ + timer_2.tx_timer_id = 0; + status = tx_timer_delete(&timer_2); + + /* Check status. */ + if (status != TX_TIMER_ERROR) + { + + /* Application timer error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Attempt to get info from a non-timer. */ + status = tx_timer_info_get(TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_TIMER_ERROR) + { + + /* Application timer error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + + /* Attempt to get info from a non-created timer. */ + timer_2.tx_timer_id = 0; + status = tx_timer_info_get(&timer_2, TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + /* Check status. */ + if (status != TX_TIMER_ERROR) + { + + /* Application timer error. */ + printf("ERROR #17\n"); + test_control_return(1); + } + + /* Attempt to create a timer with a NULL pointer. */ + status = tx_timer_create(TX_NULL, "timer 0", timer_0_expiration, 0x1234, + 1, 18, TX_AUTO_ACTIVATE); + + /* Check status. */ + if (status != TX_TIMER_ERROR) + { + + /* Application timer error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Attempt to create a timer with a bad control block size. */ + status = _txe_timer_create(&timer_3, "timer 3", timer_0_expiration, 0x1234, + 1, 18, TX_AUTO_ACTIVATE, (sizeof(TX_TIMER)+1)); + + /* Check status. */ + if (status != TX_TIMER_ERROR) + { + + /* Application timer error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + + /* Attempt to create a timer that has already been created. */ + status = tx_timer_create(&timer_0, "timer 0", timer_0_expiration, 0x1234, + 1, 18, TX_AUTO_ACTIVATE); + + /* Check status. */ + if (status != TX_TIMER_ERROR) + { + + /* Application timer error. */ + printf("ERROR #20\n"); + test_control_return(1); + } + + /* Attempt to create a timer with an invalid number of initial ticks. */ + status = tx_timer_create(&timer_2, "timer 2", timer_0_expiration, 0x1234, + 0, 18, TX_AUTO_ACTIVATE); + + /* Check status. */ + if (status != TX_TICK_ERROR) + { + + /* Application timer error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + /* Attempt to create a timer with an invalid activation. */ + status = tx_timer_create(&timer_2, "timer 2", timer_0_expiration, 0x1234, + 1, 18, TX_AUTO_ACTIVATE+3999); + + /* Check status. */ + if (status != TX_ACTIVATE_ERROR) + { + + /* Application timer error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + +#endif + + /* Sleep for a couple ticks. */ + tx_thread_sleep(19); + + /* Check for an error. */ + if (timer_0_counter != 2) + { + + /* Application timer error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Deactivate the timer. */ + status = tx_timer_deactivate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Sleep again. */ + tx_thread_sleep(19); + + /* Check for an error. */ + if (timer_0_counter != 2) + { + + /* Application timer error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + + /* Modify the timer. */ + status = tx_timer_change(&timer_0, 100, 1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + /* Clear the system time. */ + tx_time_set(0); + + /* Activate the timer. */ + status = tx_timer_activate(&timer_0); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #27\n"); + test_control_return(1); + } + + /* Sleep for 120. */ + tx_thread_sleep(120); + + /* Check the counters to make sure everything is where it should be. */ + if ((timer_0_counter != 23) || (tx_time_get() != 120)) + { + + /* Application timer error. */ + printf("ERROR #28\n"); + test_control_return(1); + } + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Delete the timer... that are currently active and on the same expiration + list! */ + status = tx_timer_deactivate(&timer_0); + status += tx_timer_deactivate(&timer_1); + status += tx_timer_change(&timer_0, 100, 100); + status += tx_timer_change(&timer_1, 100, 100); + status += tx_timer_activate(&timer_0); + status += tx_timer_activate(&timer_1); + status += tx_timer_delete(&timer_0); + status += tx_timer_delete(&timer_1); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + /* Application timer error. */ + printf("ERROR #29\n"); + test_control_return(1); + } + +#ifndef TX_DISABLE_ERROR_CHECKING + + /* Create a timer for the test. */ + tx_timer_create(&timer_0, "timer 0", timer_entry, 0, 1, 1, TX_AUTO_ACTIVATE); + + /* Setup the ISR. */ + test_isr_dispatch = test_isr; + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Resume thread 1 to take an interrupt on top of it. */ + tx_thread_resume(&thread_1); + + /* Sleep for a bit... */ + tx_thread_sleep(3); + + /* Clear the ISR. */ + test_isr_dispatch = TX_NULL; + + /* Test for error. */ + if ((error) || (timer_executed != 1) || (isr_executed != 1)) + { + + /* Thread error. */ + printf("ERROR #30\n"); + test_control_return(1); + } + +#endif + + if (error) + { + + /* Thread error. */ + printf("ERROR #31\n"); + test_control_return(1); + } + else + { + + /* Successful Multiple Sleep test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + +static void thread_1_entry(ULONG thread_input) +{ + + while(1) + { + + tx_thread_relinquish(); + } +} + +static void timer_0_expiration(ULONG timer_input) +{ + + + /* Process timer expiration. */ + timer_0_counter++; +} + + +static void timer_1_expiration(ULONG timer_input) +{ + + /* Process timer expiration. */ + timer_1_counter++; +} diff --git a/test/tx/regression/threadx_trace_basic_test.c b/test/tx/regression/threadx_trace_basic_test.c new file mode 100644 index 00000000..bd6ca72f --- /dev/null +++ b/test/tx/regression/threadx_trace_basic_test.c @@ -0,0 +1,779 @@ +/* This test is designed to test trace functionality in ThreadX. */ + + +#include <stdio.h> +#include "tx_api.h" +#define TX_SOURCE_CODE +#include "tx_trace.h" + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + +extern UINT _tx_trace_interrupt_control(UINT new_posture); +extern VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2); +extern VOID _tx_trace_object_unregister(VOID *object_ptr); + +static unsigned long thread_0_counter = 0; +static unsigned long thread_1_counter = 0; +static unsigned long thread_2_counter = 0; +static TX_THREAD thread_0; +static TX_THREAD thread_1; +static TX_THREAD thread_2; + +static TX_TIMER timer_0; + +static TX_BLOCK_POOL block_pool_0; +static TX_BYTE_POOL byte_pool_0; +static TX_EVENT_FLAGS_GROUP group_0; +static TX_MUTEX mutex_0; +static TX_QUEUE queue_0; +static TX_SEMAPHORE semaphore_0; + +/* Define a bunch of semaphores for loading up the trace buffer. */ + +static TX_SEMAPHORE semaphore_1; +static TX_SEMAPHORE semaphore_2; +static TX_SEMAPHORE semaphore_3; +static TX_SEMAPHORE semaphore_4; +static TX_SEMAPHORE semaphore_5; +static TX_SEMAPHORE semaphore_6; +static TX_SEMAPHORE semaphore_7; +static TX_SEMAPHORE semaphore_8; +static TX_SEMAPHORE semaphore_9; +static TX_SEMAPHORE semaphore_10; +static TX_SEMAPHORE semaphore_11; +static TX_SEMAPHORE semaphore_12; +static TX_SEMAPHORE semaphore_13; +static TX_SEMAPHORE semaphore_14; +static TX_SEMAPHORE semaphore_15; +static TX_SEMAPHORE semaphore_16; + + +static unsigned long error = 0; +static unsigned long full_buffer = 0; +static void *save_pointer; + +#if defined(TX_WIN32_MEMORY_SIZE) || defined(TX_LINUX_MEMORY_SIZE) + +static FILE *trace_dump_file; +static CHAR trace_dump_file_name[]= "tracedump000.trx"; + +#endif + + +/* Define task prototypes. */ + +static void thread_0_entry(ULONG task_input); +static void thread_1_entry(ULONG task_input); +static void thread_2_entry(ULONG task_input); + + +/* Define the trace buffer. */ +UCHAR trace_buffer[16384]; + + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); +UINT _tx_thread_interrupt_control(UINT new_posture); + + +void trace_dump(void) +{ + +#if defined(TX_WIN32_MEMORY_SIZE) || defined(TX_LINUX_MEMORY_SIZE) + +/* Win32 automatic dump! */ +UINT old_interrupt; + + + /* Disable interrupts. */ + old_interrupt = _tx_thread_interrupt_control(TX_INT_DISABLE); + + /* If win32, we can actually dump the file! */ + trace_dump_file = fopen(trace_dump_file_name, "wb+"); + + fwrite(trace_buffer, 1, sizeof(trace_buffer), trace_dump_file); + + fclose(trace_dump_file); + + /* Restore interrupts. */ + _tx_thread_interrupt_control(old_interrupt); + + /* Prepare for next file dump. */ + trace_dump_file_name[11]++; + if (trace_dump_file_name[11] > '9') + { + trace_dump_file_name[11] = '0'; + trace_dump_file_name[10]++; + + if (trace_dump_file_name[10] > '9') + { + trace_dump_file_name[10] = '0'; + trace_dump_file_name[9]++; + + if (trace_dump_file_name[9] > '9') + trace_dump_file_name[9] = '0'; + } + } + +#endif + +} + + +/* Define the timer for this test. */ + +static void timer_entry(ULONG i) +{ + + /* Resume thread 1. */ + tx_thread_resume(&thread_1); +} + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + + /* Make ISR entry event. */ + tx_trace_isr_enter_insert(1); + + /* Resume thread 2. */ + tx_thread_resume(&thread_2); + + /* Make ISR entry event. */ + tx_trace_isr_exit_insert(1); +} + + +/* Define the trace buffer full notify function. */ + +static VOID trace_buffer_full(void *ptr) +{ + + /* Dump trace file! */ + trace_dump(); + + full_buffer++; +} + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_trace_basic_application_define(void *first_unused_memory) +#endif +{ + +INT status; +CHAR *pointer; + + + /* Setup a pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Adjust it forward just to make sure there is some space for the test below. */ + pointer = pointer + 200; + + /* Create a bunch of objects before being enabled. */ + + /* Create a timer for the test. */ + save_pointer = (void *) pointer; + tx_timer_create(&timer_0, "timer 0", timer_entry, 0, 2, 2, TX_AUTO_ACTIVATE); + tx_block_pool_create(&block_pool_0, "block pool 0", 20, pointer, 100); + pointer = pointer + 100; + tx_byte_pool_create(&byte_pool_0, "byte pool 0", pointer, 1000); + pointer = pointer + 1000; + tx_event_flags_create(&group_0, "event flags group 0"); + tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + tx_queue_create(&queue_0, "queue 0", 16, pointer, 400); + pointer = pointer + 400; + tx_semaphore_create(&semaphore_0, "semaphore 0", 1); + + /* Enable event tracing. */ + _tx_trace_initialize(); + status = tx_trace_enable(trace_buffer, sizeof(trace_buffer), 16); + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running Trace Basic Test............................................ ERROR #1\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Trace Basic Test............................................ ERROR #2\n"); + test_control_return(1); + } +#endif + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Trace Basic Test............................................ ERROR #3\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Trace Basic Test............................................ ERROR #4\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 14, 14, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Trace Basic Test............................................ ERROR #5\n"); + test_control_return(1); + } +} + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +UINT old_interrupt; +CHAR *pointer; +TX_INTERRUPT_SAVE_AREA +ULONG object; + + /* Coverage for build without TraceX enabled. */ + tx_saved_posture = _tx_trace_interrupt_control(TX_INT_DISABLE); + _tx_trace_interrupt_control(tx_saved_posture); +#ifndef TX_ENABLE_EVENT_TRACE + _tx_trace_object_register(0, TX_NULL, TX_NULL, 0, 0); + _tx_trace_object_register(1, TX_NULL, TX_NULL, 0, 0); + _tx_trace_object_register(1, &object, TX_NULL, 0, 0); + _tx_trace_object_register(1, &object, "fake name", 0, 0); + _tx_trace_object_register(1, &object, "fake name", 1, 0); +#endif + _tx_trace_object_register(1, &object, "fake name", 1, 1); + _tx_trace_object_unregister(TX_NULL); + _tx_trace_object_unregister(&object); + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Inform user of success getting to this test. */ + printf("Running Trace Basic Test............................................ "); + + /* Delete the additional objects. */ + tx_timer_delete(&timer_0); + tx_block_pool_delete(&block_pool_0); + tx_byte_pool_delete(&byte_pool_0); + tx_event_flags_delete(&group_0); + tx_mutex_delete(&mutex_0); + tx_queue_delete(&queue_0); + tx_semaphore_delete(&semaphore_0); + + /* Create all the semaphores. */ + tx_semaphore_create(&semaphore_1, "semaphore 1", 1); + tx_semaphore_create(&semaphore_2, "semaphore 2", 1); + tx_semaphore_create(&semaphore_3, "semaphore 3", 1); + tx_semaphore_create(&semaphore_4, "semaphore 4", 1); + tx_semaphore_create(&semaphore_5, "semaphore 5", 1); + tx_semaphore_create(&semaphore_6, "semaphore 6", 1); + tx_semaphore_create(&semaphore_7, "semaphore 7", 1); + tx_semaphore_create(&semaphore_8, "semaphore 8", 1); + tx_semaphore_create(&semaphore_9, "semaphore 9", 1); + tx_semaphore_create(&semaphore_10, "semaphore 10", 1); + tx_semaphore_create(&semaphore_11, "semaphore 11", 1); + tx_semaphore_create(&semaphore_12, "semaphore 12", 1); + tx_semaphore_create(&semaphore_13, "semaphore 13", 1); + tx_semaphore_create(&semaphore_14, "semaphore 14", 1); + tx_semaphore_create(&semaphore_15, "semaphore 15", 1); + tx_semaphore_create(&semaphore_16, "semaphore 16", 1); + + /* Delete them all. */ + tx_semaphore_delete(&semaphore_1); + tx_semaphore_delete(&semaphore_2); + tx_semaphore_delete(&semaphore_3); + tx_semaphore_delete(&semaphore_4); + tx_semaphore_delete(&semaphore_5); + tx_semaphore_delete(&semaphore_6); + tx_semaphore_delete(&semaphore_7); + tx_semaphore_delete(&semaphore_8); + tx_semaphore_delete(&semaphore_9); + tx_semaphore_delete(&semaphore_10); + tx_semaphore_delete(&semaphore_11); + tx_semaphore_delete(&semaphore_12); + tx_semaphore_delete(&semaphore_13); + tx_semaphore_delete(&semaphore_14); + tx_semaphore_delete(&semaphore_15); + tx_semaphore_delete(&semaphore_16); + + /* Create one over again. */ + tx_semaphore_create(&semaphore_1, "semaphore 1", 1); + + /* Now, create them all again. */ + pointer = (CHAR *) save_pointer; + tx_block_pool_create(&block_pool_0, "block pool 0", 20, pointer, 100); + pointer = pointer + 100; + tx_byte_pool_create(&byte_pool_0, "byte pool 0", pointer, 1000); + pointer = pointer + 1000; + tx_event_flags_create(&group_0, "event flags group 0"); + tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + tx_queue_create(&queue_0, "queue 0", 16, pointer, 400); + pointer = pointer + 400; + tx_semaphore_create(&semaphore_0, "semaphore 0", 1); + + /* Attempt to enable event tracing again. */ + status = tx_trace_enable(trace_buffer, sizeof(trace_buffer), 8); + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check status. */ + if (status != TX_NOT_DONE) + { + + printf("ERROR #6\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Attempt to enable event tracing again. */ + status = tx_trace_enable(TX_NULL, 0, 8); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("ERROR #8\n"); + test_control_return(1); + } + + /* Attempt to enable event tracing again. */ + status = tx_trace_enable(TX_NULL, 1, 0); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Attempt to enable event tracing again. */ + status = tx_trace_enable(TX_NULL, 1, 8); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("ERROR #10\n"); + test_control_return(1); + } + +#endif + + /* Filter all events. */ + status = tx_trace_event_filter(TX_TRACE_ALL_EVENTS); + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Trace error. */ + printf("ERROR #11\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #12\n"); + test_control_return(1); + } + + /* Filter all events. */ + status = tx_trace_event_filter(0); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #13\n"); + test_control_return(1); + } + +#endif + + /* Unfilter all events. */ + status = tx_trace_event_unfilter(TX_TRACE_ALL_EVENTS); + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Trace error. */ + printf("ERROR #14\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #15\n"); + test_control_return(1); + } + + /* Unfilter all events. */ + status = tx_trace_event_unfilter(0); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #16\n"); + test_control_return(1); + } + +#endif + + /* Register the trace buffer full notification routine. */ + status = tx_trace_buffer_full_notify(trace_buffer_full); + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Trace error. */ + printf("ERROR #17\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #18\n"); + test_control_return(1); + } + + /* Check the NULL path with trace disabled. */ + status = tx_trace_buffer_full_notify(TX_NULL); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #19\n"); + test_control_return(1); + } + +#endif + + /* Create a timer for the test. */ + tx_timer_create(&timer_0, "timer 0", timer_entry, 0, 2, 2, TX_AUTO_ACTIVATE); + + /* Setup the ISR. */ + test_isr_dispatch = test_isr; + + while (full_buffer < 40) + { + + if (full_buffer < 20) + { + + /* Disable interrupts. */ + old_interrupt = tx_interrupt_control(TX_INT_DISABLE); + + /* Restore interrupts. */ + tx_interrupt_control(old_interrupt); + } + + /* Insert user event. */ + status = tx_trace_user_event_insert(1027, 1, 2, 3, 4); + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Trace error. */ + printf("ERROR #20\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #21\n"); + test_control_return(1); + } + + /* Insert user event. */ + status = tx_trace_user_event_insert(0, 1, 2, 3, 4); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #22\n"); + test_control_return(1); + } + + /* Insert user event. */ + status = tx_trace_user_event_insert(0, 0, 2, 3, 4); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #23\n"); + test_control_return(1); + } + + /* Insert user event. */ + status = tx_trace_user_event_insert(0, 0, 0, 3, 4); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #24\n"); + test_control_return(1); + } + + /* Insert user event. */ + status = tx_trace_user_event_insert(0, 0, 0, 0, 4); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #25\n"); + test_control_return(1); + } + + /* Insert user event. */ + status = tx_trace_user_event_insert(0, 0, 0, 0, 0); + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #26\n"); + test_control_return(1); + } + + break; +#endif + } + + /* Clear the ISR. */ + test_isr_dispatch = TX_NULL; + + /* Disable the trace buffer. */ + status = tx_trace_disable(); + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Trace error. */ + printf("ERROR #27\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #28\n"); + test_control_return(1); + } +#endif + + /* Attempt to disable again, just to get the TX_NOT_DONE error code. */ + status = tx_trace_disable(); + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check status. */ + if (status != TX_NOT_DONE) + { + + /* Trace error. */ + printf("ERROR #29\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #30\n"); + test_control_return(1); + } +#endif + + /* Attempt to enable event tracing with a bogus size. */ + status = tx_trace_enable(trace_buffer, 1, 8); + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check status. */ + if (status != TX_SIZE_ERROR) + { + + /* Trace error. */ + printf("ERROR #31\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #32\n"); + test_control_return(1); + } +#endif + + + /* Attempt to make an user event when tracing is not enabled. */ + status = tx_trace_user_event_insert(1027, 1, 2, 3, 4); + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check status. */ + if (status != TX_NOT_DONE) + { + + /* Trace error. */ + printf("ERROR #33\n"); + test_control_return(1); + } +#else + + /* Check status. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + /* Trace error. */ + printf("ERROR #34\n"); + test_control_return(1); + } +#endif + + + /* Check status. */ + if (error) + { + + /* Trace error. */ + printf("ERROR #35\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG task_input) +{ + + while(1) + { + + thread_1_counter++; + tx_thread_suspend(&thread_1); + } +} + + + +static void thread_2_entry(ULONG task_input) +{ + + while(1) + { + + thread_2_counter++; + tx_thread_suspend(&thread_2); + } +} |
