page 88,132
Comment ~
             GIVEBACK (Version 3.1) Description and Source Code

        Kurt Riegel, 3019 North Oakland Street, Arlington, VA 22207
        ASTRO Bulletin Board, data 202-524-1837, voice 703-522-5427


(The description below is cast in terms of using GIVEBACK under DESQview or
DoubleDos, in conjunction with the bulletin board program RBBS-PC, but the same
procedure is usable from ANY calling program, for example using CALL GIVEBACK
in compiled BASIC.)

This small assembly language routine follows information provided in the
DESQview (DV) 2.01 manual, and in the DoubleDos (DD) 4.0 manual.

The idea is simple, but powerful.  DESQview kindly terminates processing in a
window if the computer pauses for a standard dos keyboard function, saving the
rest of the time slice for jobs in other windows.  But in other kinds of loops,
for example the loop in RBBS bulletin board which watches for the telephone to
ring, lots of time is wasted, uselessly looking for a phone ring every few
milliseconds.  Once a second would be quite enough!

By calling this routine from the end of a wasteful loop in a program, DESQview
will be forced to "give back" the rest of the time in that time slice, that is,
you will execute the loop only once per time slice rather than many times.
This greatly speeds up jobs in the other DV windows, without affecting the
calling program at all.

The most wasteful RBBS task is waiting for the telephone to ring; another is
waiting for the user to select a command and hit the Return key.  So we CALL
this procedure at the end of these loops.  The table below summarizes actual
measurements made with DV on an AST Premium 286 (10 MHz, zero wait state),
relative to speed on the same machine without DV, running a single job.  DV
SETUP default performance settings were 9 slices foreground, 3 slices
background.  This improvement would be larger and MUCH more noticeable on a
slower machine.

Similarly, DoubleDos normally allocates two thirds of the computing cycles to
the Visible task, and the remaining third to the Invisible task (plenty for
the RBBS bulletin board).  The loss of cycles is sometimes noticeable, and this
reclaims them when not really needed by RBBS.  You can even use this to speed
up both nodes of RBBS, when one is in the Visible section and the other is in
the Invisible section (you would probably choose PRIORITY=EQUAL with 2 nodes).
DD version 4.00 has a special interrupt that allows the programmer to "give
back" up to 255 time slices of duration 55 milliseconds each.  This procedure
gives back 6 slices, about a third of a second at the old 4.77 MHz clock rate.
                        
The table below summarizes actual speed measurements with and without
GIVEBACK, running under both DoubleDos and DESQview.  The speedup is
wonderful, about 65%.  Once you use it, you'll never go back.

                        
        Non-bbs speed   ³  Waiting for Ring  ³  Caller On
        ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
DV:     Unmodified      ³        74%         ³    74%              
        With GIVEBACK   ³        98%         ³ variable, average 86%   
        ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
DD:     Unmodified      ³        57%         ³    57%              
        With GIVEBACK   ³        94%         ³ variable, average 80%   
        ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Challenge for multitasking RBBS enthusiasts:  There are additional wasteful
