home *** CD-ROM | disk | FTP | other *** search
- ;;*************************************************************************
- ;; timer.inc timer.inc
- ;;*************************************************************************
- ;; Copyright (C) 1989 Northwestern University, Vance Morrison
- ;;
- ;;
- ;; Permission to view, compile, and modify for LOCAL (intra-organization)
- ;; USE ONLY is hereby granted, provided that this copyright and permission
- ;; notice appear on all copies. Any other use by permission only.
- ;;
- ;; Northwestern University makes no representations about the suitability
- ;; of this software for any purpose. It is provided "as is" without expressed
- ;; or implied warranty. See the copywrite notice file for complete details.
- ;;
- ;;*************************************************************************
- ;; timer.inc implements functions that will allow a task to wait a specific
- ;; amount of time
- ;;
- ;; Routines provided by this module
- ;;
- ;; TIMER_DECLARE name, task
- ;; TIMER_DEFINE name
- ;; TIMER_MARK_in_AX_const_CX_BP_ES name, code_label
- ;; TIMER_RETURN name
- ;;
- ;; AUTHOR: Vance Morrison
- ;; DATE : 4/22/89
- ;;*************************************************************************
-
- TIMER_MAX = 32 ;; number of outstanding requests
-
- timer_entry struc
- timer_next dw 0 ;; this MUST be first !!!
- timer_time dw 0
- timer_jmp dw 0
- timer_entry ends
-
- timer_data struc
- timer_next_time dw ?
- timer_list dw ?
- timer_free dw ?
- timer_table timer_entry TIMER_MAX dup (<>)
- timer_switch_ctr db ? ;; counts number of context switches
- timer_data ends
-
-
- ;;************************************************************************
- ;; TIMER_DECLARE declares a structure called 'name' that can be used to
- ;; wait for a certain time. 'task' is the name of the task needed
- ;; by this module
- ;;
- TIMER_DECLARE MACRO name, task
- .errb <task>
-
- .DATA
- timer_&name&_task equ task
- global timer_&name&_data:timer_data
- .CODE
- ENDM
-
-
- ;;************************************************************************
- ;; TIMER_DEFINE defines all the data storage and does initialization
- ;; functions for the timer object 'name'.
-
- TIMER_DEFINE MACRO name
- local around, start
- .errb <name>
-
- .data
- timer_&name&_data timer_data <>
-
- .code
- jmp around
- start:
- TIMER_TASK name, %timer_&name&_task
- ;; this does not fall through
- around:
-
- mov CX, TIMER_MAX
- xor DI, DI
- mov SI, offset timer_&name&_data.timer_table+(TIMER_MAX*(size timer_entry))
- init_loop:
- sub SI, size timer_entry
- mov [SI+timer_next], DI
-
- mov DI, SI
- dec CX
- jnz init_loop
- mov timer_&name&_data.timer_free, SI
- mov timer_&name&_data.timer_list, 0
- mov timer_&name&_data.timer_switch_ctr, 1
-
- ;; start the task
- TASK_DEFINE %timer_&name&_task, start
- ENDM
-
-
- ;;************************************************************************
- ;; TIMER_MARK_in_AX_const_CX_BP_ES sets the mark point so that
- ;; the code at 'code_label' will be called aftger AX ticks have elapsed.
- ;; (a tick is 18th of a second). The code should call TIMER_RETURN
- ;; when it is done processing
- ;; (Note that AX is limited to be 1024 seconds (32K ticks))
- ;;
- TIMER_MARK_in_AX_const_CX_BP_ES MACRO name, code_label
- local done, sort_loop, found
- .errb <code_name>
-
- ;; get current time
- TIMER_GET_TICK_out_BX_const_AX_CX_BP_SI_DI_ES
- add AX, BX
- mov DX, AX ;; DX holds expiration time
-
- mov SI, offset timer_&name&_data.timer_list
- mov DI, timer_&name&_data.timer_list
- sort_loop: ;; find the position in the list
- or DI, DI
- jz found
- cmp DX, [DI+timer_time]
- js found
-
- mov SI, DI
- mov DI, [SI+timer_next]
- jmp sort_loop
- found:
-
- mov BX, timer_&name&_data.timer_free
- or BX, BX ;; anything on the free list?
- jz done
-
- mov AX, [BX+timer_next] ;; insert the record
- mov timer_&name&_data.timer_free, AX
- mov [BX+timer_time], DX
- mov [BX+timer_jmp], offset code_label
- mov [BX+timer_next], DI
- mov [SI+timer_next], BX
-
- mov BX, timer_&name&_data.timer_list
- mov AX, [BX+timer_time]
- mov timer_&name&_data.timer_next_time, AX
- done:
- ENDM
-
- TIMER_RETURN MACRO name
- .errb <name>
-
- TASK_RETURN %timer_&name&_task
- ENDM
-
-
- ;;************************************************************************
- ;; TIMER_TASK is the code that the TIMER task runs. This task basicly just
- ;; waits for the next event, and starts it when its time.
- ;;
- TIMER_TASK MACRO name
- local done, no_more, do_stuff
- .errb <name>
-
- dec timer_&name&_data.timer_switch_ctr ;; only check every 20 context
- jz do_stuff
- TASK_RETURN %timer_&name&_task
- do_stuff:
- mov timer_&name&_data.timer_switch_ctr, 20
-
- TIMER_GET_TICK_out_BX_const_AX_CX_BP_SI_DI_ES
- cmp BX, timer_&name&_data.timer_next_time
- js done ;; if time is not up. Note that
- ;; this comparison works correctly
- ;; in the face of wraparound as long
- ;; as the delta T is < 32K
-
- mov SI, timer_&name&_data.timer_list
- or SI, SI
- jz done
-
- ;; take event off the queue
- mov BX, [SI+timer_next]
- mov timer_&name&_data.timer_list, BX
- or BX, BX
- jz no_more
- mov AX, [BX+timer_time]
- mov timer_&name&_data.timer_next_time, AX
- no_more:
- mov AX, timer_&name&_data.timer_free
- mov [SI+timer_next], AX
- mov timer_&name&_data.timer_free, SI
- jmp [SI+timer_jmp]
-
- done:
- TASK_RETURN %timer_&name&_task
- ENDM
-
-
- ;;*************************************************************************
- ;; dig into low memory and get me the tick counter.
- ;;
- ;; This is where IBM Bios puts its tick counter. (18 ticks/sec)
- ;; Note that this location may be different on clones, but as far
- ;; I I can tell, most clones put the ticks here too.
- IBM_BIOS_TICK equ 46CH
-
- TIMER_GET_TICK_out_BX_const_AX_CX_BP_SI_DI_ES MACRO
- mov DX, DS
- xor BX, BX
- mov DS, BX
- mov BX, IBM_BIOS_TICK
- mov BX, [BX]
- mov DS, DX
- ENDM
-
-