sem_timedwait with CLOCK_MONOTONIC_RAW/CLOCK_MONOTONIC

The example code for int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); uses CLOCK_REALTIME as the time source from clock_gettime(struct timespec *timeout) but this is susceptible to system clock time changes for example some other process changing time backwards.

Is there a support for sem_timedwait to support CLOCK_MONOTONIC time source

below is some example code for reference.

struct timespec ts;
sem_t sema;
sem_init(&sema, 0, 0)
int ret;
if ( -1  != (ret = clock_gettime(CLOCK_REALTIME, &ts))){
    ts.tv_sec += 1;
    return sem_timedwait(sema, &ts);
}

Is there a support for sem_timedwait to support CLOCK_MONOTONIC time source

Short answer: no.

But you could implement one if you're not using a 3rd party library or C++11 and don't need cross-platform compatibility:

#include <cstring> // memset
#include <ctime>   // DEV_NOTE: some systems might need -lrt
#include <csignal> // DEV_NOTE: csignal contains a reference to CLOCK_MONOTONIC
#include <semaphore.h>
#if !defined(CLOCK_MONOTONIC)
    #error CLOCK_MONOTONIC is not defined
#endif

typedef struct timespec tick_t;

static tick_t monotonic_tick()
{
    tick_t tmp;
    if (clock_gettime(CLOCK_MONOTONIC, &tmp) != 0) {
        std::memset(&tmp, 0, sizeof(tick_t));
        // error, throw std::exception(std::strerror(errno))
    }
    return tmp;
}

static double elapsed_us(tick_t init, tick_t end)
{
    return ((end.tv_sec - init.tv_sec) * 1000000) + (static_cast<double>((end.tv_nsec - init.tv_nsec)) / 1000);
}

static double elapsed_ms(tick_t init)
{
    return (elapsed_us(init, monotonic_tick()) / 1000);
}

static int sem_timed_wait(sem_t& sem, unsigned long timeout_ms)
{
    if (timeout_ms == 0) {
        if (sem_trywait(&sem) == 0) {
            return 0;
        }
    } else {
        tick_t start = monotonic_tick();
        do {
            if (sem_trywait(&sem) == 0) {
                return 0;
            }
        } while (elapsed_ms(start) <= timeout_ms);
    }
    return -1;
}

Then to use it:

#include <iostream>
#include <pthread.h>

void* thread_fn(void* val)
{
    sem_t* sem = static_cast<sem_t*>(val);
    std::cout << std::endl << pthread_self() << " thread started" << std::endl;

    if (sem_timed_wait(*sem, 1000) == 0) {
        std::cout << std::endl << pthread_self() << " got it, sleeping 2 seconds..." << std::endl;
        sleep(2); // sleep 2 seconds
        std::cout << pthread_self() << " returning..." << std::endl;
        // don't forget to release since we acquired the lock
        sem_post(sem);
    } else {
        std::cout << pthread_self() << " timeout" << std::endl;
    }
    std::cout << pthread_self() << " thread returning" << std::endl;
    return NULL;
}

int main(int argc, char* argv[])
{
    sem_t sem;
    pthread_t t1, t2;
    sem_init(&sem, 0, 1); // binary semaphore

    std::cout << "Creating..." << std::endl;
    pthread_create(&t1, NULL, thread_fn, static_cast<void*>(&sem));
    pthread_create(&t2, NULL, thread_fn, static_cast<void*>(&sem));

    std::cout << "Joining..." << std::endl;
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    std::cout << "Leaving..." << std::endl;
    return 0;
}

The above works on a wide array of *nix systems to include the BSD line. If you need a cross platform way of doing this, Windows and Apple have simpler mechanisms to do this.

Hope that can help.

