Path: utzoo!attcan!uunet!super!udel!rochester!rutgers!ucsd!ucbvax!CORY.BERKELEY.EDU!dillon From: dillon@CORY.BERKELEY.EDU (Matt Dillon) Newsgroups: comp.sys.amiga Subject: Re: Need info on exceptions Message-ID: <8808242346.AA26596@cory.Berkeley.EDU> Date: 24 Aug 88 23:46:33 GMT Sender: daemon@ucbvax.BERKELEY.EDU Lines: 91 Time to go into a brief description of the three types of interrupts that exist on the Amiga: (1) Task Exceptions (via SetExcept() and standard signals). This is a task-level interrupt and only interrupts the task it is attached to. Other tasks still run... the interrupt only interrupts the one task. That is, any number of tasks may be handling exceptions all simultaniously. This is analogous to UNIX signals with one major exception.... system calls can get interrupted in the middle (i.e. library calls). Although all run-time libraries are reentrant between tasks, this is not always so within a given task. For instance, you cannot interrupt a DOS Write() with an exception and then do a Write() from within the exception!! Another for instance: you CAN call AllocMem(). So you have to be very careful as to when to allow an exception and when not to. Forbid() effectively disables exceptions (but also task switching). Also, there is a bug in the exception handler in that if an exception occured during a Forbid() it does NOT execute when you Permit()... i.e. you also have to do a SetExcept(0,0) to force EXEC to check for active exceptions after you Permit(). The 'simple' description of an exception is this: First, a task gets signalled and if the exception bit for that signal bit is set, the EXCEPTION-ENABLE BIT AND THE SIGNAL BIT IS CLEARED and the task then enters its exception handler. D0 contains a mask of the exception that occured (more than one bit may be set if more than one exception occured at once). The exception handler thus must be reentrant for different exception bits. After the handler runs, it must return a bitmask in D0 of those exceptions that occured. EXEC automatically ENABLES the exceptions specified by the bitmask. However, it doesn't check to see if they re-occured at this time... Thus, there is a window of vulnerability here. Usually, I reenable the exceptions manually with a SetExcept() call from the handler and return 0 in D0. Unlike other types of interrupts, EXEC saves and restores ALL of our registers (except the stack pointer) for us. But, you cannot make assumptions as to the contents of the registers (except for D0 and A1(=tc_ExceptData). Specifically, there is no guarentee A4 will contain the small-code-model data segment base so you must reload it if you intend to use that model inside the handler. (2) Software Interrupts. Software interrupts are HIGHER priority than tasks but LOWER priority than interrupts. Essentially, these are pseudo hardware interrupts but without the timing restrictions in real interrupts.... you can do things that you would not want to do in normal interrupts because they would otherwise take too long. BUT! A software interrupt is not a task, and you still may not use memory allocation/free functions within one (same restrictions as for hardware interrupts apply with the exception that you can take a longer time in the soft int). For example, instead of calling ReplyMsg() from an HARD interrupt handler you might want to Cause() a softint instead. This allows the HARD int to end (and other HARD ints to occur). A software interrupt uses the same structure as a hardware interrupt. (3) Hardware Interrupts. Real honest to goodness hardware interrupts. Implemented by SetIntVector() and AddIntServer() and the like. These are real hardware interrupts and the service routine should take as little time as possible in them... I mean as *little* time as possible. Make your code tight. Calling something like ReplyMsg() or PutMsg(), while it works, usually takes too much time for an interrupt handler to spare. Cause() a softint for things that take too much time so other interrupts can go. I don't know how much time Signal() takes. There are two flavors. (1) Direct hardware interrupts (SetIntVector()), and (2) Chained hardware interrupts. In many cases there are also resources (misc.resource, for instance) to arbitrate usage of some of the interrupt vectors. -Matt :In article ... iphwk%MTSUNIX1.BITNET@cunyvm.cuny.edu (Bill Kinnersley) writes: :> Unfortunately it can't. "To avoid serious problems, the interrupt :> routine must not use any of the memory allocation or deallocation :> functions"--RKM. That's apparently because critical system code :> is surrounded by Forbid(), but not Disable(). : :> That doesn't seem to leave much that interrupts can do. Once again, :> we're stuck with polling (and this on a multitasking OS). : :You shouldn't be doing much in an interrupt, on any system. These are real :hardware-type interrupts, you know. For software interrupts, you can :probably get away with doing memory hacking, since you know that the task :which posted them wasn't doing anything dangerous when it was posted. But, :really, you don't need to do anything like that, anyway... because you can :signal a sleeping task to do the actual grunt-work.