posix timer drifts when ported to Solaris 10
The following posix timer works on Solaris 6 & 8, but drifts
on Solaris 10 (6.5 seconds behind after 1 minute execution) :
Any ideas?
Ralph Lecessi
ralph.lecessi@lmco.com
******************************
#include <semaphore.h>
#include <thread.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/signal.h>
sem_t* sema=NULL;
thread_t clk_thr_id=NULL,exec_thr_id=NULL;
timer_t _timer;
struct timeval clock_val,prev_clock_val;
double clock_time,sim_time,delta,intv;
void clock_handler(int signo) {
sem_post(sema);
}
void* ClkThr(void* arg){
sigset_t clock_signalset;
struct sigaction clock_action;
struct sigevent clock_event;
struct itimerspec timer_specification;
/* Block all signals except SIGALRM on this thread */
sigfillset(&clock_signalset);
sigdelset(&clock_signalset,SIGALRM);
thr_sigsetmask(SIG_SETMASK,&clock_signalset,NULL);
/* Create clock action which calls clock handler */
sigemptyset(&clock_signalset); /* REMOVE LINE */
clock_action.sa_handler = clock_handler;
clock_action.sa_flags = 0;
sigemptyset(&clock_action.sa_mask);
/* Create event which generates signal SIGALRM */
clock_event.sigev_notify = SIGEV_SIGNAL;
clock_event.sigev_signo = SIGALRM;
/* Specify timer as 62.5ms (initial and period) */
timer_specification.it_interval.tv_sec=0;
timer_specification.it_interval.tv_nsec=62500000;
timer_specification.it_value.tv_sec=0;
timer_specification.it_value.tv_nsec=62500000;
/* Create timer and attach to clock event */
timer_create(CLOCK_REALTIME, &clock_event, &_timer);
/* Attach clock action to signals SIGALRM */
sigaction(SIGALRM, &clock_action, 0);
/* Queue timer as RELATIVE & attach to specification */
timer_settime(_timer, 0,&timer_specification, NULL);
/* Block thread waiting for timer expiration or termination */
for(;;) {
pause();
}
}
void updateTime() {
gettimeofday(&clock_val, NULL);
clock_time = (double) clock_val.tv_sec + ((double) clock_val.tv_usec)/1000000;
delta = clock_time - sim_time;
}
void* ExecThr(void* arg){
for(;;) {
sem_wait(sema);
sim_time += 0.0625;
updateTime();
fprintf(stderr,"CLOCK=%d.%06d",clock_val.tv_sec,clock_val.tv_usec);
if (prev_clock_val.tv_usec>clock_val.tv_usec) {
clock_val.tv_sec -= 1;
clock_val.tv_usec += 1000000;
}
intv = (clock_val.tv_sec-prev_clock_val.tv_sec) + (clock_val.tv_usec-prev_clock_val.tv_usec)/1000000.0;
fprintf(stderr," INTV=%f DEL=%f\n",intv,delta);
prev_clock_val.tv_sec=clock_val.tv_sec;
prev_clock_val.tv_usec=clock_val.tv_usec;
}
}
int main(int argc,char **argv) {
sema=(sem_t*)malloc(sizeof(sem_t));
sem_init(sema,0,0);
updateTime();
sim_time=clock_time;
prev_clock_val.tv_sec=clock_val.tv_sec;
prev_clock_val.tv_usec=clock_val.tv_usec;
if (thr_create(NULL,0,ClkThr,(void *)0,THR_BOUND,&clk_thr_id))
fprintf(stderr,"Can't create thr\n"),exit(1);
if (thr_create(NULL,0,ExecThr,(void *)0,THR_BOUND,&exec_thr_id))
fprintf(stderr,"Can't create thr\n"),exit(1);
thr_exit(0);
return 0;
}

