RajSanpui
RajSanpui

Reputation: 12104

Why is my timer not periodic but expired only one time?

I have created a timer using POSIX timerfd function. Intention is, the timer should be periodic, and the timer expiry is observed from a seperate function called myFunc( )

I am calling this function multiple times, so that the timer expiry can be observed periodically after a wait of 5 secs.

Problem is, as soon as first time it expires after 5 seconds, next time onwards...it doesn't expire again, that is no delay of 5 seconds is observed from the second iteration onwards.

Can someone tell me what i am missing?

#include <stdio.h>
#include <iostream>
#include <errno.h>
#include <dlfcn.h>
#include <assert.h>
#include <sys/mman.h>
#include <new>

#include <limits.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>

using namespace std;

struct epoll_event event;
int timer_fd, efd, no_of_fd;
void myFunc( int i );

int main()
{
  struct itimerspec its;

  its.it_value.tv_sec = 5;
  its.it_value.tv_nsec = 0;

  its.it_interval.tv_sec = 3; // Every 3 seconds interval
  its.it_interval.tv_nsec = 0;


  efd = epoll_create(2);
  timer_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK);

  if ( timer_fd == -1 )
  {
    fprintf(stderr, "timerfd_create error in start timer");
    return 1;
  }

  event.data.fd = timer_fd;
  event.events = EPOLLIN|EPOLLPRI;

  if ( epoll_ctl(efd, EPOLL_CTL_ADD, timer_fd, &event) == -1 )
  {
     fprintf(stderr, "epoll_ctl error in start timer"); 
     return 1;
  }

  if ( timerfd_settime(timer_fd, 0, &its, NULL) == -1 )
  {
    fprintf(stderr, "timerfd_settime error in start timer");
    return 1;
  }
  myFunc( 10 );
  myFunc( 20 );
  myFunc( 30 );
}

void myFunc( int i )
{
  printf("Inside myFunc %d\n", i);
  no_of_fd = 0;
  struct epoll_event revent;
  errno = 0;
  do {
     no_of_fd = epoll_wait(efd, &revent, 1, -1);
  } while ( no_of_fd < 0 && errno == EINTR );

  if ( no_of_fd < 0 )
  {
    fprintf(stderr, "epoll_wait error in start timer");

  }

  if ( revent.data.fd == timer_fd ) {
     printf("Timer expired \n");    
  }

}

Upvotes: 1

Views: 694

Answers (1)

haelix
haelix

Reputation: 4555

When using epoll with level-triggering, you should read 8 bytes on every EPOLLIN. This is an int64 that tells you the number of event expirations. Reading it effectively "clears" this number so that the next EPOLLIN is the result of a different event expiration.

The manual tells you about reading:

          If the timer has already expired one or more times since its
          settings were last modified using timerfd_settime(), or since
          the last successful read(2), then the buffer given to read(2)
          returns an unsigned 8-byte integer (uint64_t) containing the
          number of expirations that have occurred.  (The returned value
          is in host byte order—that is, the native byte order for
          integers on the host machine.)

Upvotes: 0

Related Questions