Path: utzoo!attcan!uunet!husc6!mailrus!cornell!uw-beaver!teknowledge-vaxc!sri-unix!quintus!ok From: ok@quintus.uucp (Richard A. O'Keefe) Newsgroups: comp.lang.fortran Subject: Re: Exception handling (was Fortran vs Message-ID: <426@quintus.UUCP> Date: 19 Sep 88 01:14:03 GMT References: <401@quintus.UUCP> <44400022@hcx2> Sender: news@quintus.UUCP Reply-To: ok@quintus.UUCP (Richard A. O'Keefe) Organization: Quintus Computer Systems, Inc. Lines: 84 In article <44400022@hcx2> bill@hcx2.SSD.HARRIS.COM writes: >For the record, I don't intend to respond further unless >some other interesting point(s) is raised. I merely want to answer >some questions and misconceptions (I think). {I wrote:} >> HANDLE ('exception name, ..., exception name') IN >> statements to be protected >> CANNOT HANDLE >> statements to execute if any of the exceptions cannot be trapped >> HANDLER >> statements to execute if any of the exceptions occurs >> END HANDLER >> The precise location of an exception does not matter, but any pending >> exceptions must be signalled before control leaves the protected code. {He replies} >Oh, but it does. Without a precise location, how can the generated >code (or the runtime, or whoever) figure out whether the exception >occurred _inside_ the HANDLE section or _outside_. This single fact >causes us headaches in Ada, because it is VERY expensive on our >hardware to determine exactly where the exception occurred. (I believe >this is almost universally true in cases where floating-point >operations are done by an independent co-processor.) I didn't spell it out, but my idea was that you would not be allowed to jump into a HANDLE block, and that jumping out of one or exiting it any other way (such as RETURN) would dynamically end it just like falling off the end. "Precise interrupts" are where the hardware goes to a lot of trouble to *pretend* that your code was executing on a strictly sequential machine, so that any changes which may have taken place since the exception occurred (PC advancing, &c) which would not have taken place in a strictly sequential implementation are backed out. For example, if we have X = X*Y I = I+1 in a program, on many machines the integer operation will be done while the floating-point one is still unfinished. By the time an overflow is noticed, the PC be anywhere (due to jumps). My scheme does not require precise registers, thus defined. As for the location of the exception, all you need to know is whether it occurs between two *EVENTS*. Consider the following entirely imaginary code: save_mask := exception_mask # H/W register save_addr := exception_addr # H/W register CALL EH$NEW_MASK('....', save_mask, new_mask, ierror) IF (ierror .ne. 0) GO TO "CANNOT HANDLE" exception_addr := "HANDLER" exception_mask := new_mask statements to be protected *wait*for*pending*exceptions* exception_mask := save_mask exception_addr := save_addr The information we need is that the instruction which signalled the exception started *after* the "exception_mask := new_mask" instruction and *before* the *wait*for*pending*exceptions* instruction completed. The wait-for-pending-exceptions code has the job of waiting until any functional unit which *might* cause an exception has had all the time it needs to do so. Note that in this scheme the handler receives *no* information about where the PC was or which instruction signalled the exception, nor about the state of the registers when that instruction commenced. In fact, should several instructions be started each of which can signal an exception (not a hard thing to do, when there is a deep enough pipeline) it is *not* required that the first of them be signalled, any of them may be. Note that this scheme doesn't assume that the protected code forms a contiguous region: if a compiler notices that some of the code in the protected region looks like some code elsewhere in the subprogram, it can generate an internal subroutine. All that matters is the TIME of the exception: after this event and before that? Now, I know how to do this on the major 32-bit micros. Generally, any integer or addressing exceptions are synchronous anyway, so the only problem with those machines is floating-point exceptions, and there are things you can do which have the effect of waiting until the floating- point unit has completed all pending operationgs. That *is* a bottle- neck, but it only happens when you ask for it, not after every operation. What I >don't< know is which computers can't do something like so, or why.