dillon@CORY.BERKELEY.EDU (Matt Dillon) (04/14/88)
I am just finishing up a neat little module that will give a task the ability to have prioritized vectored signals using task exceptions. I'll post it to comp.sys.amiga.tech in a day or two. Essentially, the entire interface works through two calls: oldpri = SetQPri(newpri) oldvec = SetQVector(signo, handler, pri) I call these Q interrupts to differentiate them from other types of interrupts. The Q interrupt priority of the task is set with SetQPri() and has a range -128 to 127 (-128 is the default). You may specify one or more of the task's 32 signal bits to be a Q interrupt at some specific priority. Then, when that signal comes in, its handler will be run as soon as the task's Q priority drops BELOW the priority of the handler (immediately if possible). The sequence works as follows: When the Q priority drops below the highest priority pending Q interrupt, set the Q priority to that of the pending Q interrupt and call the handler, then restore the Q priority to what it was before. The handler is run in the context of the task, in user mode, without turning off anything else in the system. Since this scheme is essentially the same as the 68000's hardware interrupt scheme, you can, for instance, put all your Q interrupts at the same priority to guarentee they will not interrupt each other. OR, if you want one signal to have priority over another, you simply give it a higher priority when you SetQVector() it. You can 'forbid' some Q interrupts by setting the task's priority higher than one or more Q Vectors with SetQPri(). For instance, if you want to use DOS calls from both your main loop and a Q interrupt, you must do something like: handler() { puts("y"); } main() { SetQVector(SIGBREAKB_CTRL_F, handler, 23); while (notdone) { SetQPri(127) puts("x"); SetQPri(-128); } SetQVector(SIGBREAKB_CTRL_F, NULL, 0); } in your main loop to avoid confusing stdio or DOS. The same goes for graphics calls and critical system calls. So far, with no optimization, a standard Amiga can process 1000 Q interrupts / sec. This is quite a bit more overhead than software interrupts and task switches, but has several advantages: (1) By applying 'handlers' to signals, one has a distinctly different way of handling events than the standard "main loop wait" method. (2) Many applications want to be able to handle events while doing complex calculations. For instance, a 'game of life' program may want to handle menu events ("STOP") while calculating a screen without having to continuously check to see if an intuition message has come in. Instead, a Q interrupt could simply set a flag or modify some count variable that would cause the calculation to abort ("somebody wants me to stop" instead of "does somebody want me to stop?"). In this case, there is zero overhead until the user actually selects the menu item. In, say, a terminal program, if you want to 'send' a file and handle the full-duplex echo smoothly, you can create a Q interrupt handler to handle all aspects of the serial receive. (EXEC IO devices are independant of calls to other libraries and to most EXEC calls and can be done asynchronously without having to fool with SetQPri()). (3) All of this is done in the context of a single task without resorting to using multiple tasks (much more of a hassle), almost as if the Q interrupt handler were called as a subroutine of the main program! look for it soon! -Matt