home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sys.sgi
- Path: sparky!uunet!paladin.american.edu!howland.reston.ans.net!zaphod.mps.ohio-state.edu!sdd.hp.com!think.com!spool.mu.edu!sgiblab!sgigate!odin!bananapc.csd.sgi.com!ciemo
- From: ciemo@bananapc.csd.sgi.com (Dave Ciemiewicz)
- Subject: Re: How Accurate Is The System Clock
- Message-ID: <1992Dec23.232926.22526@odin.corp.sgi.com>
- Sender: news@odin.corp.sgi.com (Net News)
- Nntp-Posting-Host: bananapc.csd.sgi.com
- Organization: Silicon Graphics, Customer Support Division
- References: <AJ3U.92Dec22153748@larch.cs.virginia.edu> <1992Dec23.194149.27172@odin.corp.sgi.com>
- Distribution: comp
- Date: Wed, 23 Dec 1992 23:29:26 GMT
- Lines: 153
-
- |> In <AJ3U.92Dec22153748@larch.cs.virginia.edu> aj3u@larch.cs.virginia.edu (Asim Jalis) writes:
- |>
- |> *I am writing some programs on the SGI that requires millisecond
- |> *timing accuracy. How accurate is the clock on these machines?
- |> *with the daemons and the multi-process environment. If someone
- |> *has references for timing measurements or some ideas about how
- |> *such timing can be achieved, I would really appreciate hearing
- |> *from them.
- |> *
- |> *Responses can be communicated to me through e-mail.
- |> *
- |> *
- |> *
- |> *Asim Jalis.
-
- If you are on a system with an IO3 Power Channel, you can use the cycle
- counter from there for counting 62.5 nanosecond ticks to get rather
- accurate timings. The following illustrates the use of this fast clock
- for timing purposes.
-
- /*
- ** NAME
- ** cyclecntr.c - syssgi(SGI_QUERY_CYCLECNTR) example which reads IO3 counter
- **
- ** DESCRIPTION
- ** The following program reads the Power Channel (IO3 ethernet controller)
- ** cycle counter. This counter increments once every 62.5 nanoseconds
- ** (actual interval is returned as number of picoseconds via arg1 of
- ** syssgi(SGI_QUERY_CYCLECNTR, arg1) call). The counter is read by using
- ** mmap(2) to make the counter accessible in the programs address space.
- **
- ** The cycle counter on the IO3 board wraps-around to 0 every
- ** 0xffffffff * 62.5ns = 268s. This example takes this into account.
- **
- ** COMPILATION INSTRUCTIONS
- ** cc -o cyclecntr cyclecntr.c
- **
- ** CAVEATS
- ** 1) This only works on systems with the IO3 subsystem. On 3.3.x
- ** systems, using hinv(1) will return the information as:
- **
- ** Integral Ethernet controller: Version 3
- **
- ** On 4.0 systems, hinv(1) will report:
- **
- ** Integral Ethernet: et0 IO3
- **
- **
- ** AUTHOR
- ** Dave Ciemiewicz (ciemo)
- ** Silicon Graphics Technical Assistance Center
- */
-
- #include <sys/types.h>
- #include <sys/syssgi.h>
- #include <sys/mman.h>
- #include <fcntl.h>
- #include <limits.h>
-
- volatile unsigned int* counter; /* Pointer to IO3 counter. Must be */
- /* volatile so compiler doesn't */
- /* optmized away */
-
- #define MICROSECS_PER_PICOSEC 1.0e-6
-
- #define ITERATIONS 100
-
- unsigned int interval[ITERATIONS];
-
-
- main()
- {
- unsigned long counterTickPicoSecs;
- unsigned int* counterAddr;
- int mmemfd;
- int i;
- unsigned int previousCounter;
- unsigned int currentCounter;
-
- /*
- ** Establish connection to read Power Channel (IO3) counter
- */
- counterAddr = (unsigned*)syssgi(SGI_QUERY_CYCLECNTR, &counterTickPicoSecs);
-
- if (counterAddr == (unsigned*)-1)
- {
- perror("syssgi SGI_QUERY_CYCLECNTR");
- exit(1);
- }
-
- if ((mmemfd = open("/dev/mmem", O_RDONLY, 0)) == -1)
- {
- perror("open /dev/mmem");
- exit(1);
- }
-
- counter = mmap(0, sizeof(*counter), PROT_READ, MAP_PRIVATE, mmemfd,
- (unsigned)counterAddr);
- if (counter == (unsigned int*)-1)
- {
- perror("mmap counter");
- exit(1);
- }
-
- /*
- ** Try reading counter
- */
- previousCounter = 0;
- for (i=0; i<=ITERATIONS; i++)
- {
- currentCounter = *counter; /* reads current value from mmapped */
- /* IO3 board counter */
- if (i != 0) {
- /*
- ** Compute time interval and take into account counter
- ** wraparound.
- */
- interval[i] = (currentCounter >= previousCounter) ?
- currentCounter - previousCounter :
- currentCounter + UINT_MAX - previousCounter;
- }
-
- previousCounter = currentCounter;
- }
-
-
- /*
- ** Print results. Results are not printed in loop because they increase
- ** interval.
- */
- for (i=1; i<=ITERATIONS; i++)
- {
- printf("Interval %d: ticks %d, time %.4f microsecs\n", i, interval[i],
- interval[i] * counterTickPicoSecs * MICROSECS_PER_PICOSEC);
- }
-
-
- /*
- ** Close down and clean up
- */
-
- if (munmap((void*)counter, sizeof(*counter)) == -1)
- {
- perror("munmap");
- exit(1);
- }
-
- if (close(mmemfd) == -1)
- {
- perror("close /dev/mmem");
- exit(1);
- }
- }
-