Find the answer to your Linux question:
Results 1 to 10 of 10
I am making trying to set up code that can start and stop a timer which triggers a function ~3 times a second. My initialization of the timer is Code: ...
  1. #1
    Just Joined!
    Join Date
    Oct 2009
    Posts
    14

    Creating and destroying timers

    I am making trying to set up code that can start and stop a timer which triggers a function ~3 times a second. My initialization of the timer is
    Code:
    timer_t timerid;
    
    void scan_init (void) {
    	scan_data[0] = scan_data[1] = scan_data[2] = 0;
    	struct sigevent sev;
    	struct itimerspec its;
    	/* Install our SIGUSR2 signal handler */
    	struct sigaction sa;
    
    	sa.sa_sigaction = scan_handler;
    	sigemptyset( &sa.sa_mask );
    	sa.sa_flags = SA_SIGINFO; /* we want a siginfo_t */
    	if (sigaction (SIGUSR2, &sa, 0)) {
    		printf("sigaction error\n");
    		exit(1);
    	}
    
    	/* Create the timer */
    
    	sev.sigev_notify = SIGEV_SIGNAL;
    	sev.sigev_signo = SIGUSR2;
    	sev.sigev_value.sival_ptr = &timerid;
    	if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1)
    	{
    		printf("timer_create error\n");
    		exit(1);
    	}
    
    	/* Start the timer */
    
    	its.it_value.tv_sec = 0;
    	its.it_value.tv_nsec = 350000000; // ~3 samples per second
    	its.it_interval.tv_sec = its.it_value.tv_sec;
    	its.it_interval.tv_nsec = its.it_value.tv_nsec;
    
    	if (timer_settime(timerid, 0, &its, NULL) == -1)
    	{
    		printf("timer_settime error\n");
    		exit(1);
    	}
    }
    and to stop the timer I am using
    Code:
    void scan_stop (void) {
    	if(timer_delete(timerid)) {
    		printf("timer_delete error\n");
    		exit(1);
    	}
    }
    For some reason the code works flawlessly the first time the timer run/stop/run but when it tries to stop it a second time I get no errors but the timer continues to run. When it is run again it seems like two timers are running and each time after that it looks like more and more are running.

    How can I fully stop a timer (if timer_delete doesn't do that) or is there a better way to pause a timer?

    Thanks,
    JR

  2. #2
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
    Posts
    8,974
    Have you tried disarming the timer before you delete it? IE:
    Code:
    void scan_stop (void) {
    	struct itimerspec its;
            memset((void*)&its, 0, sizeof(its));
    	if (timer_settime(timerid, 0, &its, NULL) == -1)
    	{
    		printf("error disarming timer\n");
    		exit(1);
    	}
    	if(timer_delete(timerid))
    	{
    		printf("timer_delete error\n");
    		exit(1);
    	}
    }
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  3. #3
    Just Joined!
    Join Date
    Oct 2009
    Posts
    14
    I just tried it out, same result.

    Could it be an issue with the timerid? I had it print the timer ID and it was the same before and after the timer was created. Is that normal? Even the second timer had the same ID as the first.

    Am I supposed to supply an ID or is it given by timer_create()?

    EDIT: I had the idea of just disarming the timer and my code looks like this.
    Code:
    void scan_start (void) {
    	struct itimerspec its;
    	printf("scan create!\n");
    
    	/* Start the timer */
    	its.it_value.tv_sec = 0;
    	its.it_value.tv_nsec = 350000000; // ~3 samples per second
    	its.it_interval.tv_sec = its.it_value.tv_sec;
    	its.it_interval.tv_nsec = its.it_value.tv_nsec;
    
    	if (timer_settime(timerid, 0, &its, NULL) == -1)
    	{
    		printf("timer_settime error\n");
    		exit(1);
    	}
    }
    
    void scan_stop (void) {
    	printf("scan destroyed!\n");
    	struct itimerspec its;
    	memset((void*)&its, 0, sizeof(its));
    	if (timer_settime(timerid, 0, &its, NULL) == -1)
    	{
    		printf("error disarming timer\n");
    		exit(1);
    	}
    }
    However now it says "timer_settime error" when it tries to re-activate the timer the first time.

  4. #4
    Just Joined!
    Join Date
    Oct 2009
    Posts
    14
    OK, it looks like scan_stop() and scan_start() work if called right after each other. However, between scan_stop() and scan_start() I need to start a separate timer that is done so like this.
    Code:
    void ann_collision (int impact) {
    	struct sigevent sev;
    	struct itimerspec its;
    	/* Install our SIGALRM signal handler */
    	struct sigaction sa;
    
    	sa.sa_sigaction = ann_undo_handler;
    	sigemptyset( &sa.sa_mask );
    	sa.sa_flags = SA_SIGINFO; /* we want a siginfo_t */
    	if (sigaction (SIGALRM, &sa, 0)) {
    		printf("sigaction error");
    		exit(1);
    	}
    
    	/* Create the timer */
    
    	sev.sigev_notify = SIGEV_SIGNAL;
    	sev.sigev_signo = SIGALRM;
    	sev.sigev_value.sival_ptr = &timerid;
    	if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1)
    	{
    		printf("timer_create error");
    		exit(1);
    	}
    
    	/* Start the timer */
    
    	its.it_value.tv_sec = 0;
    	its.it_value.tv_nsec = 350000000; // ~3 samples per second
    	its.it_interval.tv_sec = its.it_value.tv_sec;
    	its.it_interval.tv_nsec = its.it_value.tv_nsec;
    
    	if (timer_settime(timerid, 0, &its, NULL) == -1)
    	{
    		printf("timer_settime error");
    		exit(1);
    	}
    }
    
    void ann_undo_handler ( int cause, siginfo_t *HowCome, void *ucontext ) {
    	struct timeval time;
    	static int step = 0;
    	double us = move_log[step].time.tv_sec * 1000000 + move_log[step].time.tv_usec;
    	us -= move_log[step + 1].time.tv_sec * 1000000 + move_log[step + 1].time.tv_usec;
    	int sec = (int) us / 1000000;
    	int usec = us - (sec * 1000000);
    
    	struct itimerspec its;
    	its.it_value.tv_sec = sec;
    	its.it_value.tv_nsec = usec * 1000;
    	its.it_interval.tv_sec = its.it_value.tv_sec;
    	its.it_interval.tv_nsec = its.it_value.tv_nsec;
    
    	printf("Next interval: %d %d\n", sec, usec);
    	if (timer_settime(timerid, 0, &its, NULL) == -1)
    	{
    		printf("timer_settime error");
    		exit(1);
    	}
    
    	Set_Motor1(-move_log[step].motor1);
    	Set_Motor2(-move_log[step].motor2);
    
    	gettimeofday(&time, NULL);
    	printf("Current time: %ld %ld\n", (long int)time.tv_sec, (long int)time.tv_usec);
    	step++;
    	if (step > UNDO_LEN - 2) {
    		step = 0;
    		timer_delete(timerid);
    		Set_Motor1(0);
    		Set_Motor2(0);
    		scan_start();
    		accel_init();
    	}
    }
    For some reason after that code is run scan_start() fails.

    Keep in mind that that code is in a separate file so this timerid should be in a different scope.

    EDIT: I should probably also say I am trying to run three different timers using the signals SIGUSR1, SIGUSR2, and SIGALRM. The two timers using SIGUSR1 and SIGUSR2 are stopped while the one using SIGALRM is running, so it could be possible to use only two timers.

  5. #5
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
    Posts
    8,974
    I haven't run into this problem, but you might want to zero out the timer id between creations. However, why do that? Why not just create it, and rather than destroying it and recreating it, simply disarm it.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  6. #6
    Just Joined!
    Join Date
    Oct 2009
    Posts
    14
    I tried doing that (post #3 edit).

    When I tried to arm the timer after disarming it timer_settime() returned -1. I can arm it if I don't make another timer after disarming the first one (post #4)

  7. #7
    Just Joined!
    Join Date
    Oct 2009
    Posts
    14
    I just though of something, it isn't necessary to stop the timer at all, but just switch the sigaction(). Is it possible to remove a sigaction?

  8. #8
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
    Posts
    8,974
    You could just change the handler to SIG_IGN (the ignore signal handler). See the sigaction() man page.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  9. #9
    Just Joined!
    Join Date
    Oct 2009
    Posts
    14
    Thanks Rubberman! You've been a huge help. I have it working now, I simply switched the signal handler for one of the timers and set the other to ignore.

    Thanks again,
    JR

  10. #10
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
    Posts
    8,974
    Quote Originally Posted by embmicro View Post
    Thanks Rubberman! You've been a huge help. I have it working now, I simply switched the signal handler for one of the timers and set the other to ignore.

    Thanks again,
    JR
    As some wise person once said, "It may not be elegant, but it works!"...
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...