loops in RBBS--put on your best Sherlock outfit, and go snooping for places to
CALL GIVEBACK.  Please keep in touch with me on your progress through the
telephone numbers or address posted at the top of this file.


                           ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿                          
                           ³     RBBS 16.1       ³
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³   Starting with version 16.1, RBBS has the implementation for GIVEBACK   ³
³   already built in.  The original release version omitted one call,      ³
³   the one within the loop waiting for the telephone to ring.  It is      ³
³   repaired by making the small change below in RBBSSUB2.BAS              ³
³                                                                          ³
³  270 . . .                                                               ³
³      call giveback:WEND                                                  ³
³                                                                          ³
³    Then compile the modified RBBSSUB2.BAS, and LINK  RBBSSUB2.OBJ        ³
³    together with  GIVEBK31.OBJ and the rest of the normal RBBS  OBJect   ³
³    files package.                                                        ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ


                                                                            
                           ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿                          
                           ³    RBBS 15.1c       ³                          
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³    To implement GIVEBACK, modify RBBSSUB1.BAS by the addition of the     ³
³    lower case letter portion) in 2 lines only:                           ³
³                                                                          ³
³  270 IF RECYCLE.WAIT > 0 THEN _                              ' CPC15-1C  ³
³      IF TI! > INACTIVE.DELAY! THEN _                         ' CPC15-1C  ³
³      SUBROUTINE.PARAMETER = 8 : _                            ' CPC15-1C  ³
³      EXIT SUB                                                ' CPC15-1C  ³
³      call giveback:WEND                                                  ³
³      . . .                                                               ³
³ 1526 Y$ = KEY.PRESSED$                                                   ³
³      IF Y$ <> "" THEN _                                                  ³
³      GOTO 1545                                                           ³
³      call giveback:GOTO 1525                                             ³
³                                                                          ³
³    Then compile the modified RBBSSUB1.BAS, and LINK  RBBSSUB1.OBJ        ³
³    together with  GIVEBK31.OBJ and the rest of the normal RBBS  OBJect   ³
³    files package.                                                        ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

                           ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿                          
                           ³    RBBS 14.1d       ³                          
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³    To implement GIVEBACK, modify RBBS-SUB.BAS version 14.1D (by the      ³
³    addition of the lower case letter portion) in 2 lines only:           ³
³                                                                          ³
³     270  call giveback : WEND                                            ³
³          . . .                                                           ³
³    1526  (actually, three lines after this line number . . .)            ³
³          call giveback : WEND                                            ³
³                                                                          ³
³    Then compile the modified RBBS-SUB.BAS, and LINK  RBBS-SUB.OBJ        ³
³    together with  GIVEBK31.OBJ and the rest of the normal RBBS  OBJect   ³
³    files package.                                                        ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ




GIVEBACK Version history:

 1.0    December 1986 was the first version, for RBBS-PC v14.1D and DoubleDos
        version 4.0

 1.2    January 2, 1987  Added a second call to giveback in the WHILE..WEND
        loop which waits for user to enter a command.  DoubleDos only.

 1.3    May 20, 1987.  Changed to prevent RBBS modified with GIVEBACK from
        crashing the system when run under naked Dos, that is, without the use
        of DoubleDos.  Replaced direct INT FEh statement, with indirect AH=EEh,
        followed by normal Dos function INT 21h.  DD and Dos obligingly work
        together like this:  DD modifies the INT 21h function tables when it
        starts so as to recognize EEh, and naked Dos ignores functions like EEh
        which are unknown to it.  Possible caution--DD is definitely
        non-standard in making this modification.  This should cause no
        problem, UNLESS you use yet another non-standard program that also
        grabs AH=EEh under INT 21h for another purpose (unlikely).

2.0     Jan 1988.  Version is for DESQview 2.01  (works fine in 2.0 too),
        together with RBBS 15.1c.  It does not supersede GIVEBK13,
        required for operation under DoubleDos.  Although it duplicates some
        lines of code found in RBBSDV.ASM, this is a simple, small, and cleanly
        independent addition.  RBBS, modified to include this revision, will
        work under naked DOS alone, or under DESQview.  (personal note--I run
        only a single node, and prefer to drop all the FILELOCK, RBBSDV, and
        multilink crap and related calls from my personal version of RBBS;
        shrinks the .EXE file and makes it more reliable)

3.0     Feb 1988.  This version consolidates DoubleDos and DESQview routines
        into one that works equally well for RBBS running under either
        multitasker, or under naked DOS.  Calling points are given for both
        RBBS 14.1d and 15.1c.  My hope is that RBBS version 16.0 will
        incorporate this into the release version.

3.1     Apr 1988.  Minor upgrade neatens code and also eliminates the former
        requirement for initializing GIVEBACK by calling GIVEINIT.  It can be
        initialized explicitly as before; but if the user chooses to call
        GIVEBACK straight away, then the initialization will be taken care of
        automatically.

(End of comments here-you do not have to remove these comments to assemble.) ~


