_SOFTWARE PARTITIONING FOR MULTITASKING COMMUNICATIONS_ by David McCracken [LISTING ONE] COMMENT $ ------------------ _RELEASE -------------------------------------- A task can call this from any point to release its time. However, better heap utilization will result from freeing memory allocated during a time slot before releasing. To caller, release looks like a simple function whose prototype is void release(void). All other currently enabled tasks are then dispatched in turn until the cycle is complete and this task is redispatched by returning from the call. The si, di, ds, bp registers are restored as expected. Thus, the release function also acts as the dispatcher. By using "ret" to dispatch, the dispatcher automatically knows the size of task dispatch addresses by whether SMALL or LARGE CODE. $ _release PROC push bp push ds push di push si mov ax,dseg mov ds,ax mov si,[task_no] ;Get current task number. shl si,1 ;*2 to convert to index for sp word table. mov word ptr stk_ptrs[si],sp ;Save sp for next dispatch of this task. nextsk: dec [task_no] jnz dpatch ;If task_no is OK then go dispatch the next task. ;Task 1 (on bottom of stack heap) has just finished; so verify it didn't ; corrupt stack below allotment by checking "end of stack" marker is valid. mov bp,mark_pos ;Point to marker location on stack. cmp [bp],marker_value ;Is the mark still there? jne scrash ;Crash on task_no=0 means task 1 overran its stack. mov si,[max_t_no] mov [task_no],si ;Rollover task count to upper limit. dpatch: mov si,[task_no] ;Get current task number. cmp byte ptr task_enable[si],0 je nextsk ;If this task is disabled then try for next one. shl si,1 ;*2 to convert to index for sp word table. mov bp,mark_pos[si] ;Get this task's stack marker. cmp [bp],marker_value ;Did the preceding task overflow its stack? jne scrash cli ;Don't allow interrupts while monkeying with stack. mov sp,word ptr stk_ptrs[si] ;Retrieve sp saved during last dispatch ;of this task. sti ;Interrupts OK now because any individual stack ;should be able to support them. pop si pop di pop ds pop bp ;Assume these registers are only ones stored through ;release and re-dispatch cycle. However, watch out ;for possible register variables. ret ;Dispatch task by returning to its release return ;address. Note that dispatch/release is implicitly a ;loop only by operation with dispatched tasks. _release ENDP [LISTING TWO] COMMENT $ GPIB transaction descriptors. Each descriptor lists input destination address, maximum input length that can be tolerated, type of response (used for concurency control), checksum status of the response, response source address and its length. $ _gpib_trans LABEL WORD ; |----INPUT DESTINATION---------| |------------- RESPONSE -----------------| ; address length type CHKSTAT/chkLB address length ;...... analyzer status ..........| |............... acknowlege .............| dw OFFSET _status, SEG _status, 12040, 0f000h, 00fdh, OFFSET ack , SEG ack , 11 ;....... command request .........| |.............. command .................| dw 0 , 0 , 12, 0200h, 0100h, OFFSET _cmnd, SEG _cmnd, 245 ;....... phase request ...........| |.............. command .................| dw 0 , 0 , 12, 0200h, 0100h, OFFSET _cmnd, SEG _cmnd, 245 . . . [LISTING THREE] ;-------------------- Input Available Status ---------------------- _gpib_stat db 0,0,0,0 COMMENT $ _gpib_stat is defined as a 4 byte object so that a C program can access each byte as unsigned char (UC), any pair as unsigned short (US), or the entire group as unsigned long (UL). In C, data is declared by "extern UC gpib". A quick check for any input would be " if(*(UL*)gpib_stat)". Accessing as smaller objects allows catagorical checking without having to check each bit individually. For example, "if(*(US*)(gpib_stat+1)" tests for any bit set in the second two bytes. $ ;-------------------- Status flag selector table --------------------- flag_select LABEL WORD ;Flag selectors: byte selector and bit mask. dw 0001h ;status: flag byte 0, bit 0. dw 0002h ;command request: flag byte 0, bit 1. dw 0004h ;phase request: flag byte 0, bit 2. . . .