[ace-users] Innacurate timers in Linux after 5.5.6

Alberto Salmerón Moreno salmeron at lcc.uma.es
Mon Jul 23 13:09:52 CDT 2007


Hi all,

I've observed that, using a patched Linux kernel to better support
real-time requirements, newer versions of ACE fail to achieve the
expected, fine-grained timer resolution while older ones work as
expected. PRF follows.

ACE VERSION: 5.5.9

HOST MACHINE and OPERATING SYSTEM: Intel Pentium III, RedHat Linux 9,
2.4.20-rxv kernel (patches from
http://www.rexursive.com/software/redhat.html)

TARGET MACHINE and OPERATING SYSTEM, if different from HOST:

COMPILER NAME AND VERSION (AND PATCHLEVEL): 3.2.2 20030222 (Red Hat
Linux 3.2.2-5)

THE $ACE_ROOT/ace/config.h FILE: I used the configure script,
resulting config.h is 64Kb. I will post it if needed

THE $ACE_ROOT/include/makeinclude/platform_macros.GNU FILE:

CONTENTS OF $ACE_ROOT/bin/MakeProjectCreator/config/default.features:

AREA/CLASS/EXAMPLE AFFECTED:

DOES THE PROBLEM AFFECT: EXECUTION of application

SYNOPSIS:
The average dispatch time for a repeated timer scheduled on a reactor is
different from the expected time, while on a previous version of ACE
(5.5.6) it was right.

DESCRIPTION:
During the development of a application with severe time requirements
I've noticed that timer resolution on Linux seems to have decreased
since ACE version 5.5.6. The application needs a timer to be
dispatched every 2ms. With version 5.5.6 this requirement was
attained, but on the 5.5.8 and 5.5.9 releases the timer was activated
every 12ms. I plan to test with versions 5.5.7 and 5.5 as well, to
further locate the source of this problem.

Since this test is run on the same machine and OS, but with different
versions of ACE, I guess that this is a problem within ACE.

I would greatly appreciate any insight on this, or an indication of
where in the ACE source code can I find the timer handling code so I
can try to figure this out myself.

Note: This can be considered as a follow up to my previous post
(http://groups.google.com/group/comp.soft-sys.ace/browse_thread/thread/4da3a151b47d70a4/b8e088e24bd2a3ef?lnk=gst&rnum=1),
but using a more suitable kernel and then changing the version of ACE,
confirming that on older versions of ACE timing works better.

REPEAT BY:

Sample program follows. A timer fires every 2ms, 60 times. Then the
total time taken is printed on the screen, which should be roughly
2*60ms = 120ms.

/* test.cpp - start *********************/
#include "ace/High_Res_Timer.h"
#include "ace/Log_Msg.h"
#include "ace/OS.h"
#include "ace/OS_NS_Thread.h"
#include "ace/Reactor.h"
#include "ace/Timer_Heap.h"
#include "ace/Timer_Queue.h"

class TimerHandler : public ACE_Event_Handler {
    public:
        int n;
        long i;
        ACE_Time_Value t_end;

    	TimerHandler(int n_) : n(n_), i(0), t_end(ACE_Time_Value::zero) {};
    		
        int handle_timeout(const ACE_Time_Value &ti, const void * = 0) {
            if (i == n) {
                t_end = ti;
                reactor()->end_reactor_event_loop();
                return -1;
            }
            else {
                i++;
                return 0;
            }
        }
};

int ACE_TMAIN(int argc, ACE_TCHAR *argv[]) {
    int time = argc > 1 ? ACE_OS::atoi(argv[1]) : 2000; // 2ms

    ACE_Sched_Priority priority = 1;
    if (ACE_OS::thr_setprio (priority) == -1) {
    	ACE_ERROR ((LM_ERROR, "(%P|%t) main thr_setprio failed,"
        		"no real-time features\n"));
    }

    ACE_High_Res_Timer::global_scale_factor();
    ACE_Reactor reactor;
    reactor.timer_queue()->gettimeofday(&ACE_High_Res_Timer::gettimeofday_hr);
    ACE_Time_Value initialDelay = ACE_Time_Value(0, 0);
    ACE_Time_Value interval (0, time);
    TimerHandler *handler = new TimerHandler(60);
    if (reactor.schedule_timer(handler, 0, initialDelay, interval) == -1) {
    	ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "schedule_timer()"), 1);
    }
    ACE_Time_Value t_start = reactor.timer_queue()->gettimeofday();
    if (reactor.run_reactor_event_loop() == -1) {
    	ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "run_reactor_event_loop()"), 1);
    }
    ACE_Time_Value t_diff = handler->t_end - t_start;
    ACE_DEBUG((LM_DEBUG, "%ds %dus\n", t_diff.sec(), t_diff.usec()));
    return 0;
}
/* test.cpp - end ***********************/

SAMPLE FIX/WORKAROUND: Use an older version of ACE (e.g. 5.5.6).

--
Alberto Salmerón Moreno
Departamento de Lenguajes y Ciencias de la Computación
Universidad de Málaga, ETSI Informática
salmeron at lcc.uma.es



More information about the Ace-users mailing list