home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!ogicse!pdxgate!jrb@rigel.cs.pdx.edu
- From: jrb@rigel.cs.pdx.edu (James Binkley)
- Newsgroups: comp.unix.bsd
- Subject: bug in setitimer?
- Message-ID: <6648@pdxgate.UUCP>
- Date: 3 Jan 93 21:23:26 GMT
- Article-I.D.: pdxgate.6648
- Sender: news@pdxgate.UUCP
- Lines: 289
-
- I'm trying to use setitimer with the REAL TIMER (ITIMER_REAL) to
- get so many interrupts per second on 386BSD; .e.g,
- setitimer(ITIMER_REAL, &ival, NULL);
- So far I can't make it work correctly in terms of time. You get
- ALARM signals but you seemingly can't get better
- than 10 intr/sec. Anybody else have any ideas?
- I'll start digging into the kernel but wondered
- if anybody else might have encountered this or might
- have a logical explanation?
-
- There is sample code at the end and the output
- results from 3 runs below. The first on a Sun,
- the 2nd two on a 386BSD system. The total elapsed
- time should roughly be 5 seconds as it is on the
- Sun. The input to clk is in "bpm" or beats per minute
- and is translated into hertz and usecs for the setitimer
- call. (I'm porting some pc music code to 386bsd and at
- least I have a mpu driver working.)
-
-
- Jim Binkley
- jrb@cs.pdx.edu
-
- ----------------------------------------------------------
- sun run:
-
- bash$ /bin/time clk 48
- hertz 19 bpm 48
- setclock: START: hertz bpm usecs 19 48 52631
- closeClock: interrupts == 95
- count 95
- 5.3 real 4.7 user 0.1 sys
-
- ----------------------------------------------------------
- 386bsd run:
-
- bash% /usr/bin/time clk 48
- hertz 19 bpm 48
- setclock: START: hertz bpm usecs 19 48 52631
- closeClock: interrupts == 97
- count 95
- 9.27 real 8.80 user 0.31 sys
-
- interrupts/time == 10hz roughly
- ----------------------------------------------------------
- bash% /usr/bin/time clk 100
- hertz 40 bpm 100
- setclock: START: hertz bpm usecs 40 100 25000
- closeClock: interrupts == 201
- count 200
- 17.92 real 17.66 user 0.14 sys
-
- interrupts/time == still 10hz roughly
-
- -----------------------------------slice here-----------------
- /*
- * clk.c
- *
- * To compile:
- * cc -o clk clk.c
- * To run:
- * /usr/bin/time (or /bin/time) clk 48
- * /usr/bin/time (or /bin/time) clk 255
- *
- * Should take roughly 5 seconds in both cases approximately.
- *
- * Uses setitimer(2), ITIMER_REAL for interrupt clock.
- */
- #ifdef unix
- #include <stdio.h>
- #include <sys/signal.h>
- #include <sys/time.h>
- #endif
-
- #define DEBUG
- #define TESTMAIN
-
- #define QEVENTS 24 /* no of events per beat */
- #define LOWBPM 48 /* lowest acceptable metronome */
- #define HIBPM 255 /* highest acceptable metronome */
- #define TRUE 1
- #define FALSE 0
-
- /* bpm is a module input that is translated into hertz
- */
- static unsigned int hertz; /* current hertz */
- static int bpm; /* current beats per minute */
-
- /* scheduling flags. Flags shared between interrupt routine
- * and scheduler.
- */
- int inevents; /* true if sched executing event code */
- int timewow; /* true if clock interrupt during event code */
- int pendclk; /* True if no clk interrupt yet */
-
- /* error string printed if attempt occurs to set hbeat clk out of range
- */
- static char *bpmsyntax = "error: bpm range 48..255";
-
- static int clockon=0;
- unsigned long interrupts;
-
- openClock()
- {
- /* set new clock rate according to bpm. setclock
- * fiddles with hw.
- */
- setclock(FALSE);
-
- clockon = 1;
- interrupts = 0L;
- }
-
- closeClock()
- {
- if (clockon == 0)
- return;
- setclock(TRUE); /* restore pc time */
- clockon = 0;
- #ifdef DEBUG
- printf("closeClock: interrupts == %ld\n", interrupts);
- #endif
- }
-
-
- /* check bpm semantics. must be between LOWBPM..HIBPM
- * inclusive.
- */
- chkbpm(newbpm)
- {
- if ( newbpm < LOWBPM ) {
- setError(bpmsyntax);
- return(0);
- }
- if ( newbpm > HIBPM ) {
- setError(bpmsyntax);
- return(0);
- }
- return(1);
- }
-
- setbpm(newbpm)
- {
- unsigned int timebase;
- if (chkbpm(newbpm) == 0)
- return;
- bpm = newbpm;
- hertz = (unsigned int) ((bpm * QEVENTS) / 60);
- }
-
- /* outside code can interrogate module to find out what bpm is
- */
- getbpm()
- {
- return(bpm);
- }
-
- /* setclock
- *
- * modifies runtime clock. Only routine in this module that
- * actually touches hardware.
- */
-
- #ifdef unix
- struct itimerval ival;
- struct itimerval oval;
- #endif
-
- static
- setclock(stopflag)
- {
- extern unsigned int hertz;
- unsigned int count;
- unsigned int low;
- unsigned int hi;
- #ifdef unix
- unsigned long t;
-
- if (stopflag == TRUE) {
- unixStopClock();
- }
- else {
- unixStopClock();
- if ( hertz > 100 )
- hertz = 100;
- if ( hertz == 0 )
- hertz = 1;
-
- t = 1000000L / hertz;
- ival.it_interval.tv_sec = 0;
- ival.it_interval.tv_usec = t;
- ival.it_value.tv_sec = 0;
- ival.it_value.tv_usec = t;
- #ifdef DEBUG
- printf("setclock: START: hertz bpm usecs %d %d %ld\n", hertz, bpm, t);
- #endif
- unixStartClock();
- }
- return;
- #endif
-
- }
-
- #ifdef unix
-
- extern void tintr();
-
- static
- unixStartClock()
- {
- ival.it_interval.tv_sec = 0;
- ival.it_value.tv_sec = 0;
- signal(SIGALRM, tintr);
- setitimer(ITIMER_REAL, &ival, NULL);
- }
-
- unixStopClock()
- {
- ival.it_value.tv_sec = 0;
- ival.it_value.tv_usec = 0;
- setitimer(ITIMER_REAL, &ival, NULL);
- }
-
- void
- tintr()
- {
- pendclk = FALSE; /* interrupt has occured */
- /* clock occured during event execution; i.e., timewow
- * error has occurred
- */
- if ( inevents == TRUE )
- timewow = TRUE;
-
- #ifdef DEBUG
- interrupts++;
- #endif
- }
- #endif
-
- #ifdef TESTMAIN
-
- /* module clocktimer test routine
- *
- * syntax:
- * clk [bpm]
- * bpm can vary from 48.255 (beats per minute)
- * Results:
- * should take approximately 5 seconds for bpm
- * == 48 to 255, just more interrupts per second.
- * e.g.,
- * /bin/time clk 100
- */
- main(argc, argv)
- int argc;
- char **argv;
- {
- int count=0;
- int lbpm = 120;
- int delaycount;
-
- if (argc == 2)
- lbpm = atoi(argv[1]);
-
- /* 120 bpm means 2 beats per second.
- * 24 "ticks" per quarter note (ppq).
- */
- setbpm(lbpm); /* compute hertz */
- printf("hertz %d bpm %d\n",hertz, bpm);
- delaycount = 5 * hertz; /* 5 seconds * intrs/sec */
-
- openClock();
- do {
- pendclk = TRUE;
- while(pendclk)
- ;
- count++;
- }
- while ( count < delaycount );
- closeClock();
-
- printf("count %d\n",count);
- }
-
- setError(s)
- char *s;
- {
- printf("%s\n",s);
- }
- #endif
-