View topic - Measuring the Interrupt Latency
Measuring the Interrupt Latency
13 posts
• Page 1 of 1
Measuring the Interrupt Latency
Hello,
I wrote an application with a main() routine and a postix thread. The main() triggers an interrupt pin on my system which is delayed due to a delay element.
The pthread uses a event.sigev_notify = SIGEV_INTR;and InterruptAttachEvent() call to attach the IRQ to the specific thread. The application and the measurement works fine, but when I generate load on the system with the stress tool (http://weather.ou.edu/~apw/projects/stress/) my latencys goes from 25-35 microseconds up to 100 milli seconds. Even when I change the Scheduler or the priority over the IDE for my application or directly for the thread in the sourceode to SCHED_FIFO and Priority 255, the latency doesn't drop.
Latency goes up too, when starting the photon environment from the console.
Anyone got a suggestion?
Thanks.
I wrote an application with a main() routine and a postix thread. The main() triggers an interrupt pin on my system which is delayed due to a delay element.
The pthread uses a event.sigev_notify = SIGEV_INTR;and InterruptAttachEvent() call to attach the IRQ to the specific thread. The application and the measurement works fine, but when I generate load on the system with the stress tool (http://weather.ou.edu/~apw/projects/stress/) my latencys goes from 25-35 microseconds up to 100 milli seconds. Even when I change the Scheduler or the priority over the IDE for my application or directly for the thread in the sourceode to SCHED_FIFO and Priority 255, the latency doesn't drop.
Latency goes up too, when starting the photon environment from the console.
Anyone got a suggestion?
Thanks.
- xcp
- Active Member
- Posts: 10
- Joined: Tue May 27, 2008 9:55 am
RE: Measuring the Interrupt Latency
100 milliseconds ?? Something is very wrong. Either it's the way you measure the latency or you aren't setting the priority properly. Can you post code?
- mario
- QNX Master
- Posts: 4132
- Joined: Sun Sep 01, 2002 1:04 am
RE: Measuring the Interrupt Latency
- Code: Select all
/*
* Diplomarbeit "Charakterisierung des Echtzeitverhaltens diverser Embedded Betriebssysteme"
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* This application is intended to measure the response time from triggering an interrupt until
* a thread reacts to the incoming interrupt.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* NOTE:
* The ClockCycles() kernel call returns the current value of a free-running 64-bit cycle
* counter. This is implemented on each processor as a high-performance mechanism for timing
* short intervals.
*
*/
#include <inttypes.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <unistd.h>
#include <sys/neutrino.h>
#include <sys/mman.h>
#include <sys/syspage.h>
#include <hw/inout.h>
/* ************************* DEFINES ****************************************** */
#define MY_DEBUG
#define MY_SCHEDULER SCHED_FIFO /* Use this scheduler for the thread */
#define MY_PRIORITY 255 /* Threadpriority */
#define NUM_MEASURE 200
#define DELAY_TIME_NS 100000 /* 50 us in ns */
/* The Neutrino parallel IO port used, corresponds to a single register, with one byte length */
#define PPT_PORT_LENGTH 1
#define PPT1_DATA 0x378
#define PPT1_CTRL 0x37a
#define PPT1_INIT 0x4 /* bit 2 = printer initialisation (high to initialise) bit 4 = hardware IRQ (high to enable) */
#define PPT1_IRQ 0x7
#define PPT1_INTR 0x10 /* bit 2 = printer initialisation (high to initialise) bit 4 = hardware IRQ (high to enable) */
#define PPT1_VAL 0x14
/* High Low values */
#define HIGH 0xff
#define LOW 0x0
/* ************************* GLOBAL VARIABLES ********************************* */
uintptr_t pptCtrlHdl;
uintptr_t pptDataHdl;
pthread_t* p_workThread;
uint64_t ui64_cc_start = 0;
uint64_t ui64_cc_stop = 0;
uint64_t ui64_cc_diff = 0;
uint64_t ui64_us_diff = 0;
int i_intID;
struct sigevent event;
/* ************************** PROTOTYPES ************************************** */
void* funcWorkThread(void* arg);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void* funcWorkThread(void* arg)
{
int err;
int i;
uint64_t ccpus;
FILE* file;
file = fopen( "values.txt" , "a+" );
#ifdef MY_DEBUG
printf("DEBUG: entered funcWorkThread\n");
#endif
err = ThreadCtl( _NTO_TCTL_IO, NULL );
if ( -1 == err )
{
printf( "Can't get root permission for triggerThread!\n" );
}
/* Determine ClockCycles() per micro second */
ccpus = ((SYSPAGE_ENTRY(qtime)->cycles_per_sec) / 1000000);
#ifdef MY_DEBUG
printf( "DEBUG: This system has %lld cycles/usec\n" , ccpus );
#endif
/* Tell the kernel to attach an interrupt signal event to this thread */
event.sigev_notify = SIGEV_INTR;
i_intID = InterruptAttachEvent( PPT1_IRQ , &event , 0 );
if ( i_intID == -1 )
{
printf( "Couldn't attach event to IRQ %d\n", PPT1_IRQ );
}
for ( i = 1 ; i <= NUM_MEASURE ; i++)
{
/* Sleep until the next interrupt */
InterruptWait( 0, NULL );
/* Record the time */
ui64_cc_stop = ClockCycles();
/* Calculate the ClockClycle difference between start and stop and substract the delay */
ui64_cc_diff = (ui64_cc_stop - ui64_cc_start - (DELAY_TIME_NS * ccpus));
/* Convert ClockCycles to micro seconds */
ui64_us_diff = (ui64_cc_diff/ccpus);
#ifdef MY_DEBUG
printf("ID: %i, latency: %lld ClockCycles or %lld us\n" , i , ui64_cc_diff , ui64_us_diff);
#endif
#ifndef MY_DEBUG
fprintf(file,"ID: %i, latency: %lld ClockCycles or %lld us\n" , i , ui64_cc_diff , ui64_us_diff);
#endif
/* Reenable this interrupt */
InterruptUnmask( PPT1_IRQ, i_intID );
}
InterruptDetach( i_intID );
return EXIT_SUCCESS;
}
int main()
{
int err;
int i;
pthread_attr_t attr;
struct sched_param param;
printf("\nDiplomarbeit Christian Poessinger <poessinger@mixed-mode.de>\n");
printf("\tCharakterisierung des Echtzeitverhaltens diverser Embedded Betriebssysteme\n\n");
err = ThreadCtl( _NTO_TCTL_IO, NULL );
if ( -1 == err )
{
printf( "Can't get root permission for triggerThread!\n" );
return EXIT_FAILURE;
}
param.sched_priority = MY_PRIORITY;
pthread_attr_init( &attr );
pthread_attr_setschedpolicy( &attr , MY_SCHEDULER);
pthread_attr_setschedparam( &attr , ¶m );
/* Create Handle for parallel port 1 CTRL register */
pptCtrlHdl = mmap_device_io( PPT_PORT_LENGTH , PPT1_CTRL );
/* Create Handle for parallel port 1 DATA register */
pptDataHdl = mmap_device_io( PPT_PORT_LENGTH , PPT1_DATA );
/* Initialise parallel port */
out8( pptCtrlHdl , PPT1_INIT );
/* Activate Interrupts on parallel port */
out8( pptCtrlHdl , PPT1_INTR );
pthread_create( p_workThread, &attr, &funcWorkThread, NULL );
printf("\n\t=> Beginne Messung!\n");
for ( i = 0 ; i <= (NUM_MEASURE+1) ; i++)
{
out8( pptDataHdl , LOW ); /* send LOW bit on PPT1 */
out8( pptDataHdl , HIGH ); /* send HIGH bit on PPT1 */
ui64_cc_start = ClockCycles(); /* get the current system clockcycles */
delay(30); /* delay in milli seconds */
out8( pptDataHdl , LOW ); /* send LOW bit on PPT1 */
delay(200); /* delay in milli seconds */
}
printf("\t=> Messung beendet!\n");
return EXIT_SUCCESS;
}
- xcp
- Active Member
- Posts: 10
- Joined: Tue May 27, 2008 9:55 am
RE: Measuring the Interrupt Latency
You can't really measure latency like that. The problem is that the interrupt might occurs in between out8() and ui64_cc_start = ClockCycles(), throwing the calculation off. I'm assuming the interrupt gets trigger when setting the bit on PPT1 to HIGH.
The (f)printf in the irq is not a good idea, although the process is high priority, if there is a request currently being performed by the related driver ( devc-con/devb-eide), they are queue. Hence these calls could make the ISR block longer then you might expect.
The (f)printf in the irq is not a good idea, although the process is high priority, if there is a request currently being performed by the related driver ( devc-con/devb-eide), they are queue. Hence these calls could make the ISR block longer then you might expect.
- mario
- QNX Master
- Posts: 4132
- Joined: Sun Sep 01, 2002 1:04 am
RE: Measuring the Interrupt Latency
The IRQ can't occur between out8() and ui84_cc_start because the out8 triggers a delay device which delays the signal for 100 milliseconds. Hence the CPU has enough time to get the ClockCycles.
- xcp
- Active Member
- Posts: 10
- Joined: Tue May 27, 2008 9:55 am
Re: RE: Measuring the Interrupt Latency
xcp wrote:The IRQ can't occur between out8() and ui84_cc_start because the out8 triggers a delay device which delays the signal for 100 milliseconds. Hence the CPU has enough time to get the ClockCycles.
Isn't odd that you say that latency goes up to 100 milliseconds...
- mario
- QNX Master
- Posts: 4132
- Joined: Sun Sep 01, 2002 1:04 am
RE: Re: RE: Measuring the Interrupt Latency
No, it keeps at those high latencys even when changing the delay time from 100 to 50 milli seconds.
Actually I had an error in the latency calculation. The real latencys are between 5 to 8 microseconds when system is idle. When doing a "stress --cpu 2", having two workers on the cpu doint sqrt(), i get latencys from 8 to 9 milliseconds.
Actually I had an error in the latency calculation. The real latencys are between 5 to 8 microseconds when system is idle. When doing a "stress --cpu 2", having two workers on the cpu doint sqrt(), i get latencys from 8 to 9 milliseconds.
- xcp
- Active Member
- Posts: 10
- Joined: Tue May 27, 2008 9:55 am
RE: Re: RE: Measuring the Interrupt Latency
Then there is something that you aren`t telling us. Remember, the thread is running at high priority the main() isn`t...
- mario
- QNX Master
- Posts: 4132
- Joined: Sun Sep 01, 2002 1:04 am
RE: Re: RE: Measuring the Interrupt Latency
Thanks for the main() tip. Adding a "setprio( getpid() , 254 );" to the main() did the trick. Thanks.
- xcp
- Active Member
- Posts: 10
- Joined: Tue May 27, 2008 9:55 am
RE: Re: RE: Measuring the Interrupt Latency
setprio(0, 254 ) would work fine. The fact you need to raise the process's priority at 254 show your method of measurement is flawed.
- mario
- QNX Master
- Posts: 4132
- Joined: Sun Sep 01, 2002 1:04 am
RE: Re: RE: Measuring the Interrupt Latency
rather than 254 you should consider using sched_get_priority_max() to get the largest valid priority for your userid/scheduling policy.
- cburgess
- QNX Master
- Posts: 209
- Joined: Tue Aug 31, 2004 8:40 pm
- Location: Ottawa
Re: Measuring the Interrupt Latency
I am also measuring the interrupt latency on X86 target with QNX RTOS. Could someone explain more about this ?? I need a code for this.
- hemanth
- Active Member
- Posts: 20
- Joined: Mon Dec 23, 2013 11:14 pm
Re: Measuring the Interrupt Latency
Could someone explain : How to analyze the interrupt latency on embedded PC target (X86) ??
If its possible then please update the code also.
looking forward for your reply.
If its possible then please update the code also.
looking forward for your reply.
- hemanth
- Active Member
- Posts: 20
- Joined: Mon Dec 23, 2013 11:14 pm
13 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 3 guests