home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #1 / NN_1993_1.iso / spool / comp / unix / bsd / 10895 < prev    next >
Encoding:
Text File  |  1993-01-04  |  6.0 KB  |  300 lines

  1. Path: sparky!uunet!ogicse!pdxgate!jrb@rigel.cs.pdx.edu
  2. From: jrb@rigel.cs.pdx.edu (James Binkley)
  3. Newsgroups: comp.unix.bsd
  4. Subject: bug in setitimer?
  5. Message-ID: <6648@pdxgate.UUCP>
  6. Date: 3 Jan 93 21:23:26 GMT
  7. Article-I.D.: pdxgate.6648
  8. Sender: news@pdxgate.UUCP
  9. Lines: 289
  10.  
  11. I'm trying to use setitimer with the REAL TIMER (ITIMER_REAL) to 
  12. get so many interrupts per second on 386BSD; .e.g,
  13.     setitimer(ITIMER_REAL, &ival, NULL);
  14. So far I can't make it work correctly in terms of time.  You get
  15. ALARM signals but you seemingly can't get better
  16. than 10 intr/sec. Anybody else have any ideas? 
  17. I'll start digging into the kernel but wondered
  18. if anybody else might have encountered this or might
  19. have a logical explanation?
  20.  
  21. There is sample code at the end and the output
  22. results from 3 runs below. The first on a Sun,
  23. the 2nd two on a 386BSD system. The total elapsed
  24. time should roughly be 5 seconds as it is on the
  25. Sun. The input to clk is in "bpm" or beats per minute 
  26. and is translated into hertz and usecs for the setitimer
  27. call.  (I'm porting some pc music code to 386bsd and at 
  28. least I have a mpu driver working.)
  29.  
  30.  
  31.                 Jim Binkley
  32.                 jrb@cs.pdx.edu
  33.  
  34. ----------------------------------------------------------
  35. sun run:
  36.  
  37. bash$ /bin/time clk 48
  38. hertz 19 bpm 48
  39. setclock: START: hertz bpm usecs 19 48 52631
  40. closeClock: interrupts == 95
  41. count 95
  42.         5.3 real         4.7 user         0.1 sys  
  43.  
  44. ----------------------------------------------------------
  45. 386bsd run:
  46.  
  47. bash% /usr/bin/time clk 48 
  48. hertz 19 bpm 48 
  49. setclock: START: hertz bpm usecs 19 48 52631   
  50. closeClock: interrupts == 97 
  51. count 95 
  52.         9.27 real         8.80 user         0.31 sys 
  53.  
  54. interrupts/time == 10hz roughly
  55. ----------------------------------------------------------
  56. bash% /usr/bin/time clk 100 
  57. hertz 40 bpm 100 
  58. setclock: START: hertz bpm usecs 40 100 25000 
  59. closeClock: interrupts == 201 
  60. count 200 
  61.        17.92 real        17.66 user         0.14 sys
  62.  
  63. interrupts/time == still 10hz roughly
  64.  
  65. -----------------------------------slice here-----------------
  66. /*
  67.  * clk.c
  68.  *
  69.  * To compile:
  70.  *    cc -o clk clk.c
  71.  * To run:
  72.  *    /usr/bin/time (or /bin/time) clk 48
  73.  *    /usr/bin/time (or /bin/time) clk 255
  74.  *
  75.  * Should take roughly 5 seconds in both cases approximately.
  76.  *
  77.  * Uses setitimer(2), ITIMER_REAL for interrupt clock.
  78.  */
  79. #ifdef unix
  80. #include <stdio.h>
  81. #include <sys/signal.h>
  82. #include <sys/time.h>
  83. #endif
  84.  
  85. #define DEBUG
  86. #define TESTMAIN
  87.  
  88. #define QEVENTS        24        /* no of events per beat */
  89. #define LOWBPM        48              /* lowest acceptable metronome */
  90. #define HIBPM           255              /* highest acceptable metronome */
  91. #define TRUE         1
  92. #define FALSE         0
  93.  
  94. /* bpm is a module input that is translated into hertz
  95. */
  96. static unsigned int hertz;              /* current hertz */
  97. static int bpm;                /* current beats per minute */
  98.  
  99. /* scheduling flags. Flags shared between interrupt routine
  100.  * and scheduler.
  101.  */
  102. int inevents;           /* true if sched executing event code */
  103. int timewow;          /* true if clock interrupt during event code */
  104. int pendclk;          /* True if no clk interrupt yet */
  105.  
  106. /* error string printed if attempt occurs to set hbeat clk out of range
  107. */
  108. static char *bpmsyntax = "error: bpm range 48..255";
  109.  
  110. static int clockon=0;
  111. unsigned long interrupts;
  112.  
  113. openClock()
  114. {
  115.     /* set new clock rate according to bpm. setclock
  116.      * fiddles with hw.
  117.      */
  118.     setclock(FALSE);
  119.  
  120.     clockon = 1;
  121.     interrupts = 0L;
  122. }
  123.  
  124. closeClock()
  125. {
  126.     if (clockon == 0)
  127.         return;
  128.     setclock(TRUE);         /* restore pc time */
  129.     clockon = 0;
  130. #ifdef DEBUG
  131.     printf("closeClock: interrupts == %ld\n", interrupts);
  132. #endif
  133. }
  134.  
  135.  
  136. /* check bpm semantics. must be between LOWBPM..HIBPM
  137.  * inclusive.
  138.  */
  139. chkbpm(newbpm)
  140. {
  141.     if ( newbpm < LOWBPM ) {
  142.         setError(bpmsyntax);
  143.         return(0);
  144.     }
  145.     if ( newbpm > HIBPM ) {
  146.         setError(bpmsyntax);
  147.         return(0);
  148.     }
  149.     return(1);
  150. }
  151.  
  152. setbpm(newbpm)
  153. {
  154.     unsigned int timebase;
  155.     if (chkbpm(newbpm) == 0)
  156.         return;
  157.     bpm = newbpm;
  158.     hertz = (unsigned int) ((bpm * QEVENTS) / 60);
  159. }
  160.  
  161. /* outside code can interrogate module to find out what bpm is
  162. */
  163. getbpm()
  164. {
  165.     return(bpm);
  166. }
  167.  
  168. /* setclock
  169.  *
  170.  * modifies runtime clock. Only routine in this module that
  171.  * actually touches hardware.
  172.  */
  173.  
  174. #ifdef unix
  175. struct itimerval ival;
  176. struct itimerval oval;
  177. #endif
  178.  
  179. static
  180. setclock(stopflag)
  181. {
  182.     extern unsigned int hertz;
  183.     unsigned int count;
  184.     unsigned int low;
  185.     unsigned int hi;
  186. #ifdef unix
  187.     unsigned long t;
  188.  
  189.     if (stopflag == TRUE) {
  190.         unixStopClock();
  191.     }
  192.     else {
  193.         unixStopClock();
  194.         if ( hertz > 100 )
  195.             hertz = 100;
  196.         if ( hertz == 0 )
  197.             hertz = 1;
  198.         
  199.         t = 1000000L / hertz;    
  200.         ival.it_interval.tv_sec = 0;
  201.         ival.it_interval.tv_usec = t;
  202.         ival.it_value.tv_sec = 0;
  203.         ival.it_value.tv_usec = t;
  204. #ifdef DEBUG
  205.         printf("setclock: START: hertz bpm usecs %d %d %ld\n", hertz, bpm, t);
  206. #endif
  207.         unixStartClock();
  208.     }
  209.     return;
  210. #endif
  211.  
  212. }
  213.  
  214. #ifdef unix
  215.  
  216. extern void tintr();
  217.  
  218. static
  219. unixStartClock()
  220. {
  221.     ival.it_interval.tv_sec = 0;
  222.     ival.it_value.tv_sec = 0;
  223.     signal(SIGALRM, tintr);
  224.     setitimer(ITIMER_REAL, &ival, NULL);
  225. }
  226.  
  227. unixStopClock()
  228. {
  229.     ival.it_value.tv_sec = 0;
  230.     ival.it_value.tv_usec = 0;
  231.     setitimer(ITIMER_REAL, &ival, NULL);
  232. }
  233.  
  234. void 
  235. tintr()
  236. {
  237.     pendclk = FALSE;         /* interrupt has occured */
  238.     /* clock occured during event execution; i.e., timewow
  239.      * error has occurred
  240.      */
  241.     if ( inevents == TRUE )
  242.         timewow = TRUE;
  243.  
  244. #ifdef DEBUG
  245.     interrupts++;
  246. #endif
  247. }
  248. #endif
  249.  
  250. #ifdef TESTMAIN
  251.  
  252. /* module clocktimer test routine
  253.  *
  254.  * syntax:
  255.  *    clk [bpm]
  256.  *    bpm can vary from 48.255 (beats per minute)
  257.  *    Results:
  258.  *         should take approximately 5 seconds for bpm
  259.  *        == 48 to 255, just more interrupts per second.
  260.  * e.g.,  
  261.  *    /bin/time clk 100
  262.  */
  263. main(argc, argv)
  264. int argc; 
  265. char **argv;
  266. {
  267.     int count=0;
  268.     int lbpm = 120;
  269.     int delaycount;
  270.  
  271.     if (argc == 2)
  272.         lbpm = atoi(argv[1]);
  273.  
  274.     /* 120 bpm means 2 beats per second.
  275.        * 24 "ticks" per quarter note (ppq).
  276.      */
  277.     setbpm(lbpm);  /* compute hertz */
  278.     printf("hertz %d bpm %d\n",hertz, bpm);
  279.     delaycount = 5 * hertz;    /* 5 seconds * intrs/sec */
  280.  
  281.     openClock();
  282.     do {
  283.         pendclk = TRUE;
  284.         while(pendclk)
  285.             ;
  286.         count++;
  287.     }
  288.     while ( count < delaycount );
  289.     closeClock();
  290.  
  291.     printf("count %d\n",count);
  292. }
  293.  
  294. setError(s)
  295. char *s;
  296. {
  297.     printf("%s\n",s);
  298. }
  299. #endif
  300.