One service — the tx_timer_pool_ performance_info_get service — provides an information summary for a particular application timer up to the time the service is invoked.. 10.11 Sample Sy
Trang 110.9 Deleting an Application Timer
The tx_timer_delete service deletes an application timer Figure 10.10 shows how to
delete an application timer
If variable status contains the return value TX_SUCCESS, we have successfully deleted
the application timer Make certain that you do not inadvertently use a deleted timer
10.10 Retrieving Application Timer Information
There are three services that enable you to retrieve vital information about application timers The fi rst such service for application timers — the tx_timer_pool_info_get
service — retrieves a subset of information from the Application Timer Control Block This information provides a “ snapshot ” at a particular instant in time, i.e., when the
service is invoked The other two services provide summary information that is based
on the gathering of run-time performance data One service — the tx_timer_pool_
performance_info_get service — provides an information summary for a particular
application timer up to the time the service is invoked By contrast the tx_timer_pool_ performance_system_info_get retrieves an information summary for all application
timers in the system up to the time the service is invoked These services are useful
in analyzing the behavior of the system and determining whether there are potential
problem areas The tx_timer_info_get5 service retrieves a variety of information about an
TX_TIMER my_timer;
UINT status;
…
/* Delete application timer Assume that the application timer has already been created */
status = tx_timer_delete(&my_timer);
/* If status equals TX_SUCCESS, the application timer is deleted */
Figure 10.10: Deleting an application timer
5 By default, only the tx_timer_info_get service is enabled The other two information-gathering
services must be enabled in order to use them
Trang 2application timer The information that is retrieved includes the application timer name, its active/inactive state, the number of timer-ticks before the timer expires, the number of subsequent timer-ticks for timer expiration after the fi rst expiration, and a pointer to the next created application timer Figure 10.11 shows how this service can be used to obtain information about an application timer
If variable status contains the return value TX_SUCCESS, we have retrieved valid
information about the timer
10.11 Sample System Using Timers to Measure Thread
Performance
In Chapter 8 , we created a sample system that produced output beginning as follows: Current Time: 34 Speedy_Thread fi nished cycle
Current Time: 40 Slow_Thread fi nished cycle
Current Time: 56 Speedy_Thread fi nished cycle
The timing data in this output was captured with the use of the internal system clock Following are the statements near the end of the Speedy_Thread entry function that
generate information about the performance of Speedy_Thread
TX_TIMER my_timer;
CHAR *my_timer_name;
UINT active;
ULONG remaining_ticks;
ULONG reschedule_ticks;
TX_TIMER *next_timer;
UINT status;
…
/* Retrieve information about the previously created application timer called "my_timer." */
status = tx_timer_info_get(&my_timer, &my_timer_name, &active,&remaining_ticks, &reschedule_ticks,
&next_timer);
/* If status equals TX_SUCCESS, the information requested is valid */
Figure 10.11: Retrieve information about an application timer
Trang 3current_time tx_time_get();
printf( “ Current Time: %5lu Speedy_Thread fi nished cycle \n ”
current_time);
We used the tx_time_get service to retrieve the current time from the internal system clock Each time the Speedy_Thread fi nished its cycle it displayed the preceding timing information
For this sample system, we will eliminate the display of information at the end of each thread cycle However, we will continue to use the internal system clock to determine the time duration of a thread cycle, but we will display a summary of information at
designated intervals, say every 500 timer-ticks We will use an application timer to trigger this periodic display Following is a portion of the sample output we would like to have displayed on a periodic basis:
**** Timing Info Summary
Current Time: 500
Speedy_Thread counter: 22
Speedy_Thread avg time: 22
Slow_Thread counter: 11
Slow_Thread avg time: 42
We need to compute the average cycle time for both the Speedy_Thread and the
Slow_Thread To accomplish this, we need two variables for each of the two threads: one to store the total time spent in the cycle, and one to count the total number of cycles completed Figure 10.12 contains these variable declarations and the other additions to the declarations and defi nitions section of the program
/* Declare the application timer */
TX_TIMER stats_timer;
/* Declare the counters and accumulators */
ULONG Speedy_Thread_counter = 0, total_speedy_time = 0;
ULONG Slow_Thread_counter = 0, total_slow_time = 0;
/* Define prototype for expiration function */
void print_stats(ULONG);
Figure 10.12: Additions to the declarations and defi nitions section
Trang 4We need to add the timer creation service to the tx_application_defi ne function, as
indicated by Figure 10.13
We need to modify the entry functions for the Speedy_Thread and the Slow_Thread
Delete the following statements at the end of the Speedy_Thread entry function:
current_time tx_time_get();
printf( “ Current Time: %lu Speedy_Thread fi nished cycle \n ”
current_time);
We will use the internal system clock to compute the time to complete each cycle We also need to compute the total cycle time as follows:
total_speedy_time Σcycle time_
Figure 10.14 contains the necessary additions for the Speedy_Thread
The entry function for Slow_Thread requires similar additions, but we leave that as an exercise for the reader These computations store the total number of cycles that have
/* Insert at the beginning of Speedy_Thread entry function */
ULONG start_time, cycle_time;
/* Get the starting time for this cycle */
start_time = tx_time_get();
…
/* Insert at the end of Speedy_Thread entry function */
/* Increment thread counter, compute cycle time & total time */
Speedy_Thread_counter++;
current_time = tx_time_get();
cycle_time = current_time - start_time;
total_speedy_time = total_speedy_time + cycle_time;
Figure 10.14: Additions to the Speedy_Thread entry function
/* Create and activate the timer */
tx_timer_create (&stats_timer, "stats_timer", print_stats, 0x1234, 500, 500, TX_AUTO_ACTIVATE);
Figure 10.13: Additions to the application defi nitions section
Trang 5been completed, and the total amount of time spent in those cycles The expiration
function called print_stats will use these values to compute average cycle time for both threads and will display summary information
Every 500 timer-ticks, the application timer called stats_timer expires and invokes the expiration function print_stats After determining that both thread counters are greater than zero, that function computes the average cycle times for Speedy_Thread and Slow_ Thread, as follows:
avg speedy time total speedy time
speedy thread counter
and
avg slow time total slow time
slow thread counter
Function print_stats then displays the current time, the average cycle times, and the
number of cycles completed by each of the threads Figure 10.15 contains a listing of the print_stats expiration function
/* Display statistics at periodic intervals */
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;
printf("\n**** Timing Info Summary\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\n", avg_slow_time);
}
else printf("Bypassing print_stats, Time: %lu\n", tx_time_get());
}
Figure 10.15: Expiration function to display summary information
Trang 6This program can be modifi ed easily to display other timing information; the timer can be changed to expire at different time intervals as well The complete program listing called
10_sample_system.c is located in the next section of this chapter and on the attached CD
10.12 Listing for 10_sample_system.c
The sample system named 10_sample_system.c is located on the attached CD The
complete listing appears below; line numbers have been added for easy reference
001 /* 10_sample_system.c
002
003 Create two threads, and one mutex
004 Use arrays for the thread stacks
005 The mutex protects the critical sections
006 Use an application timer to display thread timings */
007
008 /****************************************************/
009 /* Declarations, Defi nitions, and Prototypes */
010 /****************************************************/
011
012 #include “ tx_api.h ”
013 #include stdio.h
014
015 #defi ne STACK_SIZE 1024
016
017 CHAR stack_speedy[STACK_SIZE];
018 CHAR stack_slow[STACK_SIZE];
019
020
021 /* Defi ne the ThreadX object control blocks */
022
023 TX_THREAD Speedy_Thread;
024 TX_THREAD Slow_Thread;
025
026 TX_MUTEX my_mutex;
027
028 /* Declare the application timer */
029 TX_TIMER stats_timer;
030
Trang 7031 /* Declare the counters and accumulators */
032 ULONG Speedy_Thread_counter 0,
033 total_speedy_time 0;
034 ULONG Slow_Thread_counter 0,
035 total_slow_time 0;
036
037 /* Defi ne prototype for expiration function */
038 void print_stats(ULONG);
039
040 /* Defi ne thread prototypes */
041
042 void Speedy_Thread_entry(ULONG thread_input);
043 void Slow_Thread_entry(ULONG thread_input);
044
045
046 /****************************************************/
047 /* Main Entry Point */
048 /****************************************************/
049
050 /* Defi ne main entry point */
051
052 int main()
053 {
054
055 /* Enter the ThreadX kernel */
056 tx_kernel_enter();
057 }
058
059
060 /****************************************************/
061 /* Application Defi nitions */
062 /****************************************************/
063
064 /* Defi ne what the initial system looks like */
065
066 void tx_application_defi ne(void *fi rst_unused_memory)
067 {
068
069
070 /* Put system defi nitions here,
Trang 8071 e.g., thread and mutex creates */
072
073 /* Create the Speedy_Thread */
074 tx_thread_create( & Speedy_Thread, “ Speedy_Thread ”
075 Speedy_Thread_entry, 0,
076 stack_speedy, STACK_SIZE,
077 5, 5, TX_NO_TIME_SLICE, TX_AUTO_START);
078
079 /* Create the Slow_Thread */
080 tx_thread_create( & Slow_Thread, “ Slow_Thread ”
081 Slow_Thread_entry, 1,
082 stack_slow, STACK_SIZE,
083 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START);
084
085 /* Create the mutex used by both threads */
086 tx_mutex_create( & my_mutex, “ my_mutex ” , TX_NO_INHERIT);
087
088 /* Create and activate the timer */
089 tx_timer_create ( & stats_timer, “ stats_timer ” , print_stats,
090 0 1234, 500, 500, TX_AUTO_ACTIVATE);
091
092 }
093
094
095 /****************************************************/
096 /* Function Defi nitions */
097 /****************************************************/
098
099 /* Defi ne the activities for the Speedy_Thread */
100
101 void Speedy_Thread_entry(ULONG thread_input)
102 {
103 UINT status;
104 ULONG current_time;
105 ULONG start_time, cycle_time;
106
107 while(1)
108 {
109
110 /* Get the starting time for this cycle */
Trang 9111 start_time tx_time_get();
112
113 /* Activity 1: 2 timer-ticks */
114 tx_thread_sleep(2);
115
116 /* Activity 2: 5 timer-ticks *** critical section ***
117 Get the mutex with suspension */
118
119 status tx_mutex_get( & my_mutex, TX_WAIT_FOREVER);
120 if (status ! TX_SUCCESS) break; /* Check status */
121
122 tx_thread_sleep(5);
123
124 /* Release the mutex */
125 status tx_mutex_put( & my_mutex);
126 if (status ! TX_SUCCESS) break; /* Check status */
127
128 /* Activity 3: 4 timer-ticks */
129 tx_thread_sleep(4);
130
131 /* Activity 4: 3 timer-ticks *** critical section ***
132 Get the mutex with suspension */
133
134 status tx_mutex_get( & my_mutex, TX_WAIT_FOREVER);
135 if (status ! TX_SUCCESS) break; /* Check status */
136
137 tx_thread_sleep(3);
138
139 /* Release the mutex */
140 status tx_mutex_put( & my_mutex);
141 if (status ! TX_SUCCESS) break; /* Check status */
142
143 /* Increment thread counter, compute cycle time & total
time */
144 Speedy_Thread_counter ;
145 current_time tx_time_get();
146 cycle_time current_time-start_time;
147 total_speedy_time total_speedy_time cycle_time;
148
149 }
Trang 10150 }
151
152 /****************************************************/
153
154 /* Defi ne the activities for the Slow_Thread */
155
156 void Slow_Thread_entry(ULONG thread_input)
157 {
158 UINT status;
159 ULONG current_time;
160 ULONG start_time, cycle_time;
161
162 while(1)
163 {
164
165 /* Get the starting time for this cycle */
166 start_time tx_time_get();
167
168 /* Activity 5: 12 timer-ticks *** critical section ***
169 Get the mutex with suspension */
170
171 status tx_mutex_get( & my_mutex, TX_WAIT_FOREVER);
172 if (status ! TX_SUCCESS) break; /* Check status */
173
174 tx_thread_sleep(12);
175
176 /* Release the mutex */
177 status tx_mutex_put( & my_mutex);
178 if (status ! TX_SUCCESS) break; /* Check status */
179
180 /* Activity 6: 8 timer-ticks */
181 tx_thread_sleep(8);
182
183 /* Activity 7: 11 timer-ticks *** critical section ***
184 Get the mutex with suspension */
185
186 status tx_mutex_get( & my_mutex, TX_WAIT_FOREVER);
187 if (status ! TX_SUCCESS) break; /* Check status */
188
189 tx_thread_sleep(11);