|
Main / ThreadxExample
/* 12_sample_system.c
Create two threads, one byte pool, two message queues, three timers, and
one counting semaphore. This is an example of multiple object suspension
using event-chaining, i.e., speedy_thread and slow_thread wait for a
message to appear on either of two queues */
/****************************************************/
/* Declarations, Definitions, and Prototypes */
/****************************************************/
#include "tx_api.h"
#include <stdio.h>
#define STACK_SIZE 1024
#define BYTE_POOL_SIZE 9120
#define NUMBER_OF_MESSAGES 100
#define MESSAGE_SIZE TX_1_ULONG
#define QUEUE_SIZE MESSAGE_SIZE*sizeof(ULONG)*NUMBER_OF_MESSAGES
/* Define the ThreadX object control blocks... */
TX_THREAD speedy_thread; /* higher priority thread */
TX_THREAD slow_thread; /* lower priority thread */
TX_BYTE_POOL my_byte_pool; /* byte pool for stacks and queues */
TX_SEMAPHORE gatekeeper; /* indicate how many objects available */
TX_QUEUE queue_1; /* queue for multiple object suspension */
TX_QUEUE queue_2; /* queue for multiple object suspension */
TX_TIMER stats_timer; /* generate statistics at intervals */
TX_TIMER queue_timer_1; /* send message to queue_1 at intervals */
TX_TIMER queue_timer_2; /* send message to queue_2 at intervals */
/* Variables needed to get info about the message queue */
CHAR *info_queue_name;
TX_THREAD *first_suspended;
TX_QUEUE *next_queue;
ULONG enqueued_1=0, enqueued_2=0, suspended_count=0, available_storage=0;
/* Define the variables used in the sample application... */
ULONG speedy_thread_counter=0, total_speedy_time=0;
ULONG slow_thread_counter=0, total_slow_time=0;
ULONG send_message_1[TX_1_ULONG]={0X0}, send_message_2[TX_1_ULONG]={0X0};
ULONG receive_message_1[TX_1_ULONG], receive_message_2[TX_1_ULONG];
/* speedy_thread and slow_thread entry function prototypes */
void speedy_thread_entry(ULONG thread_input);
void slow_thread_entry(ULONG thread_input);
/* timer entry function prototypes */
void queue_timer_1_entry(ULONG thread_input);
void queue_timer_2_entry(ULONG thread_input);
void print_stats(ULONG);
/* event notification function prototypes */
void queue_1_send_notify(TX_QUEUE *queue_1_ptr);
void queue_2_send_notify(TX_QUEUE *queue_2_ptr);
/****************************************************/
/* Main Entry Point */
/****************************************************/
/* Define main entry point. */
int main()
{
/* Enter the ThreadX kernel. */
tx_kernel_enter();
}
/****************************************************/
/* Application Definitions */
/****************************************************/
/* Define what the initial system looks like. */
void tx_application_define(void *first_unused_memory)
{
CHAR *speedy_stack_ptr;
CHAR *slow_stack_ptr;
CHAR *queue_1_ptr;
CHAR *queue_2_ptr;
/* Create a byte memory pool from which to allocate the thread stacks. */
tx_byte_pool_create(&my_byte_pool, "my_byte_pool",
first_unused_memory, BYTE_POOL_SIZE);
/* Create threads, queues, the semaphore, timers, and register functions
for event-chaining */
/* Allocate the stack for speedy_thread. */
tx_byte_allocate(&my_byte_pool, (VOID **) &speedy_stack_ptr, STACK_SIZE,
TX_NO_WAIT);
/* Create speedy_thread. */
tx_thread_create(&speedy_thread, "speedy_thread", speedy_thread_entry, 0,
speedy_stack_ptr, STACK_SIZE, 5, 5, TX_NO_TIME_SLICE,
TX_AUTO_START);
/* Allocate the stack for slow_thread. */
tx_byte_allocate(&my_byte_pool, (VOID **) &slow_stack_ptr, STACK_SIZE,
TX_NO_WAIT);
/* Create slow_thread */
tx_thread_create(&slow_thread, "slow_thread", slow_thread_entry, 1,
slow_stack_ptr, STACK_SIZE, 15, 15, TX_NO_TIME_SLICE,
TX_AUTO_START);
/* Create the message queues used by both threads. */
tx_byte_allocate(&my_byte_pool, (VOID **) &queue_1_ptr,
QUEUE_SIZE, TX_NO_WAIT);
tx_queue_create (&queue_1, "queue_1", MESSAGE_SIZE,
queue_1_ptr, QUEUE_SIZE);
tx_byte_allocate(&my_byte_pool, (VOID **) &queue_2_ptr,
QUEUE_SIZE, TX_NO_WAIT);
tx_queue_create (&queue_2, "queue_2", MESSAGE_SIZE,
queue_2_ptr, QUEUE_SIZE);
/* Create the gatekeeper semaphore that counts the available objects */
tx_semaphore_create (&gatekeeper, "gatekeeper", 0);
/* Create and activate the stats timer */
tx_timer_create (&stats_timer, "stats_timer", print_stats,
0x1234, 500, 500, TX_AUTO_ACTIVATE);
/* Create and activate the timer to send messages to queue_1 */
tx_timer_create (&queue_timer_1, "queue_timer", queue_timer_1_entry,
0x1234, 12, 12, TX_AUTO_ACTIVATE);
/* Create and activate the timer to send messages to queue_2 */
tx_timer_create (&queue_timer_2, "queue_timer", queue_timer_2_entry,
0x1234, 9, 9, TX_AUTO_ACTIVATE);
/* Register the function to increment the gatekeeper semaphore when a
message is sent to queue_1 */
tx_queue_send_notify(&queue_1, queue_1_send_notify);
/* Register the function to increment the gatekeeper semaphore when a
message is sent to queue_2 */
tx_queue_send_notify(&queue_2, queue_1_send_notify);
}
/****************************************************/
/* Function Definitions */
/****************************************************/
/* Entry function definition of speedy_thread
it has a higher priority than slow_thread */
void speedy_thread_entry(ULONG thread_input)
{
ULONG start_time, cycle_time=0, current_time=0;
UINT status;
/* This is the higher priority speedy_thread */
while(1)
{
/* Get the starting time for this cycle */
start_time = tx_time_get();
/* Activity 1: 2 ticks. */
tx_thread_sleep(2);
/* Activity 2: 5 ticks. */
/* wait for a message to appear on either one of the two queues */
tx_semaphore_get (&gatekeeper, TX_WAIT_FOREVER);
/* Determine whether a message queue_1 or queue_2 is available */
status = tx_queue_receive (&queue_1, receive_message_1, TX_NO_WAIT);
if (status == TX_SUCCESS)
; /* A message on queue_1 has been found - process */
else
/* Receive a message from queue_2 */
tx_queue_receive (&queue_2, receive_message_2, TX_WAIT_FOREVER);
tx_thread_sleep(5);
/* Increment the thread counter and get timing info */
speedy_thread_counter++;
current_time = tx_time_get();
cycle_time = current_time - start_time;
total_speedy_time = total_speedy_time + cycle_time;
}
}
/************************************************************/
/* Entry function definition of slow_thread
it has a lower priority than speedy_thread */
void slow_thread_entry(ULONG thread_input)
{
ULONG start_time, current_time=0, cycle_time=0;
UINT status;
while(1)
{
/* Get the starting time for this cycle */
start_time = tx_time_get();
/* Activity 3 - sleep 12 ticks. */
/* wait for a message to appear on either one of the two queues */
tx_semaphore_get (&gatekeeper, TX_WAIT_FOREVER);
/* Determine whether a message queue_1 or queue_2 is available */
status = tx_queue_receive (&queue_1, receive_message_1, TX_NO_WAIT);
if (status == TX_SUCCESS)
; /* A message on queue_1 has been found - process */
else
/* Receive a message from queue_2 */
tx_queue_receive (&queue_2, receive_message_2, TX_WAIT_FOREVER);
tx_thread_sleep(12);
/* Activity 4: 8 ticks. */
tx_thread_sleep(8);
/* Increment the thread counter and get timing info */
slow_thread_counter++;
current_time = tx_time_get();
cycle_time = current_time - start_time;
total_slow_time = total_slow_time + cycle_time;
}
}
/*****************************************************/
/* print statistics at specified times */
void print_stats (ULONG invalue)
{
ULONG current_time, avg_slow_time, avg_speedy_time;
if ((speedy_thread_counter>0) && (slow_thread_counter>0))
{
current_time = tx_time_get();
avg_slow_time = total_slow_time / slow_thread_counter;
avg_speedy_time = total_speedy_time / speedy_thread_counter;
tx_queue_info_get (&queue_1, &info_queue_name, &enqueued_1,
&available_storage, &first_suspended,
&suspended_count, &next_queue);
tx_queue_info_get (&queue_2, &info_queue_name, &enqueued_2,
&available_storage, &first_suspended,
&suspended_count, &next_queue);
printf("\nEvent-Chaining: 2 threads waiting for 2 queues\n\n");
printf(" Current Time: %lu\n", current_time);
printf(" speedy_thread counter: %lu\n", speedy_thread_counter);
printf(" speedy_thread avg time: %lu\n", avg_speedy_time);
printf(" slow_thread counter: %lu\n", slow_thread_counter);
printf(" slow_thread avg time: %lu\n", avg_slow_time);
printf(" total # queue_1 messages sent: %lu\n", send_message_1[TX_1_ULONG-1]);
printf(" total # queue_2 messages sent: %lu\n", send_message_2[TX_1_ULONG-1]);
printf(" current # messages in queue_1: %lu\n", enqueued_1);
printf(" current # messages in queue_2: %lu\n\n", enqueued_2);
}
else printf("Bypassing print_stats function, Current Time: %lu\n", tx_time_get());
}
/*****************************************************/
/* Send a message to queue_1 at specified times */
void queue_timer_1_entry (ULONG invalue)
{
/* Send a message to queue_1 using the multiple object suspension approach */
/* The gatekeeper semaphore keeps track of how many objects are available
via the notification function */
send_message_1[TX_1_ULONG-1]++;
tx_queue_send (&queue_1, send_message_1, TX_NO_WAIT);
}
/*****************************************************/
/* Send a message to the queue at specified times */
void queue_timer_2_entry (ULONG invalue)
{
/* Send a message to queue_2 using the multiple object suspension approach */
/* The gatekeeper semaphore keeps track of how many objects are available
via the notification function */
send_message_2[TX_1_ULONG-1]++;
tx_queue_send (&queue_2, send_message_2, TX_NO_WAIT);
}
/*****************************************************/
/* Notification function to increment gatekeeper semaphore
whenever a message has been sent to queue_1 */
void queue_1_send_notify(TX_QUEUE *queue_ptr_1)
{
tx_semaphore_put (&gatekeeper);
}
/*****************************************************/
/* Notification function to increment gatekeeper semaphore
whenever a message has been sent to queue_2 */
void queue_2_send_notify(TX_QUEUE *queue_ptr_2)
{
tx_semaphore_put (&gatekeeper);
}
|