Timer update

master
Denes Matetelki 14 years ago
parent 6792784464
commit f39d876cc2

@ -11,9 +11,9 @@ public:
Timer( const int signal = SIGALRM ); Timer( const int signal = SIGALRM );
virtual ~Timer() {} virtual ~Timer();
virtual void timerExpired() {} virtual void timerExpired() {};
virtual void periodicTimerExpired() {} virtual void periodicTimerExpired() {};
void createTimer( const time_t interval_sec, void createTimer( const time_t interval_sec,
const long interval_nsec = 0, const long interval_nsec = 0,
@ -29,8 +29,8 @@ public:
private: private:
// after turning on all warnings, gcc reports that the class has pointer // after turning on all warnings, gcc reports that the class has pointer
// data members (time_t, which is an int by the way) so copy ctor and // data members (time_t, which is a long int by the way) so copy ctor and
// assign op shall be inmplemented // assign op shall be declared
Timer( const Timer& timer ); Timer( const Timer& timer );
Timer& operator=( const Timer& ); Timer& operator=( const Timer& );
@ -39,6 +39,7 @@ private:
timer_t m_timerId; timer_t m_timerId;
bool m_periodic; bool m_periodic;
bool m_running; bool m_running;
sigset_t m_mask;
}; // class Timer }; // class Timer

@ -7,24 +7,49 @@
#include <string.h> // strerror #include <string.h> // strerror
/// @note not used now
// static void sigHandler(int sig, siginfo_t *si, void *uc)
// {
// TRACE_STATIC;
//
// }
struct sigaction& sigActionInit( struct sigaction &sigAct, const int signal ) struct sigaction& sigActionInit( struct sigaction &sigAct, const int signal )
{ {
sigAct.sa_flags = SA_SIGINFO; sigAct.sa_flags = SA_SIGINFO;
// sigAct.sa_sigaction = sigHandler;
sigemptyset( &sigAct.sa_mask ); sigemptyset( &sigAct.sa_mask );
sigaddset( &sigAct.sa_mask, signal ); sigaddset( &sigAct.sa_mask, signal );
sigaction( signal, &sigAct, 0 ); sigaction( signal, &sigAct, 0 );
return sigAct; return sigAct;
} }
sigset_t& sigSetInit( sigset_t &sigSet, const int signal )
{
sigemptyset( &sigSet );
sigaddset(&sigSet, signal );
sigprocmask(SIG_SETMASK, &sigSet, NULL);
return sigSet;
}
Timer::Timer( const Timer& timer ) Timer::Timer( const int signal )
: m_signal( timer.m_signal ) : m_signal( signal )
, m_sigAction( sigActionInit( m_sigAction , m_signal ) ) , m_sigAction( sigActionInit( m_sigAction , m_signal ) )
, m_timerId( 0 ) , m_timerId( 0 )
, m_periodic( false ) , m_periodic( false )
, m_running( true ) , m_running( true )
, m_mask( sigSetInit( m_mask, m_signal ) )
{
TRACE;
}
Timer::~Timer()
{ {
TRACE; TRACE;
sigprocmask(SIG_UNBLOCK, &m_mask, NULL);
} }
@ -40,7 +65,10 @@ void Timer::createTimer( const time_t interval_sec,
sigev.sigev_notify = SIGEV_SIGNAL; sigev.sigev_notify = SIGEV_SIGNAL;
sigev.sigev_signo = m_signal; sigev.sigev_signo = m_signal;
sigev.sigev_value.sival_ptr = &m_timerId; sigev.sigev_value.sival_ptr = &m_timerId;
timer_create( CLOCK_MONOTONIC, &sigev, &m_timerId ); timer_create( CLOCK_REALTIME, &sigev, &m_timerId );
LOG( Logger::FINEST, ( std::string( "Timer created with ID: " ) +
stringify( m_timerId ) ).c_str() );
// arm it // arm it
struct itimerspec its; struct itimerspec its;
@ -58,15 +86,30 @@ void Timer::wait()
{ {
TRACE; TRACE;
int sig; /// @note timerID is acquired from the siginfo after all
sigwait( &m_sigAction.sa_mask, &sig ); long* tidp;
siginfo_t sigInfo;
sigwaitinfo( &(m_sigAction.sa_mask), &sigInfo);
tidp = (long*)sigInfo.si_value.sival_ptr;
// LOG( Logger::FINEST, ( std::string( "Timer expired with ID: " ) +
// stringify( (timer_t)*tidp ) ).c_str() );
timerExpired(); timerExpired();
if ( m_periodic ) { if ( m_periodic ) {
while ( m_running ) { while ( m_running ) {
sigwait( &m_sigAction.sa_mask, &sig );
sigwaitinfo( &(m_sigAction.sa_mask), &sigInfo);
tidp = (long*)sigInfo.si_value.sival_ptr;
// LOG( Logger::FINEST, ( std::string( "Timer expired with ID:" ) +
// stringify( (timer_t)*tidp ) ).c_str() );
periodicTimerExpired(); periodicTimerExpired();
} }
} }
} }
@ -88,21 +131,3 @@ void Timer::gracefulStop()
m_running = false; m_running = false;
} }
Timer::Timer( const int signal )
: m_signal( signal )
, m_sigAction( sigActionInit( m_sigAction , m_signal ) )
, m_timerId( 0 )
, m_periodic( false )
, m_running( true )
{
TRACE;
}
Timer& Timer::operator=( const Timer& )
{
TRACE;
return *this;
}

