Instrument buffers can be used to find out how many events of a given type happened in the kernel during execution of a program.
You can monitor a class of several types of events, or you can just look at individual events.
Examples of events that can be monitored are:
scheduler events
thread operations
interrupts
mutex operations
binary semaphore operations
counting semaphore operations
clock ticks and interrupts
Examples of fine-grained scheduler event types are:
scheduler lock
scheduler unlock
rescheduling
time slicing
Information about the events is stored in an event record. The structure that defines this record has type struct Instrument_Record:
The list of records is stored in an array called instrument_buffer which you can let the kernel provide or you can provide yourself by setting the configuration option CYGVAR_KERNEL_INSTRUMENT_EXTERNAL_BUFFER.
To write a program that examines the instrumentation buffers:
Enable instrumentation buffers in the eCos kernel configuration. The component macro is CYGPKG_KERNEL_INSTRUMENT.
To allocate the buffers yourself, enable the configuration option CYGVAR_KERNEL_INSTRUMENT_EXTERNAL_BUFFER.
Include the header file cyg/kernel/instrmnt.h .
#include <cyg/kernel/instrmnt.h> |
The Instrumentation_Record structure is not published in the kernel header file. In the future there will be a cleaner mechanism to access it, but for now you should paste into your code in the following lines:
struct Instrument_Record { CYG_WORD16 type; // record type CYG_WORD16 thread; // current thread id CYG_WORD timestamp; // 32 bit timestamp CYG_WORD arg1; // first arg CYG_WORD arg2; // second arg }; |
Enable the events you want to record using cyg_instrument_enable() , and disable them later. Look at cyg/kernel/instrmnt.h and the examples below to see what events can be enabled.
Place the code you want to debug between the matching functions cyg_instrument_enable() and cyg_instrument_disable() .
Examine the buffer. For now you need to look at the data in there (the example program below shows how to do that), and future versions of eCos will include a host-side tool to help you understand the data.
Example 27-2. Using instrument buffers
This program is also provided in the examples directory.
/* this is a program which uses eCos instrumentation buffers; it needs
to be linked with a kernel which was compiled with support for
instrumentation */
#include <stdio.h>
#include <pkgconf/kernel.h>
#include <cyg/kernel/instrmnt.h>
#include <cyg/kernel/kapi.h>
#ifndef CYGVAR_KERNEL_INSTRUMENT_EXTERNAL_BUFFER
# error You must configure eCos with CYGVAR_KERNEL_INSTRUMENT_EXTERNAL_BUFFER
#endif
struct Instrument_Record
{
CYG_WORD16 type; // record type
CYG_WORD16 thread; // current thread id
CYG_WORD timestamp; // 32 bit timestamp
CYG_WORD arg1; // first arg
CYG_WORD arg2; // second arg
};
struct Instrument_Record instrument_buffer[20];
cyg_uint32 instrument_buffer_size = 20;
int main(void)
{
int i;
cyg_instrument_enable(CYG_INSTRUMENT_CLASS_CLOCK, 0);
cyg_instrument_enable(CYG_INSTRUMENT_CLASS_THREAD, 0);
cyg_instrument_enable(CYG_INSTRUMENT_CLASS_ALARM, 0);
printf("Program to play with instrumentation buffer\n");
cyg_thread_delay(2);
cyg_instrument_disable(CYG_INSTRUMENT_CLASS_CLOCK, 0);
cyg_instrument_disable(CYG_INSTRUMENT_CLASS_THREAD, 0);
cyg_instrument_disable(CYG_INSTRUMENT_CLASS_ALARM, 0);
for (i = 0; i < instrument_buffer_size; ++i) {
printf("Record %02d: type 0x%04x, thread %d, ",
i, instrument_buffer[i].type, instrument_buffer[i].thread);
printf("time %5d, arg1 0x%08x, arg2 0x%08x\n",
instrument_buffer[i].timestamp, instrument_buffer[i].arg1,
instrument_buffer[i].arg2);
}
return 0;
} |
Here is how you could compile and run this program in the examples directory, using (for example) the MN10300 simulator target:
$ make XCC=mn10300-elf-gcc INSTALL_DIR=/tmp/ecos-work-mn10300/install instrument-test mn10300-elf-gcc -c -o instrument-test.o -g -Wall -I/tmp/ecos-work-mn10300/install/include \ -ffunction-sections -fdata-sections instrument-test.c mn10300-elf-gcc -nostartfiles -L/tmp/ecos-work-mn10300/install/lib -W1,--gc-sections -o \ instrument-test instrument-test.o -Ttarget.ld -nostdlib $ mn10300-elf-run --board=stdeval1 instrument-test |
Example 27-3. Instrument buffer output
Here is the output of the instrument-test program. Notice that in little over 2 seconds, and with very little activity, and with few event types enabled, it gathered 17 records. In larger programs it will be necessary to select very few event types for debugging.
Program to play with instrumentation buffer Record 00: type 0x0207, thread 2, time 6057, arg1 0x48001cd8, arg2 0x00000002 Record 01: type 0x0202, thread 2, time 6153, arg1 0x48001cd8, arg2 0x00000000 Record 02: type 0x0904, thread 2, time 6358, arg1 0x48001d24, arg2 0x00000000 Record 03: type 0x0905, thread 2, time 6424, arg1 0x00000002, arg2 0x00000000 Record 04: type 0x0906, thread 2, time 6490, arg1 0x00000000, arg2 0x00000000 Record 05: type 0x0901, thread 2, time 6608, arg1 0x48009d74, arg2 0x48001d24 Record 06: type 0x0201, thread 2, time 6804, arg1 0x48001cd8, arg2 0x480013e0 Record 07: type 0x0803, thread 1, time 94, arg1 0x00000000, arg2 0x00000000 Record 08: type 0x0801, thread 1, time 361, arg1 0x00000000, arg2 0x00000000 Record 09: type 0x0802, thread 1, time 548, arg1 0x00000001, arg2 0x00000000 Record 10: type 0x0803, thread 1, time 94, arg1 0x00000000, arg2 0x00000000 Record 11: type 0x0801, thread 1, time 361, arg1 0x00000001, arg2 0x00000000 Record 12: type 0x0903, thread 1, time 513, arg1 0x48009d74, arg2 0x48001d24 Record 13: type 0x0208, thread 1, time 588, arg1 0x00000000, arg2 0x00000000 Record 14: type 0x0203, thread 1, time 697, arg1 0x48001cd8, arg2 0x480013e0 Record 15: type 0x0802, thread 1, time 946, arg1 0x00000002, arg2 0x00000000 Record 16: type 0x0201, thread 1, time 1083, arg1 0x480013e0, arg2 0x48001cd8 Record 17: type 0x0000, thread 0, time 0, arg1 0x00000000, arg2 0x00000000 Record 18: type 0x0000, thread 0, time 0, arg1 0x00000000, arg2 0x00000000 Record 19: type 0x0000, thread 0, time 0, arg1 0x00000000, arg2 0x00000000 |