Thread: Timers and software interrupts

  1. #1
    Registered User
    Join Date
    Jan 2009
    Location
    Groningen, The Netherlands
    Posts
    3

    Timers and software interrupts

    At the moment I'm working on a project where I need a timer that works beside my main application. I'm working on Ubuntu 8.10 distro, with NetBeans IDE with the C/C++ plugin. I want to work with a statemachine where every timerinterval a state is executed. I tried browsing the man-pages for Linux and Ubuntu and stumbled over the timer_create() and timer_createfd() functions, but no where a working example. How can I create a timer and how to handle the interrupt?

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I take it you mean timerfd_create()?

    Either way, have a look at http://uw714doc.sco.com/en/man/html.5/sigevent.5.html
    It explains how you fill in the sigevent structure.

    Of course, you may want to use timefd_create and select() or some such to receive your signal instead.

    Or use the signal handling system. It all depends on what you actually wish to achieve.

    Edit: Beyond that, you probably should post your code, and someone will help you out.

    --
    Mats
    Last edited by matsp; 01-20-2009 at 10:38 AM.
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Jan 2009
    Location
    Groningen, The Netherlands
    Posts
    3

    Thumbs up

    Thanks Mats, you pointed me in the right direction.....

    This is the code I'm working with now... it's a small test program where I want to get a timer running with an interval of 1,5 seconds... every time when the timer is done I want to print "hello from the timer" to the screen.

    First off my declarations:

    Code:
    int fdClock;
    struct itimerspec itset_time;
    struct itimerspec start_time;
    static void sighandler (int whatever);
    Then my main function... first off some values for the timer, not sure if this is correct, but I want an interval of 1,5 sec... wasn't sure what to do with start_time struct.

    Code:
    int main(void)
    {
            //Init values timer	
    	itset_time.it_interval.tv_nsec = 500;
    	itset_time.it_interval.tv_sec = 1;
    	itset_time.it_value.tv_nsec = 0;
    	itset_time.it_value.tv_sec = 0;
    	start_time.it_value.tv_nsec = 0;
    	start_time.it_value.tv_sec = 0;		
    	start_time.it_interval.tv_nsec = 0;
    	start_time.it_interval.tv_sec = 0;
    
    	fdClock = timerfd_create(CLOCK_REALTIME, O_NONBLOCK);
    	printf("%d\n", fdClock);
    	fcntl(fdClock, FD_CLOEXEC);
    	timerfd_settime(fdClock, FD_CLOEXEC, itset_time, start_time);
    	signal(FD_CLOEXEC, sighandler);
           while(1){sleep(2);};
           return(EXIT_SUCCESS);
    }
    I now the code is a bit rough, with the endless loop and all..... not very pretty.
    But I hope it does the trick, I've got the feeling I'm doing something wrong with or the timer or the signal indications, but no idea which it is. Did interrupts on PIC microcontroller, but Linux is new to me. With microcontrollers I have to reset the flag on my own to get the any new interrupt from a timer, same here? or does the OS reset the flag? I have the feeling I'm forgetting the resetting as well.

    The sighandler is implemented as follows:

    Code:
    void sighandler(int whatever)
    {
    	printf("hello from the timer\n");
    }
    The code compiles, but it doesn't do anything... what's missing?

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I can't actually see anything wrong with that code, so I guess we have to wait for someone who ACTUALLY knows this API to come along and put us right.

    Also, one of the moderators may want to move this to the Linux forum.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Afro1986 View Post
    Code:
    signal(FD_CLOEXEC, sighandler);
    I'm quite sure there is no such signal as "FD_CLOEXEC," and besides, if you want to use signals for handling timers there are easier mechanisms than timerfds (for instance, good old setitimer() )

    The whole point of using a timerfd is because you DON'T want to use signals, but rather work it into a main select() or poll() loop. I suppose there could be differences in precision between a timerfd and a setitimer but they may not matter.

    On top of all that, setitimer at least has the benefit of being a UNIX standard.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #6
    Registered User
    Join Date
    Apr 2008
    Posts
    396
    Code:
    timerfd_settime(fdClock, FD_CLOEXEC, itset_time, start_time);
    the flags argument is not right, you need to indicate 0 for a relative timer or TFD_TIMER_ABSTIME (cf manpage) for an absolute timer. The last argument, your start_time, is the last value of the timer, you can use 0 if you don't want to get back that. Those two timerspec are expected to be pointers...
    Other remarks: check the result of your system calls, they may fail (and probably failed in your case), and as noticed in the previous post, what are you doing with FD_CLOEXEC in every call?, use it once with fcntl, it has no sense with the other functions (plus the way it is used with fcntl is wrong, check it).

  7. #7
    Registered User
    Join Date
    Jan 2009
    Location
    Groningen, The Netherlands
    Posts
    3
    Thanks for the tips.. I got it working

    Code:
    struct itimerval old;
    struct itimerval new;
    
    void 
    catch_alarm (int sig)
    {
      //keep_going = 0;
      printf("Alarm event\n");
      signal (sig, catch_alarm);
    }
    
    int
    main(void)
    {
      signal (SIGALRM, catch_alarm);
      new.it_interval.tv_sec = 1; 
      new.it_interval.tv_usec = 500000; 
      new.it_value.tv_sec = 1;
      new.it_value.tv_usec = 500000;
      
      old.it_interval.tv_sec = 0;
      old.it_interval.tv_usec = 0;
      old.it_value.tv_sec = 0;
      old.it_value.tv_usec = 0;
      
      if (setitimer (ITIMER_REAL, &new, &old) < 0)
    	  printf("timer init failed\n");
      else 
    	  printf("timer init succeeded\n");
      while(1) sleep(2);
    return EXIT_SUCCESS;
    }
    It's actually pretty easy to get a timer running, thanks again....

Popular pages Recent additions subscribe to a feed