[Search for users]
[Overall Top Noters]
[List of all Conferences]
[Download this site]
Title: | DIGITAL UNIX (FORMERLY KNOWN AS DEC OSF/1) |
Notice: | Welcome to the Digital UNIX Conference |
Moderator: | SMURF::DENHAM |
|
Created: | Thu Mar 16 1995 |
Last Modified: | Fri Jun 06 1997 |
Last Successful Update: | Fri Jun 06 1997 |
Number of topics: | 10068 |
Total number of notes: | 35879 |
10007.0. "POSIX 4.0 TIMERS PROBLEM" by IB004::BERNAT () Mon Jun 02 1997 06:55
I faced a problem working with real-time timers under POSIX 4.0
on Digital Unix version 4.0.
My application requires a real time timer to generate a signal
every sampling period, in order to gather data from a physical
process. This sampling period must be constant (about 3 milliseconds).
I built a little test program in order to work out the timing
precision provided by POSIX 4.0 interface of Digital Unix 4.0.
This program called "rt_test4.c" comes in the next pages.
The working is very simple. Every time the timer generates a
SIGALRM signal, the current time is obtained through a call to
the function "clock_gettime()". This time in microseconds
is sent to the standard output, as well as the difference with
regard to the value returned by "clock_gettime()" in the
previous call.
In theory, these differences should be constant and a multiple
of the resolution of the timer.
Nevertheless, the differences are not multiple of the resolution
, 976562 nanoseconds, but multiple of 976000 nanoseconds.
This problem is not very important because I could choose a
sampling period multiple of 976000 nanoseconds.
There is another problem much more important. Every time the field
"tv_sec" of the structure returned by "clock_gettime()"
changes of value, a change in the difference happens. Therefore,
once per second, my system would take an incorrect sample.
In the next pages you can find the ASCII files generated by
the program for 2 different settings of period between SIGALRM
signals. "rt_out4.dat1" is for a period of 976
microseconds whereas "rt_out4.dat2" is for a period of
(60*976) microseconds. Only relevant samples of time were kept,
the rest were substituted by horizontal ellipses.
How can I do to fix the problem with real time timers ?
Apart from the problem with timers, I faced also a problem with
the definition of constants "MCL_CURRENT" and
"MCL_FUTURE" to lock memory. In theory, these constants should be
accesible, by simply including the header <sys/mman.h>.
Nevertheless, it was also necessary to define the constant
"_OSF_SOURCE". This behaviour, I think, is out of the standard
and is not documented anywhere.
Defining the constant "_OSF_SOURCE" in my source files may generate
some kind of problems working with POSIX 4.0 interface ?
Please, I hope you can answer as soon as possible.
Thank you very much in advance.
Jos� Mar�a Bernat (CSC Barcelona)
/* rt_test4.c
This is a little program to test POSIX4.0 real time timers.
A real time timer is installed. This timer generates a SIGGALRM
signal every TIME_PERIOD microseconds
After the initialization phase, the process enters into an infinite
loop whose first instruction is wait for the SIGALRM signal. Then the
process awakes, gets the current time of the timer and prints:
- time value of the timer
- difference of that value with regard to the value got in the
previous cycle
In order to avoid swapping and paging problems memory is locked.
Besides, priority of the process is set to the maximum so as to prevent
other process from taking over the CPU.
Finally this program runs under superuser privileges.
The compilation command is:
cc -non_shared -w0 rt_test4.c -lrt -o rt_test4
Output of the program was redirected to the file "rt_out4.dat"
*/
/* ??????????
definition of _OSF_SOURCE is needed in order to deal
with the constants MCL_CURRENT and MCL_FUTURE.
May it produce some kind of lateral effects in my
programs ?, because this behaviour is out of the standar. */
#define _OSF_SOURCE
#define _POSIX_C_SOURCE 199309 /* POSIX4.0 */
#include <unistd.h>
#include <sys/mman.h>
#include <signal.h>
#include <time.h>
#include <sched.h>
#include <math.h>
#include <stdio.h>
#define TIME_PERIOD (60 * 976) /* time period in microseconds between 2 */
/* subsequent alarms */
#define BUFFER_SIZE (1024 * 1024)
/* buffer where output will be stored until program exits and it is
dumped */
char buffer[BUFFER_SIZE];
void control_c_handler(int signum)
{
/* the program ends after a ^C, dumping the information contained
in the buffer */
fprintf(stderr, "\nTiming trace dumped");
printf(buffer);
fprintf(stderr, "\nAborting process\n\n");
exit(0);
}
void main()
{
sigset_t these_sigs;
timer_t created_timer;
struct itimerspec timer_setting;
struct timespec realtime_res;
struct timespec now;
FILE * file_ptr;
int init = 1;
double time_usec;
double prev_time_usec;
struct sched_param scheduling_parameters;
struct sigaction action;
char *buffer_ptr;
/* set scheduling policy to FIFO and priority to maximum */
if ((scheduling_parameters.sched_priority =
sched_get_priority_max(SCHED_FIFO)) == -1)
perror("sched_get_priority_max");
if (sched_setscheduler(getpid(), SCHED_FIFO, &scheduling_parameters) == -1)
perror("sched_setscheduler");
/* lock memory */
if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1)
perror("mlockall");
/* create a timer that generates a periodic SIGALRM every 976 microseconds */
(void)timer_create(CLOCK_REALTIME, NULL, &created_timer);
timer_setting.it_value.tv_sec = 1;
timer_setting.it_value.tv_nsec = 0;
timer_setting.it_interval.tv_sec = 0;
timer_setting.it_interval.tv_nsec = TIME_PERIOD*1000;
(void)timer_settime(created_timer, 0, &timer_setting, NULL);
/* set the handler for the ^C */
action.sa_handler = control_c_handler;
(void)sigemptyset(&action.sa_mask);
action.sa_flags = 0;
if (sigaction(SIGINT, &action, (struct sigaction *)NULL) == -1)
perror("sigaction");
(void)sigfillset(&these_sigs);
(void)sigdelset(&these_sigs, SIGINT);
(void)sigprocmask(SIG_BLOCK, &these_sigs, NULL);
/* "sigwaitinfo" will wait for SIGALRM */
(void)sigemptyset(&these_sigs);
(void)sigaddset(&these_sigs, SIGALRM);
/* initialize the buffer pointer */
buffer_ptr = buffer;
/* get real time clock resolution */
(void)clock_getres(CLOCK_REALTIME, &realtime_res);
buffer_ptr +=
sprintf(buffer_ptr, "\nReal time clock resolution = %f useconds\n\n",
realtime_res.tv_sec * 1000000.0 +
realtime_res.tv_nsec / 1000.0);
for (;;)
{
/* sleep until a SIGALRM arrives */
(void)sigwaitinfo(&these_sigs, NULL);
/* get the current time */
(void)clock_gettime(CLOCK_REALTIME, &now);
prev_time_usec = time_usec;
/* calculate the current time in microseconds */
time_usec = now.tv_sec * 1000000.0 + now.tv_nsec /1000.0;
if (init == 1)
init = 0;
else
if ((buffer_ptr - buffer) < (BUFFER_SIZE - 256))
buffer_ptr +=
sprintf(buffer_ptr, "%f\t%f\n", time_usec,
time_usec - prev_time_usec);
}
}
rt_out4.dat1
Real time clock resolution = 976.562000 useconds
864927879989664.000000 976.000000
864927879990640.000000 976.000000
864927879991616.000000 976.000000
864927879992592.000000 976.000000
864927879993568.000000 976.000000
864927879994544.000000 976.000000
864927879995520.000000 976.000000
864927879996496.000000 976.000000
864927879997472.000000 976.000000
864927879998448.000000 976.000000
864927880000000.000000 1552.000000 <---------- PROBLEM !!!!
864927880000976.000000 976.000000
864927880001952.000000 976.000000
............................
864927880995520.000000 976.000000
864927880996496.000000 976.000000
864927880997472.000000 976.000000
864927880998448.000000 976.000000
864927881000000.000000 1552.000000 <---------- PROBLEM !!!!
864927881000976.000000 976.000000
864927881001952.000000 976.000000
864927881002928.000000 976.000000
............................
864927881995520.000000 976.000000
864927881996496.000000 976.000000
864927881997472.000000 976.000000
864927881998448.000000 976.000000
864927882000000.000000 1552.000000 <---------- PROBLEM !!!!
864927882000976.000000 976.000000
864927882001952.000000 976.000000
864927882002928.000000 976.000000
864927882003904.000000 976.000000
864927882004880.000000 976.000000
864927882005856.000000 976.000000
864927882006832.000000 976.000000
............................
864927882995520.000000 976.000000
864927882996496.000000 976.000000
864927882997472.000000 976.000000
864927882998448.000000 976.000000
864927883000000.000000 1552.000000 <---------- PROBLEM !!!!
864927883000976.000000 976.000000
864927883001952.000000 976.000000
............................
rt_out4.dat2
Real time clock resolution = 976.562000 useconds
864928070461648.000000 58560.000000
864928070520208.000000 58560.000000
864928070578768.000000 58560.000000
864928070637328.000000 58560.000000
864928070695888.000000 58560.000000
864928070754448.000000 58560.000000
864928070813008.000000 58560.000000
864928070871568.000000 58560.000000
864928070930128.000000 58560.000000
864928070988688.000000 58560.000000
864928071048800.000000 60112.000000 <---------- PROBLEM !!!!
864928071107360.000000 58560.000000
864928071165920.000000 58560.000000
864928071224480.000000 58560.000000
864928071283040.000000 58560.000000
864928071341600.000000 58560.000000
864928071400160.000000 58560.000000
864928071458720.000000 58560.000000
864928071517280.000000 58560.000000
864928071575840.000000 58560.000000
864928071634400.000000 58560.000000
864928071692960.000000 58560.000000
864928071751520.000000 58560.000000
864928071810080.000000 58560.000000
864928071868640.000000 58560.000000
864928071927200.000000 58560.000000
864928071985760.000000 58560.000000
864928072045872.000000 60112.000000 <---------- PROBLEM !!!!
864928072104432.000000 58560.000000
864928072162992.000000 58560.000000
864928072221552.000000 58560.000000
............................
864928072924272.000000 58560.000000
864928072982832.000000 58560.000000
864928073042944.000000 60112.000000 <---------- PROBLEM !!!!
864928073101504.000000 58560.000000
864928073160064.000000 58560.000000
............................
864928073862784.000000 58560.000000
864928073921344.000000 58560.000000
864928073979904.000000 58560.000000
864928074040016.000000 60112.000000 <---------- PROBLEM !!!!
864928074098576.000000 58560.000000
864928074157136.000000 58560.000000
............................
T.R | Title | User | Personal Name | Date | Lines |
---|
10007.1 | | SMURF::DENHAM | Digital UNIX Kernel | Mon Jun 02 1997 11:59 | 18 |
| The _OSF_SOURCE and the mman.h header file thing is a bug. Please
QAR it. The best workaround is to *not* define any standards
macros when you build -- then you get everything for free.
As to the behavior of the clock, you're things are they really
are. First, the kernel keeps time with microsecond resolution,
not nanosecond. So those extra nanoseconds you're getting back
don't really exist as far as the kernel is concerned. But they
do add up, as you've seen.
The other effect you're seeing is that once a second the kernel
has to make up for the fact that is clock frequency isn't a multiple
of 10. So it adds the missing microseconds (576 on most platforms,
400 on the 4100 series) into the system time to keep in synch.
You can virtually eliminate this leap effect by turning on the
MICRO_TIME option, which tends to smooth out the movements
of the system time.
|
10007.2 | "core dumped" ooops | HELIX::SONTAKKE | | Mon Jun 02 1997 18:08 | 6 |
| Was there any load on the system? Because when you really want to use
your sampling period to do "some real work", the 3 ms time period is
going to be *very* close. I hope the system is not connected to
nuclear power plant or something like that :-)
- Vikas
|
10007.3 | How I turn the MICRO_TIME option on ? | IB004::BERNAT | | Thu Jun 05 1997 03:38 | 4 |
| How can I turn the MICRO_TIME option on ?
I've tried, but result was not the expected. Could you help me with this ?
Thank you very again.
|
10007.4 | options MICRO_TIME | RHETT::PARKER | | Thu Jun 05 1997 10:05 | 11 |
|
Place the following in /sys/conf/SYSNAME :
options MICRO_TIME
and then rebuild the kernel. This is in the release notes.
Hth,
Lee
|