GIVESEG SEGMENT 'CODE'
        ASSUME  CS:GIVESEG
        PUBLIC  GIVEINIT        ;the initialization routine, optional
        PUBLIC  GIVEBACK	;CALL GIVEBACK to give back time slice

MultiTasker  DB  -1     ; will indicate which multitasker is running, if any
                        ;-1 means this hasn't yet been called, and
                        ;    initialization is required using GIVEINIT
                        ; 0 means no multitasker is present, only naked dos
                        ; 1 means DESQview is running
                        ; 2 means DoubleDos is running

GIVEINIT PROC	FAR
	PUSH	AX	; save this stuff for safety
        PUSH    BX
        PUSH    CX
        PUSH    DX
        MOV     AX,2B01H                ; DV get version request, result to AX
        MOV     CX,'DE'                 ; Illegal
        MOV     DX,'SQ'                 ;        date, on purpose
        INT     21H                     ; An error indicates DV isn't running
        CMP     AL,0FFH                 ; Are we in DV?
        JE      NO_DV                   ; Jump if not
        MOV     CS:MultiTasker,1  	; 1 will mean DV is present
        JMP     SHORT InitExit
NO_DV:				; DV isn't here, maybe DD is-let's check
	MOV	AH,0E4h		; function E4h tests for presence of DoubleDos
	INT	21h  		; does nothing at all if DD not present
	CMP	AL,01  		; 1 indicates DD present, program visible
	JZ	DDhere
	CMP	AL,02 		; 2 indicates DD present, program invisible
	JZ	DDhere
        JMP     NoMultitsk      ; anything else indicates not present, so quit
DDhere: MOV	CS:MultiTasker,2	;this value indicates DD present
        JMP     SHORT InitExit
NoMultitsk:
        MOV     CS:MultiTasker,0        ;Neither DV nor DD running
InitExit:
        POP     DX                      ;and put it all back
        POP     CX
        POP     BX
	POP	AX
        RET
GIVEINIT ENDP


API_CALL PROC		; local DV routine that goes on stack, does whatever
	PUSH	AX	;  call is passed in BX, then goes off stack
        MOV     AX,101AH
        INT     15H                     ; OSTACK
        MOV     AX,BX
        INT     15H                     ; Parameter
        MOV     AX,1025H
        INT     15H                     ; USTACK
        POP     AX
        RET
API_CALL ENDP


GIVEBACK PROC FAR       ;Gives up the rest of its time slice when called.
                        ;GIVEINIT will be invoked automatically the first time
                        ; that GIVEBACK is called; GIVEINIT can (optionally)
                        ; be called explicitly to force initialization.
        CMP     CS:MultiTasker,1        ;let's see what's running here
        JZ      DVrunning               ;1 means DESQview is running
        JG      DDrunning               ;2 means DoubleDos is running
        CMP     CS:MultiTasker,0        ;only naked Dos or uninitialized state
                                        ;  remain as possibilities
        JZ      GetOutaHere             ;0 means naked Dos
        CALL    GIVEINIT                ;last remaining possibility is -1
        JMP     GIVEBACK                ;after initializing, try this again

GetOutaHere:                            ;nothing else to do, so go back
        RET

DVrunning:
        PUSH    BX
        MOV     BX,1000H                ; DV_PAUSE function call
        CALL    API_CALL
        POP     BX
        JMP     SHORT GetOutaHere


DDrunning:
        push    bp      ;save caller's base pointer register
        mov     bp,sp   ;setup to address off of base pointer register
        push    ax      ;just in case this messes up something
        mov     ax,0EE06h

Comment ~       EEh in AH is special DoubleDos giveback interrupt. 06h in AL is
six 55ms giveback intervals = 1/3 sec.  ~

        int     21h     ;invokes special DoubleDos giveback interrupt
        pop     ax      ;puts it back
	POP	BP      ;restore callers base pointer register
        JMP     SHORT GetOutaHere

GIVEBACK ENDP
GIVESEG  ENDS
         END
