#include #include #include #include #include class CCounter { public: CCounter() : m_iCount(0) { pthread_mutex_init(&m_Mutex, 0); pthread_cond_init(&m_Cond, 0); } ~CCounter() { pthread_cond_destroy(&m_Cond); pthread_mutex_destroy(&m_Mutex); } void WaitUntilAtLeast(int const i) { pthread_mutex_lock(&m_Mutex); while (m_iCount < i) pthread_cond_wait(&m_Cond, &m_Mutex); pthread_mutex_unlock(&m_Mutex); } void operator++() { pthread_mutex_lock(&m_Mutex); m_iCount++; pthread_cond_signal(&m_Cond); pthread_mutex_unlock(&m_Mutex); } private: pthread_mutex_t m_Mutex; pthread_cond_t m_Cond; int m_iCount; }; static volatile int s_iIterations; static volatile pthread_t s_Thread1ID; static volatile pthread_t s_Thread2ID; static volatile timeval s_iTime[1000]; static CCounter s_ThreadsStarted; void* Thread1(void*) { ++s_ThreadsStarted; s_ThreadsStarted.WaitUntilAtLeast(2); sigset_t EmptyMask; sigemptyset(&EmptyMask); for (int i = 0; i < s_iIterations; i++) { gettimeofday(const_cast(&s_iTime[2*i]), 0); pthread_kill(s_Thread2ID, SIGALRM); sigsuspend(&EmptyMask); } return 0; } void* Thread2(void*) { ++s_ThreadsStarted; s_ThreadsStarted.WaitUntilAtLeast(2); sigset_t EmptyMask; sigemptyset(&EmptyMask); sigsuspend(&EmptyMask); for (int i = 0; i < s_iIterations; i++) { gettimeofday(const_cast(&s_iTime[2*i+1]), 0); pthread_kill(s_Thread1ID, SIGALRM); sigsuspend(&EmptyMask); } return 0; } void SignalHandler(int const /*iSignal*/) { // write(STDOUT_FILENO, "SIGALRM\n", 8); } int main(int argc, char** argv) { sigset_t BlockedSignals; sigemptyset(&BlockedSignals); sigaddset(&BlockedSignals, SIGALRM); sigprocmask(SIG_BLOCK, &BlockedSignals, 0); struct sigaction Sigaction; memset(&Sigaction, 0, sizeof(Sigaction)); Sigaction.sa_handler = SignalHandler; sigaction(SIGALRM, &Sigaction, 0); s_iIterations = (argc > 1) ? atoi(argv[1]) : 5; std::cout << "Iterations: " << s_iIterations << "\n"; pthread_create(const_cast(&s_Thread1ID), 0, Thread1, 0); pthread_create(const_cast(&s_Thread2ID), 0, Thread2, 0); pthread_join(s_Thread1ID, 0); pthread_kill(s_Thread2ID, SIGALRM); pthread_join(s_Thread2ID, 0); for (int i = 1; i < 2 * s_iIterations; i++) { timeval Delta; timersub(&s_iTime[i], &s_iTime[i-1], &Delta); std::cout << i << ' ' << Delta.tv_usec * 1e-3 << " ms\n"; } { timeval Timeval1; timeval Timeval2; timeval Delta; gettimeofday(&Timeval1, 0); gettimeofday(&Timeval2, 0); timersub(&Timeval2, &Timeval1, &Delta); std::cout << "Time required for one gettimeofday() call: " << Delta.tv_usec * 1e-3 << " ms\n"; } return 0; } // Local variables: // compile-command: "g++ -Wall -W -g -O3 ctxtsw.cpp -o ctxtsw -lpthread" // End: