borcelf@jacobs.cs.orst.edu (Fernando Borcel) (01/19/89)
I Started messing around with VBL tasks just today, following my IM II direc- tions. Now, I wore this rather silly task, just to see what it does, and it worked (oh, surprise!), but for just a few times, bombing bad afterwards. Here's what I wrote: procedure myVbl; var VBLTask : QElemPtr; begin SetUpA5; FlashMenuBar(0); {my "TASK"} new(VBLTask); VBLTask^ := myVBLTask^; if vInstall(VBLTask) <> NoErr then {Enqueue for Next VBL task} exitToShell; RestoreA5; end; {later in the code, something I call only ONCE} ... ... new(MyVBLTask); with MyVBLTask^.VBLQElem do begin qtype := ord(vtype); vbladdr := @myVBL; vblCount := 5; vblPhase := 0; end; new(VBLTask); {I decided to use a copy of the task} VBLTask^ := MyVBLTask^; if vInstall(VBLTask) <> NoErr then exitToShell; --- I tried many other combinations, but none of them worked any better... Thanks. ___ __ |{tektronix,hp-pcd}!orstcs! / _ _ _ _ _ _/ _ /_/ _ _ _ _ / | jacobs.cs.orst.edu!borcelf /- /_// // / _// // // / / )/ // // /_// | _/ /_ / / //_// //_//_/ /__//_// /_ /_ /_ |borcelf@jacobs.cs.orst.edu
lsr@Apple.COM (Larry Rosenstein) (01/20/89)
In article <8343@orstcs.CS.ORST.EDU> borcelf@jacobs.cs.orst.edu (Fernando Borcel) writes: >Here's what I wrote: > > procedure myVbl; > var > VBLTask : QElemPtr; > begin > SetUpA5; > > FlashMenuBar(0); {my "TASK"} > > new(VBLTask); > VBLTask^ := myVBLTask^; > if vInstall(VBLTask) <> NoErr then {Enqueue for Next VBL task} > exitToShell; > > RestoreA5; > end; There are a couple of problems here: (1) A VBL task runs at interrupt level, and can't call any routins that allocate memory. FlashMenuBar does allocate memory (it's listed in the chart in Inside Mac). I suspect that New could also. (2) The technique you use to set up the task to be executed again is not right. You don't need to creata new task block. Instead you shouldsimply reset the vbl counter in the existing task block. A pointer to the task block is passed in A0 when your VBL code is called. There are various ways to get this register in Pascal, depending on the development system. Your initial installation code looks OK to me. -- Larry Rosenstein, Object Specialist Apple Computer, Inc. 20525 Mariani Ave, MS 46-B Cupertino, CA 95014 AppleLink:Rosenstein1 domain:lsr@Apple.COM UUCP:{sun,voder,nsc,decwrl}!apple!lsr
oster@dewey.soe.berkeley.edu (David Phillip Oster) (01/20/89)
n addition to all the previous problems, most versions of SetUpA5() look at a global variable, CurrentA5, which is not guaranteed to be correct under multifinder.
lsr@Apple.COM (Larry Rosenstein) (01/21/89)
In article <27628@ucbvax.BERKELEY.EDU> oster@dewey.soe.berkeley.edu.UUCP (David Phillip Oster) writes: >n addition to all the previous problems, most versions of SetUpA5() look >at a global variable, CurrentA5, which is not guaranteed to be correct >under multifinder. Tech Note 208 also mentions a problem in that SetupA5 saves the current A5 on the stack, which screws up some optimizing compilers (eg, MPW C 3.0). It suggests that you save the current A5 value in a local place and restore it at the end. -- Larry Rosenstein, Object Specialist Apple Computer, Inc. 20525 Mariani Ave, MS 46-B Cupertino, CA 95014 AppleLink:Rosenstein1 domain:lsr@Apple.COM UUCP:{sun,voder,nsc,decwrl}!apple!lsr
borcelf@jacobs.CS.ORST.EDU (Fernando Borcel) (01/21/89)
In article <445@internal.Apple.COM> lsr@Apple.COM (Larry Rosenstein) writes: > >(2) The technique you use to set up the task to be executed again is not >right. You don't need to creata new task block. Instead you shouldsimply >reset the vbl counter in the existing task block. A pointer to the task >block is passed in A0 when your VBL code is called. There are various ways >to get this register in Pascal, depending on the development system. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ OK, I'm using LSPascal. How do I get A0, and what is the TYPE of what it's pointed by it? Fernando ___ __ |{tektronix,hp-pcd}!orstcs! / _ _ _ _ _ _/ _ /_/ _ _ _ _ / | jacobs.cs.orst.edu!borcelf /- /_// // / _// // // / / )/ // // /_// | _/ /_ / / //_// //_//_/ /__//_// /_ /_ /_ |borcelf@jacobs.cs.orst.edu
tim@hoptoad.uucp (Tim Maroney) (01/21/89)
In article <27628@ucbvax.BERKELEY.EDU> oster@dewey.soe.berkeley.edu.UUCP (David Phillip Oster) writes: >In addition to all the previous problems, most versions of SetUpA5() look >at a global variable, CurrentA5, which is not guaranteed to be correct >under multifinder. In article <451@internal.Apple.COM> lsr@Apple.COM (Larry Rosenstein) writes: >Tech Note 208 also mentions a problem in that SetupA5 saves the current A5 >on the stack, which screws up some optimizing compilers (eg, MPW C 3.0). >It suggests that you save the current A5 value in a local place and restore >it at the end. However, this doesn't address the fact that you may need a different A5 from the one in CurrentA5, which was David's point. This may happen in interrupt driven code that is not switched by MultiFinder. VBL tasks only run when their application has the processor, but not so things like socket listeners or custom interrupt handlers. I still don't know any way around this except for stashing a copy of your A5 in code-relative space, which is explicitly forbidden (with good reason) by Tech Note #2. I'm not even sure that Apple acknowledges that this is a problem; when I pointed it out to David Goldsmith a couple of years back, he just started shouting angrily.... -- Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim "The above opinions and suggestions have absolutely nothing to do with the little, fat man putting crisp, $100 bills in my pocket." -- Alan Vymetalik
paul@taniwha.UUCP (Paul Campbell) (01/23/89)
In article <6347@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: >interrupt driven code that is not switched by MultiFinder. VBL tasks >only run when their application has the processor, but not so things >like socket listeners or custom interrupt handlers. I still don't know >any way around this except for stashing a copy of your A5 in >code-relative space, which is explicitly forbidden (with good reason) >by Tech Note #2. I'm not even sure that Apple acknowledges that this Yes! Yes! I'm forever running into this problem, when you want to find a 'global' object in the Mac (ie the context of an INIT to communicate with it, or some completion routines and their apps) often it's a real pain. The real problem is one of 'naming' how can I have two items agree on a name to find a common item if they don't have common context, often the problem can be solved by extending the parameter block involved (for example VBL's or completion routines). I once had to go to the extent of writing a driver (don't ask!) so that I had a common 'name' that could be accessed by apps, a cdev and another driver! In many ways this may be a better way to do it in the long run (ie with whatever they end up doing with the MMU etc) because it uses a trap to get from local context to the global context, and the trap handling code (the driver's Control routine) can do all the inter-context manipulation (but then this is starting to sound a lot like how people hack around this stuff in Unix, which is after all my bias ....). On the other hand somethimes Apple do do it right! The 'A1Param' in the slot SIntInstall is a good example, one can carry as much baggage as one likes there, simply by using it as a pointer to a locked data structure. Paul -- Paul Campbell ..!{unisoft|mtxinu}!taniwha!paul (415)420-8179 Taniwha Systems Design, Oakland CA "Read my lips .... no GNU taxes" - as if they could tax free software
lsr@Apple.COM (Larry Rosenstein) (01/24/89)
In article <6347@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: > >However, this doesn't address the fact that you may need a different A5 >from the one in CurrentA5, which was David's point. This may happen in Definitely true. In fact, I wouldn't recommend using CurrentA5 any more. The times when you need to setup A5 are in interrupt routines, and generally, you can't count on CurrentA5 under MultiFinder. (Although I think there are some cases where it is OK to use CurrentA5, it is best not to take chances.) >like socket listeners or custom interrupt handlers. I still don't know >any way around this except for stashing a copy of your A5 in >code-relative space, which is explicitly forbidden (with good reason) >by Tech Note #2. I'm not even sure that Apple acknowledges that this >is a problem This is clearly acknowledged in Tech Note 180. Some routines that run at interrupt level are given pointers to parameter blocks, etc. where the desired A5 could be stashed. (VBL tasks are one of these.) Some routines don't have any place to store A5, so the Tech Note recommends storing the desired A5 into your code area. This applies to Time Manager tasks and interrupt service routines. -- Larry Rosenstein, Object Specialist Apple Computer, Inc. 20525 Mariani Ave, MS 46-B Cupertino, CA 95014 AppleLink:Rosenstein1 domain:lsr@Apple.COM UUCP:{sun,voder,nsc,decwrl}!apple!lsr
lsr@Apple.COM (Larry Rosenstein) (01/24/89)
In article <8383@orstcs.CS.ORST.EDU> borcelf@jacobs.CS.ORST.EDU.UUCP (Fernando Borcel) writes: > >OK, I'm using LSPascal. How do I get A0, and what is the TYPE of what it's >pointed by it? Here is a simple LSP 2.0 program that shows how to use VBLs. It sets up a VBL task that runs every 2 seconds. That task increments a global variable. The main program loops checking the variable and printing it when it changes. When you click the mouse the program stops. I don't know if the GetA0 technique is absolutely safe. It depends on the compiler not using A0 for anything before the start of the vbl task. It seemed to work in this case. A safer technique is to write a short assembler routine that gets A0 and passes it as a parameter to your Pascal routine. But this requires some other development system that can generate assembler code. (Eg, MPW or LSC.) *********** program VBLTest; var myRecord: record mya5: LONGINT; vblBlock: VBLTask; end; state: INTEGER; { INLINES to manipulate A5 } function GetA5: LONGINT; inline $2E8D; {MOVE.L A5,(A7)} function LoadA5 (newA5: LONGINT): LONGINT; inline $2F4D, $0004, $2A5F; { INLINE to get A0 in the task } function GetA0: LONGINT; inline $2e88; { Can't do debugging at interrupt level } { don't want to use $A+ because it uses CurrentA5 } {$D-} procedure VBL; var err: OSErr; curA5: LONGINT; p: ^LONGINT; begin { Get the pointer to myA5 } p := Pointer(GetA0 - 4); { Set A5 } curA5 := LoadA5(p^); { Here's where you do something. } state := state + 1; { Reset the VBL counter } myRecord.vblBlock.vblCount := 120; { Restore A5 } curA5 := LoadA5(curA5); end; {$D+} var err: OSErr; old: integer; ev: EventRecord; begin { Initialize A5 } myRecord.mya5 := GetA5; state := 0; old := 0; showtext; with myRecord.vblBlock do begin qType := Ord(vType); vblAddr := @VBL; vblCount := 120; vblPhase := 0; end; err := VInstall(@myRecord.vblBlock); writeln('err=', err); while true do begin if old <> state then begin old := state; writeln(old); end; if GetNextEvent(-1, ev) then begin if ev.what = mouseDown then leave; end; end; err := VRemove(@myRecord.vblBlock); writeln('err=', err); end.-- Larry Rosenstein, Object Specialist Apple Computer, Inc. 20525 Mariani Ave, MS 46-B Cupertino, CA 95014 AppleLink:Rosenstein1 domain:lsr@Apple.COM UUCP:{sun,voder,nsc,decwrl}!apple!lsr