To: perot@pallas.amp.uni-hannover.de
Subject: Re: [3] System stack problem ...                                                


On Thu, 9 Jan 1997 10:34:06  Peter Rottengatter <perot wrote: 
>
>On Wed, 8 Jan 1997, Ronald Andersson wrote:
>>
>> Oh, sorry then.  It's just that in the early threader code you showed me,
>> there was a 'house_cleaning' vector which was regularly invoked regardless
>> of the STiK activity.  If that had still been the case,  it would cause
>> problems of the type you described for the reasons I described.
>
>The cleaning is still there, but along with the work code it gets 
>desactivated. The only difference between the `work' and the `cleaning' 
>is that the latter is called once a second, whereas the call frequency
>of the former is adjustable, both only if STiK is set active.

Yes, I see.  Anyway, you told me in another mail that you'd found the error,
so the matter is no longer critical.


>> Ok.  I suppose the threader has changed too much from its original form
>> for my conclusions based on that code to be valid.  If you don't mind,
>> it would be very interesting to see the new source, in which case I may
>> also be able to find some more relevant explanation of the problems.
>
>Yes, I know I wanted to send it the other day, but I didn't get around to 
>actually doing it. Here I try again ;-)

Ok, I've saved it with my other reference sources now.
I've also made some suggestions for optimizations below.


>   ; This is the end of the install routine :
>
>            move.l  sp, sys_stack                ;" Pointer to our stack
>            rts
>
>;-------------------------------------------------------------------------------------)
>
>            .dc.l   'XBRA'                       ;" XBRA structure for
>            .dc.l   'STiK'                       ;" STiK ...
>old_200_Hz: .ds.l   1                            ;" Old 200 Hz timer vector
>
>my_200_Hz:
;
;The code segment bracketed by the 'extra_d0' save and restore operations
;is quite correct as it stands, but wastes time by always doing things 
;as if the special case was likely, which only happens once per 24 hours.
;I'd replace this as follows:
;
             addq.l   #5,stik_clock               ;" Count stack internal clock
             cmpi.l   #86400000,stik_clock        ;" Test One day in milliseconds
             bpl.s    clk_ok
             subi.l   #86400000,stik_clock        ;" Reduce  One day in milliseconds
clk_ok:
;as you can see, this practically halves normal execution time of the segment,
;and eliminates the need for having the extra_d0 variable.  Thus, even when
;the special case occurs, the new code will still be faster than the old.

             subq.w  #1, traffic                  ;" Count down for IP traffic
;subq is faster than sub

>            bne     early_a                      ;" Is it time for it ?
>            move.w  fraction, traffic            ;" Yes : Reset counter
>            bset    #0, tm_exec                  ;" Signal : Do work

early_a:     subq.w  #1, cleaning                 ;" Count down for Cleaning up
;subq is faster than sub

>            bne     early_b                      ;" Is it time for it ?
>            move.w  #200, cleaning               ;" Yes : Reset counter
>            bset    #1, tm_exec                  ;" Signal : Do work
>early_b:

;In the segment below there is a danger due to the use of TST instead of TAS.
;If some other system routine somehow handles the interrupt response so that a
;new interrupt occurs before we've reached the start of 'keep_koing', then
;STiK will lock up the system by endlessly pushing more frames on stack.
;The tests of tm_sema, active, and tm_exec must be switched around to use TAS.
;
             tst.w   tm_exec                      ;" Something to do ?
             beq     lazy                         ;" No : Do nothing
             tst.w   active                       ;" Are we switched active ?
             beq     lazy                         ;" No : Do nothing
             tas     tm_sema                      ;" STiK work still on ?
             bpl     here_we_go                   ;" Yes : Do some work now
;
;The above also saves a little CPU time by eliminating the setting of tm_sema
;in the 'keep_going' routine.

>lazy:       move.l  old_200_Hz, -(sp)            ;" Jump to system handler
>            rts
>
>active:     .dc.w   0                            ;" Flag for active
>traffic:    .dc.w   1                            ;" Counter for IP traffic
>fraction:   .dc.w   10                           ;" Divide by this
>cleaning:   .dc.w   1                            ;" Counter for Cleaning up
>tm_sema:    .dc.w   0                            ;" Execution semaphore
>tm_exec:    .dc.w   0                            ;" Execution flags
>stik_clock: .dc.l   0                            ;" Internal clock
>sys_stack:  .dc.l   0                            ;" Our stack pointer
>
>here_we_go:
>            tst.w   longframe                    ;" Do we have a 68000 CPU ?
>            beq     cpu_fixed                    ;" Yes, no extra stack word
>            clr.w   -(sp)                        ;" Extra stack word for 680X0
>cpu_fixed:  pea     keep_going                   ;" Install exception stack frame
>            move.w  sr, -(sp)                    ;" For return to STiK work
>            move.l  old_200_Hz, -(sp)            ;" Jump to system handler
>            rts
>
>keep_going:
;;;;            move.w  #-1, tm_sema                 ;" Signaling STiK work
;this instruction is not needed with TAS used above

>            movem.l d0-d7/a0-a7, cpu_state       ;" Save CPU register
>            move.w  (sp), d0                     ;" Fetch status from stack
>            bset    #13, d0                      ;" Stay in Super mode
>            move.w  d0, sr                       ;" Lower interupt level
>            move.l  sys_stack, sp                ;" Install our system stack
>            btst    #0, tm_exec                  ;" IP traffic to do ?
>            beq     dont_a                       ;" No : Skip it
>            lea     poll_ports, a0               ;" Address of IP traffic routine
>            jsr     (a0)                         ;" Execute it !
>            bclr    #0, tm_exec                  ;" Signal done it
>dont_a:     btst    #1, tm_exec                  ;" Clean up to do ?
>            beq     dont_b                       ;" No : Skip it
>            lea     clean_up, a0                 ;" Address of clean up routine
>            jsr     (a0)                         ;" Execute it !
>            bclr    #1, tm_exec                  ;" Signal done it
>dont_b:     movem.l cpu_state, d0-d7/a0-a7       ;" Restore CPU register
>            clr.w   tm_sema                      ;" STiK work finished
>            rte
>

;;;;extra_do:   .ds.l   1                            ;" Just one for d0
;this variable is not needed with the fix in the first segment of this source

>cpu_state:  .ds.l   16                           ;" Space for CPU registers
>
>;-------------------------------------------------------------------------------------)
>
>
>I got a mail from Andreas Kromke. He states MagiC has a Stack of 5 ... 6 
>kB, MagiCMac has more. TOS has 1 kB. This means MagiC does not need any 
>extra system stack, 5 kB is enough by far. 1 kB on TOS might be tight, 
>however, so maybe I reset the stack only for TOS.

I don't agree.  That stack may already be used extensively when your routine
is entered.  Assume for example that some complex AES/VDI function is running,
and has called a GEMDOS trap, which has called a BIOS trap, all of which may
have been extended by patch TSRs.  Then a low level interrupt occurs, and is
in turn interrupted by timer C, leading to your routine.

This is not at all exaggerated either, this sort of thing happens very often,
because the complex functions use more time, which makes it more likely that
one of them is active when an interrupt occurs.

There really is no telling how much stack will then remain for your use, but
if you always use your internal stack you _do_ know what you have, and if that
turns out to be insufficient for MagiC we will find it out quickly and can
easily increase the size to be used.

I believe that 1KB reserved _entirely_ for interrupts is sufficient.

-------------------------------------------------------------------------
Regards:  Ronald Andersson                     mailto:dlanor@oden.se
                                               http://www.oden.se/~dlanor
-------------------------------------------------------------------------
