diff options
author | Chris Johns <chrisj@rtems.org> | 2007-08-17 01:07:10 +0000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2007-08-17 01:07:10 +0000 |
commit | 8db468ffde833523535720e8ec8119d760a9561a (patch) | |
tree | 11ac560f17473229c34809cbb8a2e737157f8372 /testsuites/samples | |
parent | 2007-08-17 Chris Johns <chrisj@rtems.org> (diff) | |
download | rtems-8db468ffde833523535720e8ec8119d760a9561a.tar.bz2 |
2007-08-17 Chris Johns <chrisj@rtems.org>
* Makefile.am, README, configure.ac, capture/.cvsignore,
capture/Makefile.am, capture/capture.doc, capture/capture.scn,
capture/init.c, capture/system.h, capture/test1.c: Add a sample
test for the capture engine.
Diffstat (limited to '')
-rw-r--r-- | testsuites/samples/ChangeLog | 7 | ||||
-rw-r--r-- | testsuites/samples/Makefile.am | 2 | ||||
-rw-r--r-- | testsuites/samples/README | 11 | ||||
-rw-r--r-- | testsuites/samples/capture/.cvsignore | 2 | ||||
-rw-r--r-- | testsuites/samples/capture/Makefile.am | 26 | ||||
-rw-r--r-- | testsuites/samples/capture/capture.doc | 508 | ||||
-rw-r--r-- | testsuites/samples/capture/capture.scn | 137 | ||||
-rw-r--r-- | testsuites/samples/capture/init.c | 73 | ||||
-rw-r--r-- | testsuites/samples/capture/system.h | 92 | ||||
-rw-r--r-- | testsuites/samples/capture/test1.c | 270 | ||||
-rw-r--r-- | testsuites/samples/configure.ac | 1 |
11 files changed, 1128 insertions, 1 deletions
diff --git a/testsuites/samples/ChangeLog b/testsuites/samples/ChangeLog index 7542d0cd96..8d8d29c68c 100644 --- a/testsuites/samples/ChangeLog +++ b/testsuites/samples/ChangeLog @@ -1,3 +1,10 @@ +2007-08-17 Chris Johns <chrisj@rtems.org> + + * Makefile.am, README, configure.ac, capture/.cvsignore, + capture/Makefile.am, capture/capture.doc, capture/capture.scn, + capture/init.c, capture/system.h, capture/test1.c: Add a sample + test for the capture engine. + 2007-07-24 Joel Sherrill <joel.sherrill@OARcorp.com> * nsecs/init.c: Add include of unistd.h for sleep() prototype. diff --git a/testsuites/samples/Makefile.am b/testsuites/samples/Makefile.am index b2afb0e8d5..82560d18ff 100644 --- a/testsuites/samples/Makefile.am +++ b/testsuites/samples/Makefile.am @@ -4,7 +4,7 @@ ACLOCAL_AMFLAGS = -I ../aclocal -SUBDIRS = hello ticker base_sp unlimited minimum fileio +SUBDIRS = hello capture ticker base_sp unlimited minimum fileio if MPTESTS ## base_mp is a sample multiprocessing test diff --git a/testsuites/samples/README b/testsuites/samples/README index b6e03a41f5..03234e95d7 100644 --- a/testsuites/samples/README +++ b/testsuites/samples/README @@ -42,6 +42,12 @@ The following describes each of the sample applications: This is intended as a starting point for custom developed single processor applications. + capture + + This simple application starts the monitor and allows you access + to the capture engine. The capture engine provides a trace of + RTEMS activity and is used to debug your application. + cdtest A very simple C++ application which demonstrates that it is @@ -70,3 +76,8 @@ The following describes each of the sample applications: This test has an initialization task create three application tasks which sleep and periodically wake up and print the time. + unlimited + + This is a test for the umlimited object feature of RTEMS. Here + you can configure RTEMS to give as many objects as memory + in the Workspace. diff --git a/testsuites/samples/capture/.cvsignore b/testsuites/samples/capture/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/testsuites/samples/capture/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/testsuites/samples/capture/Makefile.am b/testsuites/samples/capture/Makefile.am new file mode 100644 index 0000000000..6a22fbafa2 --- /dev/null +++ b/testsuites/samples/capture/Makefile.am @@ -0,0 +1,26 @@ +## +## $Id$ +## + +MANAGERS = io event + +rtems_tests_PROGRAMS = capture.exe +capture_exe_SOURCES = init.c test1.c system.h + +dist_rtems_tests_DATA = capture.scn +dist_rtems_tests_DATA += capture.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +unlimited_exe_LDADD = $(MANAGERS_NOT_WANTED:%=$(PROJECT_LIB)/no-%.rel) + +LINK_OBJS = $(capture_exe_OBJECTS) $(capture_exe_LDADD) +LINK_LIBS = $(capture_exe_LDLIBS) + +capture.exe$(EXEEXT): $(capture_exe_OBJECTS) $(capture_exe_DEPENDENCIES) + @rm -f capture.exe$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/samples/capture/capture.doc b/testsuites/samples/capture/capture.doc new file mode 100644 index 0000000000..5333dc643c --- /dev/null +++ b/testsuites/samples/capture/capture.doc @@ -0,0 +1,508 @@ +# +# $Id$ +# +# COPYRIGHT (c) 1989-1999. +# On-Line Applications Research Corporation (OAR). +# +# The license and distribution terms for this file may be +# found in the file LICENSE in this distribution or at +# http://www.rtems.com/license/LICENSE. +# + +Capture Engine Tutorial + +The Capture Engine is a software trace tool built into the RTEMS operating +system. Being software it does use CPU and memory resources. If do not use it +does not effect RTEMS or your application. The Capture Engine is designed to +placed the lowest load possible on the system when operating and when disabled +does not effect RTEMS. It binds to RTEMS at runtime and does not require RTEMS +or your application to be rebuilt inorder to use it. + +This tutorial will guide you through the building of RTEMS and the sample +programs for the pc586 BSP on Windows using the MinGW tools. The RTEMS Capture +Engine sample programmes are found in CVS and will be available in the next +release of RTEMS. The turoial will show how to create filters and triggers and +how to obtain a trace of the tasks running. The Capture Engine Command Line +Interface (CLI) will be used as this currently is the only available interface +to the Capture Engine. + +The tutorial uses the PC586 BSP running under QEMU. This provides a stable +environment that be easly duplicated on readly available hardware. If you are +new to RTEMS, simulators helps you get RTEMS running quickly. The RTEMS Wiki +provides the information needed to download and install these tools. + +In this tutorial I have placed the RTEMS source code into the Windows +directory: + + c:\rtems\src\rtems-4.7.0 + +RTEMS is configured using the shell MSYS with this command: + + $ /c/rtems/src + $ mkdir pc586 + $ cd pc586 + $ /c/rtems/src/rtems-4.7.0/configure --target=i386-rtems4.8 \ + --enable-network --enable-posix --enable-itron \ + --enable-tests=samples --enable-maintainer-mode \ + --enable-cxx --enable-rtems-bsp=pc586 + $ make all + +If you wish to use the Windows Command prompt open an RTEMS Command prompt +window by running the c:\rtems\i386\rtems-cmd.bat batch file from Explorer. The +shell commands become: + + RTEMS(i386) C:\rtems\i386> cd ..\src + RTEMS(i386) C:\rtems\src> mkdir pc586 + RTEMS(i386) C:\rtems\src> cd pc586 + RTEMS(i386) C:\rtems\src\pc586> sh /c/rtems/src/rtems-4.7.0/configure + --target=i386-rtems4.7 --enable-network --enable-posix --enable-itron + --enable-tests=samples --enable-maintainer-mode --enable-cxx + --enable-rtems-bsp=pc586 + RTEMS(i386) C:\rtems\src\pc586> make all + +Install the Windows version of QEMU and run with the following command: + + RTEMS(i386) C:\rtems\src\pc586> type c:\rtems\i386\bin\qemu.bat + rem @echo off + set QEMU=C:\rtems\i386\qemu-0.8.2-windows + %QEMU%\qemu -L %QEMU% -m 128 -boot a -fda c:\rtems\i386\rtems-boot.img + -hda fat:%1 %2 %3 + +You will need to download the GRUB boot loader image from the RTEMS +website. This image will boot the QEMU PC and attempt to read a GRUB +configuration file from the hda root directory. You pass the qemu.bat file the +path on your disk to the hda root directory. The capture engine examples are in +the standard testsuite examples directory. For our Windows host once built they +are in: + + rtems\src\pc586\i386-rtems4.8\c\pc586\testsuites\samples + +In this directory create a GRUB configuration file with an entry similar to +this one: + + RTEMS(i386) C:\rtems\src\pc586> type i386-rtems4.8\c\pc586\testsuites\sam + ples\rtems-grub.cfg + # RTEMS Grub configuration for the Samples + set default=0 + + menuentry "RTEMS - Capture" { + set root=(hd0,0) + multiboot (hd0,0)/capture/capture.exe + } + +It has a single entry the Capture Engine test. Change to the samples directory +and run QEMU using the QEMU batch file we created above: + + RTEMS(i386) C:\rtems\src\pc586> cd i386-rtems4.7\c\pc586\testsuites\samples + RTEMS(i386) C:\rtems\src\pc586\i386-rtems4.7\c\pc586\testsuites\samples> qemu . + +A QEMU console will open and you will see the GNU GRUB menu. The "RTEM - +Capture" menu item will be highlighted. Press Enter and GRUB will load and +execute the RTEMS Capture Engine example. + +RTEMS will only take a moment to initialise and you will be presented with the +RTEMS monitor login prompt: + + Initialized console on port CONSOLE + + + *** CAPTURE ENGING TEST *** + + Monitor ready, press enter to login. + + rtems $ + +The standard configuration is the Capture Engine not initialised and not +running. It needs to be initialised. You enter a trace buffer size in bytes +with the open command: + + rtems $ copen 5000 + capture engine open + rtems $ + +If you look in the Capture Engine example source code 'test1.c' a CLI command +'test1' is added to the RTEMS monitor. When you enter the 'test1' command the +'RMON' task will call 'capture_test_1()'. This function creates a task called +'CT1a' and starts it, then task 'CT1b' is created and started and finally +'CT1c' is created and started. All tasks are passed the object id of a +semaphore as a task argument. The RMON command thread then loops sleeping for 1 +second, waking to check if all of the tasks that have been created have been +deleted themselves. Once all tasks have been deleted the command returns +presenting the prompt to the user. + +The first task started is 'CT1a'. It obtains the mutex, waits 2.5 seconds, +releases it then deletes itself. The second task 'CT1b' loops until task 'CT1c' +has been deleted. The last task 'CT1c' also obtains the semaphore, waits 0.5 +seconds, releases the semaphore then deletes itself. + +The priority of RMON is 1 and is the highest priority task. The task 'CT1a' has +the lowest priority of 102, task 'CT1b' has a priority of 101, and 'CT1c' is the +highest priority of the three created tasks with 100. + +The test generates priority inheritance where task 'CT1a' inherits the priority +of task 'CT1c' and the Capture Engine captures this for you to observe. Task +'CT1a' obtains the semaphore with a priority of 102 then sleeps. Task 'CT1b' +consumes all of the CPU time with a priority of 101. Normally task 'CT1a' would +never run again. Task 'CT1c' runs and blocks waiting for the semaphore. When +task 'CT1a' wakes after 2.5 seconds it inherits the priority of task 'CT1c' +which is 100, higher than task 'CT1b'. Task 'CT1a' can now run and releases the +semaphore which task 'CT1c' obtains. After it wakes from a 0.5 second sleep it +releases the semaphore and deletes itself which causes task 'CT1b' to delete +itself. + +We could just open the capture engine, enable it and start tracing how-ever +there could be a large number of context switches before we get to our test and +the tasks events we are interested in. This would create a large amount of +trace noise and add extra load onto the system capturing this noise. A software +capture tool like this one is effective if we can filter the events recorded +into the trace buffer and if we can control when we trigger to start +recording. + +The simplest type of filter is the ceiling and floor priority filter. Here we +narrow the range of priorities captured. This is useful for applications which +typically have a middle range of priorites removing device type tasks such as +networking tasks or file system tasks as well as low priority back ground +tasks. Our test tasks have a priority range of 100 to 102. The filter is set +with the following commands: + + rtems $ cwceil 100 + watch ceiling 100. + rtems $ cwfloor 102 + watch floor is 102. + rtems $ + +We also need to enable the global watch. This causes all tasks in the priority +range to be captured: + + rtems $ cwglob on + global watch enabled. + rtems $ + +You can set or clear a trigger. To start with we will use the simplest trigger +we can have. This is just a task name. As the RMON task handles the RTEMS +monitor keyboard and executes the commands we shall trigger when this task +effects a task in our priority range. To set the trigger use this command: + + rtems $ ctset RMON + trigger set. + rtems $ cwlist + watch priority ceiling is 100 + watch priority floor is 102 + global watch is enabled + total 1 + 00000000 RMON g- T:S------ F:----- + rtems $ + +The 'cwlist' command lists the watch and trigger configuration. You will see +the RMON trigger line has a number, a label and flags. Later you will be given +more detail on these values. The number is an RTEMS object id. It is 0 which +means use the label when looking for the trigger. We could have entered the +task id for RMON in the trigger rather than the label. + +The capture engine is disabled after being opened and needs to be enabled. The +ability to enable and disable the capture engine with a single command allows +you to remove any effect the capture may have on the application while you are +tracing a problem. To enable enter: + + rtems $ cenable + capture engine enabled. + rtems $ + +To dump a recorded the trace you enter: + + rtems $ ctrace + rtems $ + +The trace buffer is empty. Notice how the capture engine is not triggering on +the RMON task or the execution of any other tasks that may be in the +system. Every monitor key press causes the RMON task to be switched in to +run. It is now time to run the test so enter the 'test1' command: + + rtems $ test1 + rtems $ + +After a few seconds the RTEMS monitor prompt will return and we can dump the +trace. + + rtems $ ctrace + 91.980000 0a010002 RMON 1 1 CREATED_BY + 91.980000 0a010003 CT1a 102 102 CREATED + 91.980000 0a010002 RMON 1 1 STARTED_BY + 91.980000 0a010003 CT1a 102 102 STARTED + 91.980000 0a010003 CT1a 102 102 SWITCHED_IN + 91.980000 0a010003 CT1a 102 102 BEGIN + 91.980000 0a010003 CT1a 102 102 SWITCHED_OUT + 92.980000 0a010002 RMON 1 1 CREATED_BY + 92.980000 0a010004 CT1b 101 101 CREATED + 92.980000 0a010002 RMON 1 1 STARTED_BY + 92.980000 0a010004 CT1b 101 101 STARTED + 92.980000 0a010004 CT1b 101 101 SWITCHED_IN + 92.980000 0a010004 CT1b 101 101 BEGIN + 93.980000 0a010004 CT1b 101 101 SWITCHED_OUT + 93.980000 0a010002 RMON 1 1 CREATED_BY + 93.980000 0a010004 CT1c 100 100 CREATED + 93.980000 0a010002 RMON 1 1 STARTED_BY + 93.980000 0a010005 CT1c 100 100 STARTED + 93.980000 0a010005 CT1c 100 100 SWITCHED_IN + 93.980000 0a010005 CT1c 100 100 BEGIN + 93.980000 0a010005 CT1c 100 100 SWITCHED_OUT + 93.980000 0a010004 CT1b 101 101 SWITCHED_IN + rtems $ + +The trace dump command by default displays 24 trace records. We have more so +enter the trace command until all have been displayed. The details of the trace +data will be discussed once we have all the trace data. + + rtems $ ctrace + 94.480000 0a010004 CT1b 101 101 SWITCHED_OUT + 94.480000 0a010003 CT1a 102 100 SWITCHED_IN + 94.480000 0a010003 CT1a 102 102 SWITCHED_OUT + 94.480000 0a010005 CT1c 100 100 SWITCHED_IN + 94.480000 0a010005 CT1c 100 100 SWITCHED_OUT + 94.480000 0a010004 CT1b 101 101 SWITCHED_IN + 94.980000 0a010004 CT1b 101 101 SWITCHED_OUT + 94.980000 0a010005 CT1c 100 100 SWITCHED_IN + 94.980000 0a010005 CT1c 100 100 DETELED_BY + 94.980000 0a010005 CT1c 100 100 DETELED + 94.980000 0a010004 CT1b 101 101 SWITCHED_IN + 94.980000 0a010004 CT1b 101 101 DELETED_BY + 94.980000 0a010004 CT1b 101 101 DELETED + 94.980000 0a010003 CT1a 102 100 SWITCHED_IN + 94.980000 0a010003 CT1a 102 100 DELETED_BY + 94.980000 0a010003 CT1a 102 100 DELETED + rtems $ + +The first column of the trace data is the time stamp. The test command started +when the time stamp was 91.98 seconds and took 3 seconds to run. Your trace +will have a different starting value but the total time should be 3 +seconds. The actual start value is the time it takes you to enter the various +capture commands. It would seem I am rather slow. + +The second column is the object id. In this case they are task ids. The third +column is the object name. + +The fourth is the real task priority and fifth column is the executing task +priority. The executing priority follows any priority inheritance. The last +column is the event the capture engine has captured. + +The first couple of records: + + 91.980000 0a010002 RMON 1 1 CREATED_BY + 91.980000 0a010003 CT1a 102 102 CREATED + +show at 91.98 seconds task id '0a010002' named 'RMON' with a priority of 1 and +executing at a priority of 1 created task id '0a010003' named 'CT1a' with a +priority of 102 and an executing priority of 102. Next 'RMON' started 'CT1a' +and it was switch into context, began running, then was switched out. + + 91.980000 0a010002 RMON 1 1 STARTED_BY + 91.980000 0a010003 CT1a 102 102 STARTED + 91.980000 0a010003 CT1a 102 102 SWITCHED_IN + 91.980000 0a010003 CT1a 102 102 BEGIN + 91.980000 0a010003 CT1a 102 102 SWITCHED_OUT + +The task 'CT1a' was switched out because it blocked on the semaphore. + +If you look at the 'test1' command's code you will see the command sleeps for 1 +second after starting the task. This is why the lower priority task 'CT1a' is +switched in and able to run. The sleep can be seen in the next event where +'RMON' creates 'CT1b'. The timestamp is 1 second later. + + 92.980000 0a010002 RMON 1 1 CREATED_BY + 92.980000 0a010004 CT1b 101 101 CREATED + 92.980000 0a010002 RMON 1 1 STARTED_BY + 92.980000 0a010004 CT1b 101 101 STARTED + 92.980000 0a010004 CT1b 101 101 SWITCHED_IN + 92.980000 0a010004 CT1b 101 101 BEGIN + 93.980000 0a010004 CT1b 101 101 SWITCHED_OUT + +There are no 'RMON' switched in or switched out events. These are being +filtered by the priority range filter. We see the 'RMON' CREATED_BY events as +these are actually occuring on test tasks which are in the priority range. + +The create and start process is repeated for the remaining two tasks. The +following section of the trace show 'CT1c' being switch out and 'CT1b' being +switch in. Task 'CT1b' loops consuming all of the CPU time until 'CT1a' +wakes. This is 500 milli-seconds. + + 93.980000 0a010005 CT1c 100 100 BEGIN + 93.980000 0a010005 CT1c 100 100 SWITCHED_OUT + 93.980000 0a010004 CT1b 101 101 SWITCHED_IN + 94.480000 0a010004 CT1b 101 101 SWITCHED_OUT + 94.480000 0a010003 CT1a 102 100 SWITCHED_IN + +When 'CT1a' wakes it is executing at the priority of 'CT1c' of 100 and so +higher than 'CT1b'. Task 'CT1a' then releases the semaphore dropping it +priority back to 102 allowing 'CT1c' to run. + + 94.480000 0a010003 CT1a 102 102 SWITCHED_OUT + 94.480000 0a010005 CT1c 100 100 SWITCHED_IN + 94.480000 0a010005 CT1c 100 100 SWITCHED_OUT + 94.480000 0a010004 CT1b 101 101 SWITCHED_IN + 94.980000 0a010004 CT1b 101 101 SWITCHED_OUT + 94.980000 0a010005 CT1c 100 100 SWITCHED_IN + +Task 'CT1c' release the semaphore and deletes itself. Task 'CT1b' is switched +in and it is looping waiting for 'CT1c' to delete. This has happen so 'CT1b' +deletes itself. Finally 'CT1a' deletes itself. + + 94.980000 0a010005 CT1c 100 100 DETELED_BY + 94.980000 0a010005 CT1c 100 100 DETELED + 94.980000 0a010004 CT1b 101 101 SWITCHED_IN + 94.980000 0a010004 CT1b 101 101 DELETED_BY + 94.980000 0a010004 CT1b 101 101 DELETED + 94.980000 0a010003 CT1a 102 100 SWITCHED_IN + 94.980000 0a010003 CT1a 102 100 DELETED_BY + 94.980000 0a010003 CT1a 102 100 DELETED + +The delete event shows the task deleting itself as the DELETED_BY event is the +same as the DELETED event. + +We will now explore some more complex filters and triggers. First close the +QEMU window and start QEMU again and open and enable the capture engine: + + rtems $ copen 5000 + capture engine open + rtems $ cenable + capture engine enabled. + rtems $ + +In this example we only want to monitor task 'CT1c' and wish to trigger on a +context switch from 'CT1c' to 'CT1a'. This happens when 'CT1a' releases the +semaphore and CT1c claims it. The set up is: + + rtems $ cwadd CT1c + watch added. + rtems $ cwctl CT1c on + watch enabled. + rtems $ ctset switch CT1c from CT1a + trigger set. + rtems $ cwlist + watch priority ceiling is 0 + watch priority floor is 0 + global watch is disabled + total 1 + 00000000 CT1c -w T:------- F:----- + 0:CT1a/00000000:S---- + rtems $ + +We run the test and capture the output: + + rtems $ test1 + rtems $ ctrace + 61.150000 0a010005 CT1c 100 100 SWITCHED_IN + 61.150000 0a010005 CT1c 100 100 SWITCHED_OUT + 61.650000 0a010005 CT1c 100 100 SWITCHED_IN + 61.650000 0a010005 CT1c 100 100 DELETED_BY + 61.650000 0a010005 CT1c 100 100 DELETED + rtems $ + +The trace shows CT1c being switched in once it has the semaphore then switching +out while it waits 500 milli-seconds, waking and being switched in to delete +itself. The filtering means we can focus on the specific events which we are +interested in and the trigger means we only trace once the specific event we +are interested in occurs. + +The filter and trigger do not need to relate. Lets run a variation of the last +configuation where we watch 'CT1b' and trigger on 'CT1c' being switched to from +'CT1a'. Close the QEMU window and start QEMU again and open and enable the +capture engine: + + rtems $ copen 5000 + capture engine open + rtems $ cenable + capture engine enabled. + rtems $ cwadd CT1b + watch added. + rtems $ cwctl CT1b on + watch enabled. + rtems $ ctset switch CT1c from CT1a + trigger set. + rtems $ cwlist + watch priority ceiling is 0 + watch priority floor is 0 + global watch is disabled + total 2 + 00000000 CT1c -- T:------- F:----- + 0:CT1a/00000000:S---- + 00000000 CT1b -w T:------- F:----- + rtems $ + +You can see 2 watch controls exist, one for the trigger and one for the filter. +Before we run the test we will take a look at the task list using the 'ctlist'. + + rtems $ ctlist + total 2 + 09010001 IDLE 255 255 255 READY a--- 0% 0% (10682) + 0a010002 RMON 1 1 1 READY a--- 0% 0% (826) + rtems $ + +You can see the 2 tasks that are active. These tasks existed before the capture +engine started. The capture engine learns about tasks that exist in a system if +they do something. If a task exists and does nothing the capture engine will +not know about it. Lets run the test then list the tasks again: + + rtems $ test1 + rtems $ ctlist + total 3 + 0a010004 CT1b 101 0 0 READY dtw- 100% 0% (200) + 09010001 IDLE 255 255 255 READY a--- 0% 0% (10682) + 0a010002 RMON 1 1 1 READY a--- 0% 0% (826) + rtems $ + +This time the task lists the test task we are watching 'CT1b'. If how-ever has +been deleted and the task list shows this with the 'd' in the flags. The active +tasks have an 'a'. The capture engine has to retain information on tasks that +have been deleted so the trace data can be generated. The trace buffer holds a +reference to the task's details not the specific details. Once the trace data +has been viewed the task data is no longer needed and released. + + rtems $ ctrace + 551.630000 0a010004 CT1b 101 101 SWITCHED_IN + 552.130000 0a010004 CT1b 101 101 SWITCHED_OUT + 552.130000 0a010004 CT1b 101 101 SWITCHED_IN + 552.130000 0a010004 CT1b 101 101 DELETED_BY + 552.130000 0a010004 CT1b 101 101 DELETED + rtems $ ctlist + total 2 + 09010001 IDLE 255 255 255 READY a--- 0% 0% (10682) + 0a010002 RMON 1 1 1 READY a--- 0% 0% (826) + rtems $ + +Listing the tasks shows 'CT1b' has gone. The trace buffer does not reference +it any more. + +We have now seen the following capture commands: + + copen + cenable + ctlist + cwceil + cwfloor + cwglob + cwadd + cwctl + ctset + ctrace + +The ctset is worth a closer look. The general form of the command is: + + ctset [-?] type [to name/id] [from] [from name/id] + +The 'type' is the type of trigger. The following possible types of triggers +exist: + + switch - a context switch from one task to another task + create - the executing task creates a task + start - the executing task starts a task + restart - the executing task restarts a task + delete - the executing task deletes a task + begin - a task is beginning + exitted - a task is exitting + +With the ctset command you set a trigger for a task. If you do not supply a +from task the type of event can be from any task. You can be more specific by +stating the event for a task must be by a specific task. Looking at the examples +from before we set a trigger on a context switch from CT1a to CT1c with: + + ctset switch CT1c from CT1a diff --git a/testsuites/samples/capture/capture.scn b/testsuites/samples/capture/capture.scn new file mode 100644 index 0000000000..57e045e1a9 --- /dev/null +++ b/testsuites/samples/capture/capture.scn @@ -0,0 +1,137 @@ +*** CAPTURE ENGING TEST *** + +Monitor ready, press enter to login. + +rtems $ +rtems $ copen 5000 +capture engine open +rtems $ cwceil 100 +watch ceiling 100. +rtems $ cwfloor 102 +watch floor is 102. +rtems $ cwglob on +global watch enabled. +rtems $ ctset RMON +trigger set. +rtems $ cwlist +watch priority ceiling is 100 +watch priority floor is 102 +global watch is enabled +total 1 + 00000000 RMON g- T:S------ F:----- +rtems $ cenable +capture engine enabled. +rtems $ ctrace +rtems $ test1 +rtems $ ctrace + 91.980000 0a010002 RMON 1 1 CREATED_BY + 91.980000 0a010003 CT1a 102 102 CREATED + 91.980000 0a010002 RMON 1 1 STARTED_BY + 91.980000 0a010003 CT1a 102 102 STARTED + 91.980000 0a010003 CT1a 102 102 SWITCHED_IN + 91.980000 0a010003 CT1a 102 102 BEGIN + 91.980000 0a010003 CT1a 102 102 SWITCHED_OUT + 92.980000 0a010002 RMON 1 1 CREATED_BY + 92.980000 0a010004 CT1b 101 101 CREATED + 92.980000 0a010002 RMON 1 1 STARTED_BY + 92.980000 0a010004 CT1b 101 101 STARTED + 92.980000 0a010004 CT1b 101 101 SWITCHED_IN + 92.980000 0a010004 CT1b 101 101 BEGIN + 93.980000 0a010004 CT1b 101 101 SWITCHED_OUT + 93.980000 0a010002 RMON 1 1 CREATED_BY + 93.980000 0a010004 CT1c 100 100 CREATED + 93.980000 0a010002 RMON 1 1 STARTED_BY + 93.980000 0a010005 CT1c 100 100 STARTED + 93.980000 0a010005 CT1c 100 100 SWITCHED_IN + 93.980000 0a010005 CT1c 100 100 BEGIN + 93.980000 0a010005 CT1c 100 100 SWITCHED_OUT + 93.980000 0a010004 CT1b 101 101 SWITCHED_IN +rtems $ ctrace + 94.480000 0a010004 CT1b 101 101 SWITCHED_OUT + 94.480000 0a010003 CT1a 102 100 SWITCHED_IN + 94.480000 0a010003 CT1a 102 102 SWITCHED_OUT + 94.480000 0a010005 CT1c 100 100 SWITCHED_IN + 94.480000 0a010005 CT1c 100 100 SWITCHED_OUT + 94.480000 0a010004 CT1b 101 101 SWITCHED_IN + 94.980000 0a010004 CT1b 101 101 SWITCHED_OUT + 94.980000 0a010005 CT1c 100 100 SWITCHED_IN + 94.980000 0a010005 CT1c 100 100 DETELED_BY + 94.980000 0a010005 CT1c 100 100 DETELED + 94.980000 0a010004 CT1b 101 101 SWITCHED_IN + 94.980000 0a010004 CT1b 101 101 DELETED_BY + 94.980000 0a010004 CT1b 101 101 DELETED + 94.980000 0a010003 CT1a 102 100 SWITCHED_IN + 94.980000 0a010003 CT1a 102 100 DELETED_BY + 94.980000 0a010003 CT1a 102 100 DELETED + +*** CAPTURE ENGING TEST *** + +Monitor ready, press enter to login. + +rtems $ copen 5000 +capture engine open +rtems $ cenable +capture engine enabled. +rtems $ cwadd CT1c +watch added. +rtems $ cwctl CT1c on +watch enabled. +rtems $ ctset switch CT1c from CT1a +trigger set. +rtems $ cwlist +watch priority ceiling is 0 +watch priority floor is 0 +global watch is disabled +total 1 + 00000000 CT1c -w T:------- F:----- + 0:CT1a/00000000:S---- +rtems $ test1 +rtems $ ctrace + 61.150000 0a010005 CT1c 100 100 SWITCHED_IN + 61.150000 0a010005 CT1c 100 100 SWITCHED_OUT + 61.650000 0a010005 CT1c 100 100 SWITCHED_IN + 61.650000 0a010005 CT1c 100 100 DELETED_BY + 61.650000 0a010005 CT1c 100 100 DELETED + +*** CAPTURE ENGING TEST *** + +Monitor ready, press enter to login. + +rtems $ copen 5000 +capture engine open +rtems $ cenable +capture engine enabled. +rtems $ cwadd CT1b +watch added. +rtems $ cwctl CT1b on +watch enabled. +rtems $ ctset switch CT1c from CT1a +trigger set. +rtems $ cwlist +watch priority ceiling is 0 +watch priority floor is 0 +global watch is disabled +total 2 + 00000000 CT1c -- T:------- F:----- + 0:CT1a/00000000:S---- + 00000000 CT1b -w T:------- F:----- +rtems $ ctlist +total 2 + 09010001 IDLE 255 255 255 READY a--- 0% 0% (10682) + 0a010002 RMON 1 1 1 READY a--- 0% 0% (826) +rtems $ test1 +rtems $ ctlist +total 3 + 0a010004 CT1b 101 0 0 READY dtw- 100% 0% (200) + 09010001 IDLE 255 255 255 READY a--- 0% 0% (10682) + 0a010002 RMON 1 1 1 READY a--- 0% 0% (826) +rtems $ ctrace + 551.630000 0a010004 CT1b 101 101 SWITCHED_IN + 552.130000 0a010004 CT1b 101 101 SWITCHED_OUT + 552.130000 0a010004 CT1b 101 101 SWITCHED_IN + 552.130000 0a010004 CT1b 101 101 DELETED_BY + 552.130000 0a010004 CT1b 101 101 DELETED +rtems $ ctlist +total 2 + 09010001 IDLE 255 255 255 READY a--- 0% 0% (10682) + 0a010002 RMON 1 1 1 READY a--- 0% 0% (826) diff --git a/testsuites/samples/capture/init.c b/testsuites/samples/capture/init.c new file mode 100644 index 0000000000..891d342b46 --- /dev/null +++ b/testsuites/samples/capture/init.c @@ -0,0 +1,73 @@ +/* Init
+ *
+ * This routine is the initialization task for this test program.
+ * It is called from init_exec and has the responsibility for creating
+ * and starting the tasks that make up the test. If the time of day
+ * clock is required for the test, it should also be set to a known
+ * value by this function.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#define CONFIGURE_INIT
+
+#include "system.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rtems.h>
+#include <rtems/capture-cli.h>
+#include <rtems/monitor.h>
+
+void setup_tasks_to_watch ();
+
+volatile int can_proceed = 1;
+
+rtems_task Init(
+ rtems_task_argument ignored
+)
+{
+ rtems_task_priority old_priority;
+ rtems_mode old_mode;
+ rtems_event_set out;
+
+ /* lower the task priority to allow created tasks to execute */
+
+ rtems_task_set_priority(RTEMS_SELF, 20, &old_priority);
+ rtems_task_mode(RTEMS_PREEMPT, RTEMS_PREEMPT_MASK, &old_mode);
+
+ printf( "\n*** CAPTURE ENGINE TEST ***\n" );
+
+ while (!can_proceed)
+ {
+ printf ("Sleeping\n");
+ usleep (1000000);
+ }
+
+ rtems_monitor_init (0);
+ rtems_capture_cli_init (0);
+
+ setup_tasks_to_watch ();
+
+ rtems_task_delete (RTEMS_SELF);
+
+ printf( "\nblocking main\n" );
+
+ rtems_event_receive (RTEMS_EVENT_1, RTEMS_WAIT | RTEMS_EVENT_ANY,
+ 0, &out);
+
+ printf( "\n*** END OF UNLIMITED TASK TEST ***\n" );
+ exit( 0 );
+}
+
diff --git a/testsuites/samples/capture/system.h b/testsuites/samples/capture/system.h new file mode 100644 index 0000000000..d4d6b6dce5 --- /dev/null +++ b/testsuites/samples/capture/system.h @@ -0,0 +1,92 @@ +/* system.h
+ *
+ * This include file contains information that is included in every
+ * function in the test set.
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+
+/* functions */
+
+rtems_task Init(
+ rtems_task_argument argument
+);
+
+rtems_task test_task(
+ rtems_task_argument my_number
+);
+
+void
+destory_all_tasks(
+ const char *who
+);
+
+boolean status_code_bad(
+ rtems_status_code status_code
+);
+
+void test1();
+void test2();
+void test3();
+
+/* configuration information */
+
+#include <bsp.h> /* for device driver prototypes */
+
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define TASK_ALLOCATION_SIZE (5)
+#define CONFIGURE_MAXIMUM_TASKS rtems_resource_unlimited(TASK_ALLOCATION_SIZE)
+#define CONFIGURE_EXTRA_TASK_STACKS (75 * RTEMS_MINIMUM_STACK_SIZE)
+
+#define CONFIGURE_MAXIMUM_USER_EXTENSIONS (5)
+
+#include <rtems/confdefs.h>
+
+/*
+ * Keep track of the task id's created, use a large array.
+ */
+
+#define MAX_TASKS (1000)
+#define TASK_INDEX_OFFSET (1)
+
+extern rtems_id task_id[MAX_TASKS];
+
+/*
+ * Increment the task name.
+ */
+
+#define NEXT_TASK_NAME(c1, c2, c3, c4) \
+ if (c4 == '9') { \
+ if (c3 == '9') { \
+ if (c2 == 'z') { \
+ if (c1 == 'z') { \
+ printf("not enough task letters for names !!!\n"); \
+ exit( 1 ); \
+ } else \
+ c1++; \
+ c2 = 'a'; \
+ } else \
+ c2++; \
+ c3 = '0'; \
+ } else \
+ c3++; \
+ c4 = '0'; \
+ } \
+ else \
+ c4++ \
+
+
+/* end of include file */
diff --git a/testsuites/samples/capture/test1.c b/testsuites/samples/capture/test1.c new file mode 100644 index 0000000000..cfe6abae5c --- /dev/null +++ b/testsuites/samples/capture/test1.c @@ -0,0 +1,270 @@ +/* Test1
+ *
+ * This test uses creates a number of tasks so the capture engine
+ * can show a trace.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include "system.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+static volatile int capture_CT1a_deleted;
+static volatile int capture_CT1b_deleted;
+static volatile int capture_CT1c_deleted;
+
+static void
+capture_wait (uint32_t period)
+{
+ rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (period * 1000));
+}
+
+/*
+ * CT1a: Claim the mutex and then wait a while then wake
+ * up and release the mutex. While this task waits with
+ * the mutex another higher priority task is started that
+ * just loops using all the processing time. It is not until
+ * another even higher priority thread blocks on the mutex
+ * does this task get raised to that priority and so
+ * releases the mutex. This will allow us to capture the
+ * action of priority inversion.
+ */
+static void
+capture_CT1a (rtems_task_argument arg)
+{
+ rtems_id mutex = (rtems_id) arg;
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_obtain (mutex, RTEMS_WAIT, 0);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ fprintf (stdout, "error: CT1a: mutex obtain: %s\n",
+ rtems_status_text (sc));
+
+ capture_wait (2500);
+
+ sc = rtems_semaphore_release (mutex);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ fprintf (stdout, "error: CT1a: mutex release: %s\n",
+ rtems_status_text (sc));
+
+ capture_CT1a_deleted = 1;
+
+ rtems_task_delete (RTEMS_SELF);
+}
+
+static void
+capture_CT1b (rtems_task_argument arg)
+{
+ volatile int i;
+
+ while (!capture_CT1c_deleted)
+ i++;
+
+ capture_CT1b_deleted = 1;
+
+ rtems_task_delete (RTEMS_SELF);
+}
+
+static void
+capture_CT1c (rtems_task_argument arg)
+{
+ rtems_id mutex = (rtems_id) arg;
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_obtain (mutex, RTEMS_WAIT, 0);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ fprintf (stdout, "error: CT1c: mutex obtain: %s\n",
+ rtems_status_text (sc));
+
+ capture_wait (500);
+
+ sc = rtems_semaphore_release (mutex);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ fprintf (stdout, "error: CT1c: mutex release: %s\n",
+ rtems_status_text (sc));
+
+ capture_CT1c_deleted = 1;
+
+ rtems_task_delete (RTEMS_SELF);
+}
+
+static void
+capture_test_1 (int argc,
+ char** argv,
+ rtems_monitor_command_arg_t* command_arg,
+ boolean verbose)
+{
+ rtems_status_code sc;
+ rtems_name name;
+ rtems_id id[3];
+ rtems_id mutex;
+ int loops;
+
+ capture_CT1a_deleted = 0;
+ capture_CT1b_deleted = 0;
+ capture_CT1c_deleted = 0;
+
+ name = rtems_build_name('C', 'T', 'm', '1');
+
+ sc = rtems_semaphore_create (name, 1,
+ RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE |
+ RTEMS_INHERIT_PRIORITY,
+ 0, &mutex);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: Test 1: cannot mutex: %s\n",
+ rtems_status_text (sc));
+ return;
+ }
+
+ name = rtems_build_name('C', 'T', '1', 'a');
+
+ sc = rtems_task_create (name, 102, 2 * 1024,
+ RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
+ RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,
+ &id[0]);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: Test 1: cannot create CT1a: %s\n",
+ rtems_status_text (sc));
+ rtems_semaphore_delete (mutex);
+ return;
+ }
+
+ sc = rtems_task_start (id[0], capture_CT1a, (rtems_task_argument) mutex);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: Test 1: cannot start CT1a: %s\n",
+ rtems_status_text (sc));
+ rtems_task_delete (id[0]);
+ rtems_semaphore_delete (mutex);
+ return;
+ }
+
+ capture_wait (1000);
+
+ name = rtems_build_name('C', 'T', '1', 'b');
+
+ sc = rtems_task_create (name, 101, 2 * 1024,
+ RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
+ RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,
+ &id[1]);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: Test 1: cannot create CT1b: %s\n",
+ rtems_status_text (sc));
+ rtems_task_delete (id[0]);
+ rtems_semaphore_delete (mutex);
+ return;
+ }
+
+ sc = rtems_task_start (id[1], capture_CT1b, 0);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: Test 1: cannot start CT1b: %s\n",
+ rtems_status_text (sc));
+ rtems_task_delete (id[1]);
+ rtems_task_delete (id[0]);
+ rtems_semaphore_delete (mutex);
+ return;
+ }
+
+ capture_wait (1000);
+
+ name = rtems_build_name('C', 'T', '1', 'c');
+
+ sc = rtems_task_create (name, 100, 2 * 1024,
+ RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
+ RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,
+ &id[2]);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: Test 1: cannot create CT1c: %s\n",
+ rtems_status_text (sc));
+ rtems_task_delete (id[1]);
+ rtems_task_delete (id[0]);
+ rtems_semaphore_delete (mutex);
+ return;
+ }
+
+ sc = rtems_task_start (id[2], capture_CT1c, (rtems_task_argument) mutex);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: Test 1: cannot start CT1c: %s\n",
+ rtems_status_text (sc));
+ rtems_task_delete (id[2]);
+ rtems_task_delete (id[1]);
+ rtems_task_delete (id[0]);
+ rtems_semaphore_delete (mutex);
+ return;
+ }
+
+ loops = 15;
+
+ while (!(capture_CT1a_deleted || capture_CT1b_deleted ||
+ capture_CT1c_deleted) && loops)
+ {
+ loops--;
+ capture_wait (1000);
+ }
+
+ if (!loops)
+ {
+ fprintf (stdout, "error: Test 1: test tasks did not delete\n");
+ rtems_task_delete (id[2]);
+ rtems_task_delete (id[1]);
+ rtems_task_delete (id[0]);
+ }
+
+ sc = rtems_semaphore_delete (mutex);
+ if (sc != RTEMS_SUCCESSFUL)
+ fprintf (stdout, "error: Test 1: deleting the mutex: %s\n",
+ rtems_status_text (sc));
+}
+
+static rtems_monitor_command_entry_t capture_cmds[] =
+{
+ {
+ "test1",
+ "usage: \n",
+ 0,
+ capture_test_1,
+ { 0 },
+ 0
+ }
+};
+
+void setup_tasks_to_watch ()
+{
+ int cmd;
+ for (cmd = 0;
+ cmd < sizeof (capture_cmds) / sizeof (rtems_monitor_command_entry_t);
+ cmd++)
+ rtems_monitor_insert_cmd (&capture_cmds[cmd]);
+}
diff --git a/testsuites/samples/configure.ac b/testsuites/samples/configure.ac index bf19dbe2e9..3e7636b37e 100644 --- a/testsuites/samples/configure.ac +++ b/testsuites/samples/configure.ac @@ -75,5 +75,6 @@ base_mp/node2/Makefile iostream/Makefile cdtest/Makefile pppd/Makefile +capture/Makefile ]) AC_OUTPUT |