sem_timedwait with CLOCK_MONOTONIC_RAW - android, sem_timedwait with CLOCK_MONOTONIC_RAW/CLOCK_MONOTONIC - c++. The example code for int sem_timedwait(sem_t *sem, const struct timespec  The timeout is based on the CLOCK_REALTIME clock. The sem_timedwait_monotonic () function is a QNX Neutrino extension; it's similar to sem_timedwait (), but it uses CLOCK_MONOTONIC, so the timeout isn't affected by changes to the system time.

Had the same problem with POSIX system, Based on C++0x has no semaphores? How to synchronize threads? and How do I deal with the system clock changing while waiting on a std::condition_variable? and Halûk Uçar answer

#include <stdio.h>
#include <thread>            
#include <time.h>
#include <unistd.h>
#include <pthread.h>
class semaphore
{
private:   
   pthread_mutex_t m_mutex = PTHREAD_MUTEX_INITIALIZER;
   pthread_condattr_t m_attr;
   pthread_cond_t m_cond;

   unsigned long count_ = 0;   

   public :
   void init_sem()
   {
      int result = 0;
      result = pthread_condattr_init(&m_attr);

      result = pthread_condattr_setclock(&m_attr, CLOCK_MONOTONIC);

      result = pthread_cond_init(&m_cond, &m_attr); 
   }

   void notify() {
      pthread_mutex_lock(&m_mutex);
      ++count_;
      pthread_cond_signal(&m_cond);
      pthread_mutex_unlock(&m_mutex);
   }



   void wait() {
      pthread_mutex_lock(&m_mutex);
      while (!count_) // Handle spurious wake-ups.
      {
        pthread_cond_wait(&m_cond, &m_mutex);
      }
      --count_;
      pthread_mutex_unlock(&m_mutex);

   }

   void wait_for(int sec)
   {
      int rc = 0;
      pthread_mutex_lock(&m_mutex);
      if (!count_)
      {
         timespec tsTimeout;
         clock_gettime(CLOCK_MONOTONIC, &tsTimeout);

         // update time calculation to your specific case
         tsTimeout.tv_sec += time;

         // Handle spurious wake-ups.
         while (!count_ && (rc == 0))
         {
            rc = pthread_cond_timedwait(&m_cond, &m_mutex, &tsTimeout);
         }

      }

      if (rc == 0)
      {        
         printf("success\n");

         --count_;
      }
      else if (rc == ETIMEDOUT)
      {
         printf("timeout\n");
      }
      else
      {
         printf("error\n");
      }

      pthread_mutex_unlock(&m_mutex);
   }      

   bool destroy()
   {
      return ((pthread_cond_destroy(&m_cond) == 0)
        && (pthread_mutex_destroy(&m_mutex) == 0)
        && (pthread_condattr_destroy(&m_attr)==0)) ? true : false;
   }
};

112521 – monotonic sem_timedwait, there is no support for sem_timedwait() using CLOCK_MONOTONIC. such as CLOCK_MONOTONIC or CLOCK_MONOTONIC_RAW  Therefore, in my opinion it would be better to make sem_timedwait() agnostic (not dependent) on the system clock at all. My recommendation is to allow CLOCK_MONOTONIC to be used with sem_timedwait() to avoid any disruption due to arbitrary changes of the system clock.

14717 – Allow choice of clock source for calls to sem_timedwait , The OS maintains various clocks, such as CLOCK_REALTIME, CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW. CLOCK_REALTIME  Semaphores and mutexes also has timedwait functions (sem_timedwait ()/pthread_mutex_timedlock ()) but these can not as of SUSv3 be configured to use clockids other then CLOCK_REALTIME. It is possible to work around the lack of CLOCK_MONOTONIC in some cases but it requires a POSIX timer and an unused signal number.

sem_timedwait, sem_timedwait_monotonic, The sem_timedwait_monotonic() function is a QNX Neutrino extension; it's similar to sem_timedwait(), but it uses CLOCK_MONOTONIC, so the timeout isn't  The pthread_mutex_timedlock documentation says that abs_timeout takes a CLOCK_REALTIME. However, we all know that it is inappropriate for timing a specific duration (due to system time adjustments). Is there a way to make pthread lock timeout on CLOCK_MONOTONIC that is portable? The same goes with pthread_cond_timedwait.

[Resolved] Using sem_timedwait - Linux forum (Read-Only), I think CLOCK_MONOTONIC or CLOCK_MONOTONIC_RAW would be better option. What are your thoughts? Thank you. Regards Santhosh. I think your conclusion that CLOCK_MONOTONIC_RAW is "truncated" is wrong. Rather, the resolution of the hardware clock source is probably just microseconds. The nonzero low digits you're seeing in CLOCK_MONOTONIC are because the timestamps from the hardware clock source are being scaled, per adjustments made via adjtime/NTP, to correct for imprecision in the hardware clock rate that would

CLOCK_MONOTONIC and sem_timedwait / pthread_mutex_timedlock, Hi! The use of CLOCK_MONOTONIC is somewhat limited as it's not supported AFAIK for semaphores and mutexes. I know it is supported for  CLOCK_MONOTONIC Clock that cannot be set and represents monotonic time since some unspecified starting point. CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific) Similar to CLOCK_MONOTONIC, but provides access to a raw hard‐ ware-based time that is not subject to NTP adjustments.

Comments
  • Is this related to Linux kernel programming? If no, why "linux-kernel" tag?
  • @Tsyvarev bugzilla.kernel.org/show_bug.cgi?id=112521
  • Is this considered a "busy loop", i.e. does the do-while loop result in sem_timed_wait() chewing up CPU cycles whereas the "native" sem_timedwait() would not?
  • @StoneThrow .. kind of .. sem_timedwait is implementation defined, so the "native" way could employ whatever technique to implement a timed wait, but in most cases it's just a simple busy loop anyways. You could add a sleep if you wanted, but if you did something like usleep(1) on a non-realtime OS, your thread could actually sleep 10+ ms instead of 1ms due to time slices. With a timed wait, you usually only want a small time frame anyways, like 1 second or less; usually if you need a longer wait you have an event/callback system to alert instead of waiting on a kernel lock.