home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / sys / sgi / 18315 < prev    next >
Encoding:
Text File  |  1992-12-23  |  4.9 KB  |  167 lines

  1. Newsgroups: comp.sys.sgi
  2. 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
  3. From: ciemo@bananapc.csd.sgi.com (Dave Ciemiewicz)
  4. Subject: Re: How Accurate Is The System Clock
  5. Message-ID: <1992Dec23.232926.22526@odin.corp.sgi.com>
  6. Sender: news@odin.corp.sgi.com (Net News)
  7. Nntp-Posting-Host: bananapc.csd.sgi.com
  8. Organization: Silicon Graphics, Customer Support Division
  9. References: <AJ3U.92Dec22153748@larch.cs.virginia.edu> <1992Dec23.194149.27172@odin.corp.sgi.com>
  10. Distribution: comp
  11. Date: Wed, 23 Dec 1992 23:29:26 GMT
  12. Lines: 153
  13.  
  14. |> In <AJ3U.92Dec22153748@larch.cs.virginia.edu> aj3u@larch.cs.virginia.edu (Asim Jalis) writes:
  15. |> 
  16. |> *I am writing some programs on the SGI that requires millisecond
  17. |> *timing accuracy.  How accurate is the clock on these machines?
  18. |> *with the daemons and the multi-process environment.  If someone
  19. |> *has references for timing measurements or some ideas about how
  20. |> *such timing can be achieved, I would really appreciate hearing
  21. |> *from them.
  22. |> *
  23. |> *Responses can be communicated to me through e-mail.
  24. |> *
  25. |> *
  26. |> *
  27. |> *Asim Jalis.
  28.  
  29. If you are on a system with an IO3 Power Channel, you can use the cycle
  30. counter from there for counting 62.5 nanosecond ticks to get rather
  31. accurate timings.  The following illustrates the use of this fast clock
  32. for timing purposes.
  33.  
  34. /*
  35. **  NAME
  36. **      cyclecntr.c - syssgi(SGI_QUERY_CYCLECNTR) example which reads IO3 counter
  37. **
  38. **  DESCRIPTION
  39. **      The following program reads the Power Channel (IO3 ethernet controller)
  40. **      cycle counter.  This counter increments once every 62.5 nanoseconds
  41. **      (actual interval is returned as number of picoseconds via arg1 of
  42. **      syssgi(SGI_QUERY_CYCLECNTR, arg1) call).  The counter is read by using
  43. **      mmap(2) to make the counter accessible in the programs address space.
  44. **
  45. **      The cycle counter on the IO3 board wraps-around to 0 every
  46. **      0xffffffff * 62.5ns = 268s.  This example takes this into account.
  47. **
  48. **  COMPILATION INSTRUCTIONS
  49. **      cc -o cyclecntr cyclecntr.c
  50. **
  51. **  CAVEATS
  52. **      1) This only works on systems with the IO3 subsystem.  On 3.3.x
  53. **         systems, using hinv(1) will return the information as:
  54. **
  55. **              Integral Ethernet controller: Version 3
  56. **
  57. **         On 4.0 systems, hinv(1) will report:
  58. **
  59. **              Integral Ethernet: et0 IO3
  60. **
  61. **
  62. **  AUTHOR
  63. **      Dave Ciemiewicz (ciemo)
  64. **      Silicon Graphics Technical Assistance Center
  65. */
  66.  
  67. #include <sys/types.h>
  68. #include <sys/syssgi.h>
  69. #include <sys/mman.h>
  70. #include <fcntl.h>
  71. #include <limits.h>
  72.  
  73. volatile unsigned int* counter;         /* Pointer to IO3 counter.  Must be */
  74.                                         /* volatile so compiler doesn't */
  75.                                         /* optmized away */
  76.  
  77. #define MICROSECS_PER_PICOSEC 1.0e-6
  78.  
  79. #define ITERATIONS 100
  80.  
  81. unsigned int interval[ITERATIONS];
  82.  
  83.  
  84. main()
  85. {
  86.     unsigned long counterTickPicoSecs;
  87.     unsigned int* counterAddr;
  88.     int mmemfd;
  89.     int i;
  90.     unsigned int previousCounter;
  91.     unsigned int currentCounter;
  92.  
  93.     /*
  94.     ** Establish connection to read Power Channel (IO3) counter
  95.     */
  96.     counterAddr = (unsigned*)syssgi(SGI_QUERY_CYCLECNTR, &counterTickPicoSecs);
  97.     
  98.     if (counterAddr == (unsigned*)-1)
  99.     {
  100.         perror("syssgi SGI_QUERY_CYCLECNTR");
  101.         exit(1);
  102.     }
  103.  
  104.     if ((mmemfd = open("/dev/mmem", O_RDONLY, 0)) == -1)
  105.     {
  106.         perror("open /dev/mmem");
  107.         exit(1);
  108.     }
  109.  
  110.     counter = mmap(0, sizeof(*counter), PROT_READ, MAP_PRIVATE, mmemfd,
  111.                 (unsigned)counterAddr);
  112.     if (counter == (unsigned int*)-1)
  113.     {
  114.         perror("mmap counter");
  115.         exit(1);
  116.     }
  117.  
  118.     /*
  119.     **  Try reading counter
  120.     */
  121.     previousCounter = 0;
  122.     for (i=0; i<=ITERATIONS; i++)
  123.     {
  124.         currentCounter = *counter;      /* reads current value from mmapped */
  125.                                         /* IO3 board counter */
  126.         if (i != 0) {
  127.              /*
  128.              **  Compute time interval and take into account counter
  129.              **  wraparound.
  130.              */
  131.              interval[i] = (currentCounter >= previousCounter) ?
  132.                      currentCounter - previousCounter :
  133.                      currentCounter + UINT_MAX - previousCounter;
  134.         }
  135.  
  136.         previousCounter = currentCounter;
  137.     }
  138.  
  139.  
  140.     /*
  141.     **  Print results.  Results are not printed in loop because they increase
  142.     **  interval.
  143.     */
  144.     for (i=1; i<=ITERATIONS; i++)
  145.     {
  146.         printf("Interval %d: ticks %d, time %.4f microsecs\n", i, interval[i],
  147.                  interval[i] * counterTickPicoSecs * MICROSECS_PER_PICOSEC);
  148.     }
  149.  
  150.  
  151.     /*
  152.     ** Close down and clean up
  153.     */
  154.  
  155.     if (munmap((void*)counter, sizeof(*counter)) == -1)
  156.     {
  157.         perror("munmap");
  158.         exit(1);
  159.     }
  160.  
  161.     if (close(mmemfd) == -1)
  162.     {
  163.         perror("close /dev/mmem");
  164.         exit(1);
  165.     }
  166. }
  167.