@ -25,7 +25,7 @@ if(CXXTEST_FOUND)
test_Semaphore.hpp test_Semaphore.hpp
test_Timer.hpp test_Timer.hpp
test_Common.hpp test_Common.hpp
test_TimerThread.hpp test_TimerThread.hpp
) )
target_link_libraries(test CppUtils gcov) target_link_libraries(test CppUtils gcov)
endif() endif()

@ -1,15 +1,51 @@
#!/usr/bin/perl #!/usr/bin/perl
use strict;
use warnings;
use Term::ANSIColor qw(:constants); use Term::ANSIColor qw(:constants);
$Term::ANSIColor::AUTORESET = 1; $Term::ANSIColor::AUTORESET = 1;
my $line = "";
my $left;
while ( <> ) { while ( <> ) {
if (/Segmentation fault/) {
print "\n" . YELLOW . "Segmentation fault." . RESET . "\n";
$left = 3;
next;
}
if (/^(Thread \d+)/) { if (/^(Thread \d+)/) {
print "\n" . BOLD BLUE . $1 . RESET . " $'" print "\n" . BOLD BLUE . $1 . RESET . " $'";
next;
} }
elsif ( /^(#\d+)\s+(\S+)\s+in\s+(.+)( \(.*)(at.*\/)(\S+):(\d+)/ )
if ($left) {
if ( $left == 3 ) {
$line = $_;
chomp($line);
$left--;
next;
}
elsif ( $left == 2 ) {
$line .= $_;
$left--;
}
elsif ( $left == 1 ) {
print BOLD YELLOW . $_ . RESET . "\n";
$left--;
next;
}
} else {
$line = $_;
}
if ( $line =~ /^(#\d+)\s+(\S+)\s+in\s+(.+)( \(.*)(at.*\/)(\S+):(\d+)/ )
{ {
print "\n" . print "\n" .
BOLD . $1 . # no BOLD . $1 . # no
@ -21,7 +57,7 @@ while ( <> ) {
YELLOW . $7 . # line YELLOW . $7 . # line
RESET . "\n"; RESET . "\n";
} }
elsif ( /^(#\d+)\s+(\S+)\s+in\s+(.+)( \(.*)(from.*\/)(\S+)/ ) elsif ( $line =~ /^(#\d+)\s+(\S+)\s+in\s+(.+)( \(.*)(from.*\/)(\S+)/ )
{ {
print "\n" . print "\n" .
BOLD . $1 . # no BOLD . $1 . # no

@ -4,18 +4,18 @@
# ./run_test.sh <TEST_BINARY> # ./run_test.sh <TEST_BINARY>
# function yesno() function yesno()
# { {
# while true; do while true; do
# read -p "$* (y/n)[y]" yn read -p "$* (y/n)[y]" yn
# if [ "$yn" = '' ]; then yn="y"; fi if [ "$yn" = '' ]; then yn="y"; fi
# case "$yn" in case "$yn" in
# [Yy]* ) return 0;; [Yy]* ) return 0;;
# [Nn]* ) return 1;; [Nn]* ) return 1;;
# * ) echo "Please answer y/n.";; * ) echo "Please answer y/n.";;
# esac esac
# done done
# } }
pre="\E[00;33m" pre="\E[00;33m"
fail="\E[00;31m" fail="\E[00;31m"
@ -80,12 +80,14 @@ if [ $retval -ne 0 ]; then
if [ "$cores" != "" ]; then if [ "$cores" != "" ]; then
echo -e "${pre}Core file generated: ${post}" echo -e "${pre}Core file generated: ${post}"
echo $cores echo $cores
# if yesno "run 'gdb $test $cores' ?"; then
# gdb $test $cores
# fi
# NOTE no need to bt full # NOTE no need to bt full
gdb $test $cores -ex "set width 1000" -ex "thread apply all bt" -ex q > gdb.out gdb $test $cores -ex "set width 1000" -ex "thread apply all bt" -ex q > gdb.out
./gdb_out_parser.pl gdb.out ./gdb_out_parser.pl gdb.out
if yesno "run 'gdb $test $cores' ?"; then
gdb $test $cores
fi
fi fi
exit -1 exit -1
fi fi

@ -18,8 +18,9 @@ private:
{ {
public: public:
DummyTimer(int maxPeriodicCount = 5) DummyTimer(int maxPeriodicCount = 5, const int signal = SIGALRM)
: m_counter(0) : Timer(signal)
, m_counter(0)
, m_maxPeriodicCount(maxPeriodicCount) , m_maxPeriodicCount(maxPeriodicCount)
{ {
TRACE; TRACE;
@ -79,12 +80,14 @@ private:
{ {
public: public:
DummyTimerThread(const int maxPeriodicCount = INT_MAX - 1, DummyTimerThread( const int maxPeriodicCount = INT_MAX - 1,
const time_t interval_sec = 2, const int signal = SIGALRM,
const long interval_nsec = 0, const time_t interval_sec = 2,
const time_t initExpr_sec = 0, const long interval_nsec = 0,
const long initExpr_nsec = 0) const time_t initExpr_sec = 0,
: m_counter(0) const long initExpr_nsec = 0 )
: Timer(signal)
, m_counter(0)
, m_maxPeriodicCount(maxPeriodicCount) , m_maxPeriodicCount(maxPeriodicCount)
, m_interval_sec(interval_sec) , m_interval_sec(interval_sec)
, m_interval_nsec(interval_nsec) , m_interval_nsec(interval_nsec)
@ -160,6 +163,32 @@ private:
TS_ASSERT_EQUALS( t.m_counter, 100 ); TS_ASSERT_EQUALS( t.m_counter, 100 );
} }
void testCustomSignal( void )
{
TEST_HEADER;
int customSignal = SIGRTMIN;
// the main thread shall ignore the customSignal
sigset_t set;
sigemptyset( &set );
sigaddset( &set, customSignal );
sigprocmask( SIG_BLOCK, &set, NULL);
DummyTimerThread t( 5, customSignal );
t.start();
// timespec ts = { 4, 0 };
// nanosleep( &ts , 0 );
sleep(4);
t.join();
TS_ASSERT_EQUALS( t.m_counter, 100 );
sigprocmask( SIG_UNBLOCK, &set, NULL );
}
void testTimerThreadHighFreq( void ) void testTimerThreadHighFreq( void )
{ {
TEST_HEADER; TEST_HEADER;
@ -173,6 +202,7 @@ private:
int nano = 1000000000; // 10^9 int nano = 1000000000; // 10^9
int freq = 80000; int freq = 80000;
DummyTimerThread t(INT_MAX - 1, DummyTimerThread t(INT_MAX - 1,
SIGALRM,
1, 0, 1, 0,
0, nano / freq ); 0, nano / freq );
@ -185,6 +215,8 @@ private:
// expected 800000 + 100 got 795510 // expected 800000 + 100 got 795510
// accurcy: ~ > 99.5% // accurcy: ~ > 99.5%
TS_ASSERT_DELTA ( t.m_counter, 100 + freq * circle, (100 + freq * circle) * 0.995); TS_ASSERT_DELTA ( t.m_counter, 100 + freq * circle, (100 + freq * circle) * 0.995);
sigprocmask( SIG_UNBLOCK, &set, NULL );
} }
}; };

Loading…
Cancel
Save