thyssen@batserver.cs.uq.oz.au (Anthony Thyssen) (09/20/90)
Hello AmigaLand, I am desperately tring to do some timing of a section of C code and any help would be appreciated. Currently I am using both CIA-B timers (linked) to count pulses on the `PHI2' or in 68000 parlance `E' line. This gives a timer able to measure periods of up to about 1 hour! duration. I calculated that the `E' line should be runing at .715Mhz (1/10th of cpu clock rate) and physical measurments (a stop watch over ~20mins) give a figure of .709 +/- .001 Mhz (3 measurements were made). Timing a fixed loop of code (see below) however produced varing results which I beleave is due to the interupt handling of the CPU. IE with the full screen visible this timed to about 42440 +/- 10 `E' ticks. Moveing the screen then so only the title bar was showing (while timing) produced a much lower value (varing a good deal) of 40200 +/- 60 `E' ticks. I am using Disable() during the timed period to stop other tasks. QUESTIONS :- 1) What is the differance bettween Disable-Enable and Forbid-Permit exec library calls? 2) How do you blank the screen? 3) Is there any other interupts which can be disabled? How? 4) Under the above can memory still be allocated/deallocated - Important? 5) Any other comments. Anthony Thyssen - (Dragon Computing!) thyssen@batserver.cs.uq.oz.au ------------------------------------------------------------------------------- In some parts of the city curiosity didn't just kill the cat, It threw it in the river with lead weights tied to its feet. -- Terry Pratchett "Sourcery" -------------------------------------------------------------------------------
ridder@elvira.enet.dec.com (Hans Ridder) (09/21/90)
In article <4934@uqcspe.cs.uq.oz.au> thyssen@batserver.cs.uq.oz.au writes: > I calculated that the `E' line should be runing at .715Mhz (1/10th >of cpu clock rate) and physical measurments (a stop watch over ~20mins) >give a figure of .709 +/- .001 Mhz (3 measurements were made). Since it looks like you are down-under, are you doing this on a PAL Amiga? I don't remember the exact frequency, but I think PAL Amigas run at 7.09MHz (instead of 7.15MHz), giving an E clock of .709MHz. This is well documnted in the 1.3 RKM's, I believe. > Timing a fixed loop of code (see below) however produced varing >results which I beleave is due to the interupt handling of the CPU. > >IE with the full screen visible this timed to about 42440 +/- 10 `E' ticks. >Moveing the screen then so only the title bar was showing (while timing) >produced a much lower value (varing a good deal) of 40200 +/- 60 `E' ticks. My first guess is that your code was running in Chip ram, thus contending with screen (and other) DMA. It would be best if you could run in Fast ram (if you have any). Someone else posted about having troubles with repeatable timing, although I think he was having the timer set an interrupt, and found that something in the system was disabling interrupts (Disable()) for a long time, so his interrupt response time was erratic. (Is that a run-on sentence, or what?) >QUESTIONS :- > 1) What is the differance bettween Disable-Enable > and Forbid-Permit exec library calls? Put simply, Disable() shuts off all interrupts to the processor. This call should only be used when you want to change things which are accessed by interrupt routines. Forbid() just stops task switching. This call should be used when changing things other *tasks* (or processes) access. Beware that a Forbid() can be "broken" (i.e. another task might run) if you do anything which causes a Wait(). You probably don't want to do any DOS I/O (Read(), printf(), etc.) during a Forbid(). > 2) How do you blank the screen? I'm not sure what you mean here. If you just want to "shut off" the display DMA, there is a macro (in the graphics includes, I think) called OFF_DISPLAY, or something like that. Be sure to turn the display back on when you're done. > 3) Is there any other interupts which can be disabled? How? The Amiga is *full* of interrupts. If you don't want anything else to bother you, use Disable(). Note that the system time (and probably other things) will stop during a Disable(), so do this sparingly and probably not in production code. > 4) Under the above can memory still be allocated/deallocated - Important? If you asking if memory can be allocated/deallocated during a Disable(), sure. The only time you should *not* do any memory allocation/deallocation is *inside* an interrupt handler. (Because you could have interrupted someone elses allocation/deallocation.) > 5) Any other comments. Sounds like you need to get/read the Rom Kernel Manuals, published by Addison-Wesley. > Anthony Thyssen - (Dragon Computing!) thyssen@batserver.cs.uq.oz.au -hans ------------------------------------------------------------------------ Hans-Gabriel Ridder Digital Equipment Corporation ridder@elvira.enet.dec.com Customer Support Center ...decwrl!elvira.enet!ridder Colorado Springs, CO
djh@neuromancer.metaphor.com (Dallas J. Hodgson) (09/21/90)
In article <4934@uqcspe.cs.uq.oz.au> thyssen@batserver.cs.uq.oz.au writes: > > <stuff about timing 'C' code deleted> >I am using Disable() during the timed period to stop other tasks. > >QUESTIONS :- > 1) What is the differance bettween Disable-Enable > and Forbid-Permit exec library calls? > 2) How do you blank the screen? > 3) Is there any other interupts which can be disabled? How? > 4) Under the above can memory still be allocated/deallocated - Important? > 5) Any other comments. > 1) Disable() turns off interrupts. Forbid() disables task switching. 2) Throw up a 1-bitplane black screen. Or, disable video DMA with the OFF_DISPLAY (sp?) macro. 3) Sure, you can disable anything you want. I think you'll understand more if you read: a) The Amiga Hardware Reference Manual b) The Amiga Rom Kernel Manual: Exec c) The Guru's Guide to the Amiga : Interrupts, by Carl Sassenrath 4) Possibly, but I'd warn against it. Could break in the future. Nice sig. +----------------------------------------------------------------------------+ | Dallas J. Hodgson | "This here's the wattle, | | Metaphor Computer Systems | It's the emblem of our land. | | Mountain View, Ca. | You can put it in a bottle, | | USENET : djh@metaphor.com | You can hold it in your hand." | +============================================================================+ | "The views I express are my own, and not necessarily those of my employer" | +----------------------------------------------------------------------------+
daveh@cbmvax.commodore.com (Dave Haynie) (09/21/90)
In article <4934@uqcspe.cs.uq.oz.au> thyssen@batserver.cs.uq.oz.au writes: > I calculated that the `E' line should be runing at .715Mhz (1/10th >of cpu clock rate) and physical measurments (a stop watch over ~20mins) >give a figure of .709 +/- .001 Mhz (3 measurements were made). You're right, actually, on both accounts. If you have a PAL machine, the CPU clock is 7.09MHz, so you get a 0.709MHz E clock. If you have an NTSC machine, you have a 7.159MHz CPU clock, which results in a 0.716MHz E clock. > Timing a fixed loop of code (see below) however produced varing >results which I beleave is due to the interupt handling of the CPU. There are a variety of reasons why any arbitrary chunk of code will take varying amounts of time to execute. The most obvious reason is that Amiga CPUs vary from 7.09MHz 68000s to 50MHz 68030s. Thus, the policy that no CPU-speed dependent code is permitted in Amiga applications starts to make some real-world sense. If you need timing, use a timer, which will be at least reasonably consistent (like, within 1% or so) between all Amigas. >QUESTIONS :- > 1) What is the differance bettween Disable-Enable > and Forbid-Permit exec library calls? Forbid()/Permit() disables multitasking -- it lets you hog the CPU, for whatever reasons. In general, the only valid reason for this is that you have a chunk of code that's examining some shared data structures that aren't locked by a semaphore. Disable()/Enable() turn off all interrupt processing, which as a result also happens to disable multitasking. Some I/O devices will use this, but there's just about no situation in which an application program will use these functions. > 3) Is there any other interupts which can be disabled? How? Disable()/Enable(), by definition, will disable all valid interrupts. Or, to invert this argument, interrupts that don't get disabled by Disable() aren't supported by the AmigaOS. The only such interrupts you could get that are members of this class are expansion-board-generated INT1*, INT4*, INT5*, or INT7* on an A2000. > 4) Under the above can memory still be allocated/deallocated - Important? Memory can be allocated and freed during a Forbid(), and I believe during a Disable() as well, though I have never used that one myself. > Anthony Thyssen - (Dragon Computing!) thyssen@batserver.cs.uq.oz.au So you know your dragons. Think of the OS as you walking down the road, unarmed. Forbid() would be like your average angry Wyvern meeting you on this road. Disable() is more like Smaug or Tiamat coming along to greet you. -- Dave Haynie Commodore-Amiga (Amiga 3000) "The Crew That Never Rests" {uunet|pyramid|rutgers}!cbmvax!daveh PLINK: hazy BIX: hazy Get that coffee outta my face, put a Margarita in its place!
uzun@pnet01.cts.com (Roger Uzun) (09/22/90)
>> Dave haynie writes that an application need never use Disable()/Enable()
Actually this is not true. When I wrote a interrupt handler to strip
off mousevents from the input.device queue, I was "pruning" the linked
list of events streaming in, (using the IND_ADDHANDLER function of
the input.device). I found that if MASSIVE joystick twitching occurred
while pruning this linked list of events, the linked list pruning
could be interrupted in a critical section of removing one of the
port 1 (mouseport) events, and this caused a system crash (only
when doing 6 bitplane anims with all sprites enabled, when I
had 5 bitplane anims with no sprites enabled, I could not get
it to crash). To get around this I had to replace
the the Disable/Enable sequence in the int handler with a forbid/permit
sequence, then no crashes were possible.
-Roger
UUCP: {hplabs!hp-sdd ucsd nosc}!crash!pnet01!uzun
ARPA: crash!pnet01!uzun@nosc.mil
INET: uzun@pnet01.cts.com
thyssen@batserver.cs.uq.oz.au (Anthony Thyssen) (09/22/90)
Thanks to All who replied to my list of questions - I now present The testing code I am using to do a Timing of a empty loop of C code. It compiles under lattice 5.4 without options (DONOT use the -O (optimizer) option as that removes the empty loop and then the start timer assign (poke). Using OFF_DISPLAY in the start timer macro worked to stop the large variance in the timings due to the vidio DMA's (It does however cause the screen to flash but I expected that) Note the timed sections DONOT do any I/O or waits - The only system call made is to allocate/deallocate memory. The code I am timing is data structure routines for my honors project. (Skiplists, Red Black Trees, Binary Trees, Prioity Queues, ....). The Timing still varies but not to a large extent. Eg in the timing of the empty 10000 time loop varied over the range 40096 - 40104 This seems however to depend on the amout of disk activity due to the loading of the command - but I am not positive. I'll have to do some tests from ram to be sure. Here is the code for my timing routines. and a test program. This is released for comment only. Donot put on BBS's or hand out. After the code is finialized I'll release it to Comp.sources.amiga for general distrubution. I'll also release the Data Structures Code sometime but not soon. Anthony Thyssen - (Dragon Computing!) thyssen@batserver.cs.uq.oz.au ------------------------------------------------------------------------------- `One afternoon we were running the Khronal Dungeon, and we opened a door and found ourselves looking out into the living room where we were playing. One of the characters shot the Game Master with a crossbow bolt, and the whole dungeon dissappeared!' -- "Dream Park" ------------------------------------------------------------------------------- ================= CODE STARTS HERE (3 files) =============== :::::::::::::: amiga_timer.c :::::::::::::: /********************************************************************\ ** _________________________________ ** ** A n t h o n y |________ __ __ _________| ** ** | |o_| |o_| | ** ** T h y s s e n __| __ __ |__ ** ** __| __| | | |__ |__ ** ** `` Dragon Computing! '' __| __| | | |__ |__ ** ** |_____| |__| |_____| ** ** ** \********************************************************************/ /* ** This is the timing C subroutines for the amiga computer. ** Note that the start and stop timer is a macro in the header ** file to speed the timing overhead. ** This is an EXAMPLE only - Not a final release */ #include "amiga_timer.h" static UBYTE CIACRAsave, CIACRBsave; void *ciab_resource; void Open_Timer() { /* save info on current timer setup */ ciab_resource = OpenResource(CIABNAME); CIACRAsave = ciab.ciacra; CIACRBsave = ciab.ciacrb; ciab.ciaicr = 0xff &~CIAICRF_TA &~CIAICRF_TB; /* disable timer interupts */ } void TimerPrepare() { /* prepare the timer to be started */ ciab.ciacra=(CIACRAsave&(CIACRAF_TODIN|CIACRAF_SPMODE)) | CIACRBF_IN_PHI2; ciab.ciacrb=(CIACRBsave & CIACRBF_ALARM) | CIACRBF_IN_TA | CIACRBF_START; ciab.ciatalo = ciab.ciatahi = ciab.ciatblo = ciab.ciatbhi = (UBYTE)0xff; /* start at value -1 */ } ULONG TimerRead() { register ULONG ticks; ticks = ciab.ciatbhi; ticks = (ticks<<8) | ciab.ciatblo; ticks = (ticks<<8) | ciab.ciatahi; ticks = (ticks<<8) | ciab.ciatalo; ticks = ~ticks; /* negate and -1 */ return( ticks ); /* time = ticks/clock_rate (.709MHz) */ } void Close_Timer() { ciab.ciacra = CIACRAsave; ciab.ciacrb = CIACRBsave; ciab.ciaicr = (UBYTE)0xff; } :::::::::::::: amiga_timer.h :::::::::::::: /********************************************************************\ ** _________________________________ ** ** A n t h o n y |________ __ __ _________| ** ** | |o_| |o_| | ** ** T h y s s e n __| __ __ |__ ** ** __| __| | | |__ |__ ** ** `` Dragon Computing! '' __| __| | | |__ |__ ** ** |_____| |__| |_____| ** ** ** \********************************************************************/ /* ** Header file to define the code for timeing sections of C code ** on the amiga. It includes macros for starting and stopping and ** restarting the timer. ** This is an EXAMPLE only - Not a final release */ #include <exec/types.h> /* general types */ #include <hardware/cia.h> /* cia stuff */ #include <resources/cia.h> #include <hardware/custom.h> /* stuff for ON/OFF DISPLAY */ #include <hardware/dmabits.h> #include <graphics/gfxmacros.h> #include <proto/exec.h> /* do library calls direct */ extern struct CIA __far ciab; /* structure for CIA-B chip */ extern struct Custom __far custom; /* DMA chip - ON/OFF_DISPLAY */ extern void Open_Timer(); /* initialize timers */ extern ULONG TimerRead(); /* read timers */ extern void Close_Timer(); /* return timers to system */ /* start timing - Multitasking Disabled */ #define TimerStart() \ { TimerPrepare(); OFF_DISPLAY; Disable(); ciab.ciacra |= CIACRAF_START; } /* restart timing - continue the timing from where it left off */ #define TimerRestart() \ { OFF_DISPLAY; Disable(); ciab.ciacra |= CIACRAF_START; } /* Stop timer - restore Multitasking */ #define TimerStop() \ { ciab.ciacra &= ~CIACRAF_START; Enable(); ON_DISPLAY; } /* The following is to prepare the timer as part of TimerStart macro */ extern void TimerPrepare(); /* get timer ready to start */ :::::::::::::: timertest.c :::::::::::::: /*********************************************************************\ ** ________________________________ ** ** A n t h o n y |________ __ __ ________| ** ** | |o_| |o_| | ** ** T h y s s e n __| __ __ |__ ** ** __| __| | | |__ |__ ** ** `` Dragon Computing ! '' __| __| | | |__ |__ ** ** |_____| |__| |_____| ** ** ** \*********************************************************************/ /* ** Test the timer routines on the amiga ** This is an EXAMPLE only - Not a final release */ #include <stdio.h> #include "amiga_timer.h" char input[100]; main() { register int i; printf("Timing...\n"); fflush(stdout); Open_Timer(); /* initialize the timer */ TimerStart(); /* start timing */ for(i=0; i<10000; i++); TimerStop(); /* stop timing */ printf("Stopped -> %lu \n", TimerRead() ); /* read timer */ fflush(stdout); Close_Timer(); /* return timer */ return(0); } /*================ END OF CODE ================*/
barnettj@pookie.crd.ge.com (Janet A Barnett) (09/23/90)
In article <14567@cbmvax.commodore.com> daveh@cbmvax.commodore.com (Dave Haynie) writes: > Disable()/Enable() turn off all interrupt processing, >which as a result also happens to disable multitasking. > >Disable()/Enable(), by definition, will disable all valid interrupts. Or, to >invert this argument, interrupts that don't get disabled by Disable() aren't >supported by the AmigaOS. The only such interrupts you could get that are >members of this class are expansion-board-generated INT1*, INT4*, INT5*, or >INT7* on an A2000. > Here is my understanding of Disable(): Rather than set the CPU's interrupt mask to 0x7, the custom chip register INTENA is written such that no interrupt requests are allowed. Here is my question: Does this actually prevent interrupting devices (such as the video circuitry at the start of vertical blanking) from causing a transition of the CPU's IPL lines? To put this question another way, is Disable() a logical function wherein interrupts of the CPU are not physically disabled but rather simply masked out by RTEing immediately or does the interrupt control on the custom chip actually block IPL transitions to the CPU? I wanna know.
p554mve@mpirbn.mpifr-bonn.mpg.de (Michael van Elst) (09/24/90)
In article <4969@uqcspe.cs.uq.oz.au> thyssen@batserver.cs.uq.oz.au writes: >void >Open_Timer() >{ /* save info on current timer setup */ > ciab_resource = OpenResource(CIABNAME); > CIACRAsave = ciab.ciacra; > CIACRBsave = ciab.ciacrb; > ciab.ciaicr = 0xff &~CIAICRF_TA &~CIAICRF_TB; /* disable timer interupts */ >} As far as I know you have to allocate the interrupt associated with the timer to use the timer registers. Since opening the cia resource will not grant exclusive access to the cia your code might run into problems when more than one application tries to use the timer. The interrupt can be allocated with a call to AddICRVector() (sp ?).. Regards, -- Michael van Elst UUCP: universe!local-cluster!milky-way!sol!earth!uunet!unido!mpirbn!p554mve Internet: p554mve@mpirbn.mpifr-bonn.mpg.de "A potential Snark may lurk in every tree."