1
0
mirror of https://github.com/azure-rtos/threadx synced 2025-01-30 08:02:57 +08:00
threadx/test/tx/regression/threadx_thread_delayed_suspension_test.c
2023-04-04 09:40:54 +00:00

391 lines
9.8 KiB
C

/* 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