Path: utzoo!dptcdc!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!ucbvax!amdcad!rpw3 From: rpw3@amdcad.AMD.COM (Rob Warnock) Newsgroups: comp.arch Subject: Re: Complex Instructions Message-ID: <25284@amdcad.AMD.COM> Date: 19 Apr 89 04:16:51 GMT References: <57252@yale-celray.yale.UUCP> <4101@tolerant.UUCP> <25280@amdcad.AMD.COM> Reply-To: rpw3@amdcad.UUCP (Rob Warnock) Organization: [Consultant] San Mateo, CA Lines: 79 [Although the implementation discussed below is Am29000-specific, the general notion is probably feasible on the other current RISCs, and maybe even CISCs.] In article <25280@amdcad.AMD.COM> tim@amd.com (Tim Olson) writes: +--------------- | On the Am29000, the on-chip timer is disabled separately from the | external interrupts. Thus, an operating system could supply a | user-invokable disable() routine which masked interrupts and set the timer | to interrupt in a small number of cycles. The user can then perform a | series of operations, then call an enable() routine (resetting the timer | and the interrupt mask). If enable() were not called in time, the timer | would catch it and force the interrupt mask off. +--------------- [Funny you should mention... Our internal 29k/4.3bsd Unix port group was talking about this just yesterday. ;-} ] Actually, Tim, you can do a lot better than that, by remembering to optimize for the *expected* case, which is: There will be no attempt to break the lock. The main thing you are trying to protect against is rescheduling and "signals" due to external events such as typing <^C>. For that, you don't need a separate enable() call. Instead, you can use a temp_disable() call [which can be a *very* lightweight sys call, on the 29k] which needs to do just two things: 1. Check a u_page flag for a pending event that may have been held off by a previous temporary_disable() call. [This prevents the user from keeping the scheduler locked out.] 2. Store the current value of the CPU timer in the u_page. In 29000 assembler, this is: ; User does assert instruction "asne V_UIOFF,gr1,gr1", which traps ; here through vector V_UIOFF, since gr1 *does* equal gr1. user_ioff: add it0,upage,BRK_UIOFF_OFS ; find u.u_break_uioff load 0, 0, it0, it0 ; see if we need a resched mfsr it1, TCV ; get current timer value add it1, it1, 1 ; make sure non-zero add it2,upage,UIOFF_OFS ; find u.u_uioff jmpt it0, user_ioff_broken ; take traps first... store 0, 0, it1, it2 ; save timer+1 in u.u_uioff iret Assuming hits in the BTC [user doing this a lot], this is 9+8+2+2 = 21 cycles or just under one microsecond on a 25 MHz machine [with 2-first/1-burst memory]. Now, when you get an external signal like <^C>, you do all the normal Unix signal stuff, but "issig()" will check the u.u_uioff and, if it's non-zero and not more than "delta" more than the current timer value, will just set u.u_break_uioff and *not* ask for the signal. Likewise, "sched()" will delay rescheduling a uioff'd process. The timer interrupt code checks the current process to see if the u.u_uioff word is "old" [mod 2^32], and if so, clears it (and causes a resched if needed). I'm sure there are more places to touch that that, but you get the idea. That works for user-mode code, but for the kernel you *would* need hardware. What we used back at Dig. Comm. Assoc. (in a Z-80 comm system) was a counter chip, wired so it counted down to zero and hung there until reloaded. Whenever it was *not* zero, interrupts and DMA requests were held of (simple gate). The trick is that the store which loads the counter *enables* interrupts and DMA [at least long enough for them to "take"], thus preventing infinite lockouts. Hmmm... You could do the same thing for user mode, if your MMU allows mapping user pages into I/O space. [The 29k does.] Dedicate a whole I/O page to the "temp_ioff" counter, put it in every process's address space, including the kernel's. Cost: A 25-cent external chip. [I assume there are enough misc. I/O decodes lying around in a PAL somewhere.] Rob Warnock Systems Architecture Consultant UUCP: {amdcad,fortune,sun}!redwood!rpw3 DDD: (415)572-2607 USPS: 627 26th Ave, San Mateo, CA 94403