From f39d876cc253090d2061224940aa8701e51c3622 Mon Sep 17 00:00:00 2001 From: Denes Matetelki Date: Sat, 16 Apr 2011 18:37:35 +0200 Subject: [PATCH] Timer update --- include/Timer.hpp | 11 ++++--- src/Timer.cpp | 73 ++++++++++++++++++++++++++++-------------- test/CMakeLists.txt | 2 +- test/gdb_out_parser.pl | 42 ++++++++++++++++++++++-- test/run_test.sh | 32 +++++++++--------- test/test_Timer.hpp | 48 ++++++++++++++++++++++----- 6 files changed, 152 insertions(+), 56 deletions(-) diff --git a/include/Timer.hpp b/include/Timer.hpp index ad7adb9..a109303 100644 --- a/include/Timer.hpp +++ b/include/Timer.hpp @@ -11,9 +11,9 @@ public: Timer( const int signal = SIGALRM ); - virtual ~Timer() {} - virtual void timerExpired() {} - virtual void periodicTimerExpired() {} + virtual ~Timer(); + virtual void timerExpired() {}; + virtual void periodicTimerExpired() {}; void createTimer( const time_t interval_sec, const long interval_nsec = 0, @@ -29,8 +29,8 @@ public: private: // 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 - // assign op shall be inmplemented + // data members (time_t, which is a long int by the way) so copy ctor and + // assign op shall be declared Timer( const Timer& timer ); Timer& operator=( const Timer& ); @@ -39,6 +39,7 @@ private: timer_t m_timerId; bool m_periodic; bool m_running; + sigset_t m_mask; }; // class Timer diff --git a/src/Timer.cpp b/src/Timer.cpp index 7c9c6bc..1ae4dc9 100644 --- a/src/Timer.cpp +++ b/src/Timer.cpp @@ -7,24 +7,49 @@ #include // 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 ) { sigAct.sa_flags = SA_SIGINFO; + // sigAct.sa_sigaction = sigHandler; sigemptyset( &sigAct.sa_mask ); sigaddset( &sigAct.sa_mask, signal ); sigaction( signal, &sigAct, 0 ); 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 ) - : m_signal( timer.m_signal ) +Timer::Timer( const int signal ) + : m_signal( signal ) , m_sigAction( sigActionInit( m_sigAction , m_signal ) ) , m_timerId( 0 ) , m_periodic( false ) , m_running( true ) + , m_mask( sigSetInit( m_mask, m_signal ) ) +{ + TRACE; +} + +Timer::~Timer() { 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_signo = m_signal; 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 struct itimerspec its; @@ -58,15 +86,30 @@ void Timer::wait() { TRACE; - int sig; - sigwait( &m_sigAction.sa_mask, &sig ); + /// @note timerID is acquired from the siginfo after all + 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(); + if ( m_periodic ) { 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(); } } + } @@ -88,21 +131,3 @@ void Timer::gracefulStop() 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; -} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1f2a095..458b4c0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -25,7 +25,7 @@ if(CXXTEST_FOUND) test_Semaphore.hpp test_Timer.hpp test_Common.hpp - test_TimerThread.hpp + test_TimerThread.hpp ) target_link_libraries(test CppUtils gcov) endif() diff --git a/test/gdb_out_parser.pl b/test/gdb_out_parser.pl index 9e5952c..d28e354 100755 --- a/test/gdb_out_parser.pl +++ b/test/gdb_out_parser.pl @@ -1,15 +1,51 @@ #!/usr/bin/perl +use strict; +use warnings; + use Term::ANSIColor qw(:constants); $Term::ANSIColor::AUTORESET = 1; +my $line = ""; +my $left; + while ( <> ) { + + + if (/Segmentation fault/) { + print "\n" . YELLOW . "Segmentation fault." . RESET . "\n"; + $left = 3; + next; + } + 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" . BOLD . $1 . # no @@ -21,7 +57,7 @@ while ( <> ) { YELLOW . $7 . # line RESET . "\n"; } - elsif ( /^(#\d+)\s+(\S+)\s+in\s+(.+)( \(.*)(from.*\/)(\S+)/ ) + elsif ( $line =~ /^(#\d+)\s+(\S+)\s+in\s+(.+)( \(.*)(from.*\/)(\S+)/ ) { print "\n" . BOLD . $1 . # no diff --git a/test/run_test.sh b/test/run_test.sh index 38fc693..89c4e95 100755 --- a/test/run_test.sh +++ b/test/run_test.sh @@ -4,18 +4,18 @@ # ./run_test.sh -# function yesno() -# { -# while true; do -# read -p "$* (y/n)[y]" yn -# if [ "$yn" = '' ]; then yn="y"; fi -# case "$yn" in -# [Yy]* ) return 0;; -# [Nn]* ) return 1;; -# * ) echo "Please answer y/n.";; -# esac -# done -# } +function yesno() +{ + while true; do + read -p "$* (y/n)[y]" yn + if [ "$yn" = '' ]; then yn="y"; fi + case "$yn" in + [Yy]* ) return 0;; + [Nn]* ) return 1;; + * ) echo "Please answer y/n.";; + esac + done +} pre="\E[00;33m" fail="\E[00;31m" @@ -80,12 +80,14 @@ if [ $retval -ne 0 ]; then if [ "$cores" != "" ]; then echo -e "${pre}Core file generated: ${post}" echo $cores -# if yesno "run 'gdb $test $cores' ?"; then -# gdb $test $cores -# fi + # NOTE no need to bt full gdb $test $cores -ex "set width 1000" -ex "thread apply all bt" -ex q > gdb.out ./gdb_out_parser.pl gdb.out + + if yesno "run 'gdb $test $cores' ?"; then + gdb $test $cores + fi fi exit -1 fi diff --git a/test/test_Timer.hpp b/test/test_Timer.hpp index ae86c9a..9098d43 100644 --- a/test/test_Timer.hpp +++ b/test/test_Timer.hpp @@ -18,8 +18,9 @@ private: { public: - DummyTimer(int maxPeriodicCount = 5) - : m_counter(0) + DummyTimer(int maxPeriodicCount = 5, const int signal = SIGALRM) + : Timer(signal) + , m_counter(0) , m_maxPeriodicCount(maxPeriodicCount) { TRACE; @@ -79,12 +80,14 @@ private: { public: - DummyTimerThread(const int maxPeriodicCount = INT_MAX - 1, - const time_t interval_sec = 2, - const long interval_nsec = 0, - const time_t initExpr_sec = 0, - const long initExpr_nsec = 0) - : m_counter(0) + DummyTimerThread( const int maxPeriodicCount = INT_MAX - 1, + const int signal = SIGALRM, + const time_t interval_sec = 2, + const long interval_nsec = 0, + const time_t initExpr_sec = 0, + const long initExpr_nsec = 0 ) + : Timer(signal) + , m_counter(0) , m_maxPeriodicCount(maxPeriodicCount) , m_interval_sec(interval_sec) , m_interval_nsec(interval_nsec) @@ -160,6 +163,32 @@ private: 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 ) { TEST_HEADER; @@ -173,6 +202,7 @@ private: int nano = 1000000000; // 10^9 int freq = 80000; DummyTimerThread t(INT_MAX - 1, + SIGALRM, 1, 0, 0, nano / freq ); @@ -185,6 +215,8 @@ private: // expected 800000 + 100 got 795510 // accurcy: ~ > 99.5% TS_ASSERT_DELTA ( t.m_counter, 100 + freq * circle, (100 + freq * circle) * 0.995); + + sigprocmask( SIG_UNBLOCK, &set, NULL ); } };