* $Id: select.asm,v 1.1 1998/02/02 08:19:46 taubert Exp $ * * select.asm * * modified socket stuff - Derek Taubert - 12/13/94 * added GS/OS file support and proper return value - DT - 2/6/96 * added timeout support - DT - 2/13/96 * mcopy m/select.mac case on copy inc/tty.inc copy inc/gsos.inc copy inc/kern.inc copy global.equates IncBusyFlag gequ $E10064 DecBusyFlag gequ $E10068 DebugNames gequ 1 * * * TIselect START KERN2 TIselect name using pipeRecord using KernelStruct using SelTimStruct * locals mask equ 1 1 used? pPtr equ mask+4 5 fdtptr equ pPtr+4 9 fdPtr equ fdtptr+4 13 used? slept equ fdPtr+4 17 r_mask equ slept+2 19 w_mask equ r_mask+4 23 x_mask equ w_mask+4 27,28,29,30 space equ x_mask+4-1 * intermediates bsp equ x_mask+4 31 dsp equ bsp+1 32 rtl2 equ dsp+2 34 rtl1 equ rtl2+3 37 * args errnoptr equ rtl1+3 40 timeout equ errnoptr+4 44 exceptfds equ timeout+4 48 writefds equ exceptfds+4 52 readfds equ writefds+4 56 width equ readfds+4 60 retval equ width+2 62 phd phb phk plb tsc sec sbc #space tcd tcs stz retval lda >procPtr sta pPtr lda >procPtr+2 sta pPtr+2 ldy #openFiles-CKernData lda [pPtr],y sta fdtptr ldy #(openFiles-CKernData+2) lda [pPtr],y sta fdtptr+2 lda readfds ora readfds+2 beq checkwr1 pei (readfds+2) pei (readfds) pei (fdtptr+2) pei (fdtptr) jsl validate_mask cmp #0 bne err_mask checkwr1 lda writefds ora writefds+2 beq checkex1 pei (writefds+2) pei (writefds) pei (fdtptr+2) pei (fdtptr) jsl validate_mask cmp #0 bne err_mask checkex1 lda exceptfds ora exceptfds+2 beq enter_loop pei (exceptfds+2) pei (exceptfds) pei (fdtptr+2) pei (fdtptr) jsl validate_mask cmp #0 beq enter_loop err_mask lda #EBADF sta [errnoptr] lda #-1 sta retval jmp goaway enter_loop anop stz slept jsr getSelTimIndex lda #0 sta >SelTimExpired,x lda >curProcInd tax lda #0 sta >p_waitvec,x ; just for kicks.. sta >p_waitvec+2,x select_loop anop * First, reset the local select masks we're using lda #0 sta r_mask sta r_mask+2 sta w_mask sta w_mask+2 sta x_mask sta x_mask+2 * Set Process' "selecting" flag ldy #flags-KernelStruct lda [pPtr],y ora #FL_SELECTING sta [pPtr],y * For each FD, poll the device by calling its select routine * If the descriptor can't do the operation, select must record that * this process wants to do I/O. lda readfds ora readfds+2 beq checkwr2 pea SEL_READ pei (readfds+2) pei (readfds) pei (fdtptr+2) pei (fdtptr) pea 0 tdc clc adc #retval pha jsl poll_mask sta r_mask stx r_mask+2 checkwr2 lda writefds ora writefds+2 beq checkex2 pea SEL_WRITE pei (writefds+2) pei (writefds) pei (fdtptr+2) pei (fdtptr) pea 0 tdc clc adc #retval pha jsl poll_mask sta w_mask stx w_mask+2 checkex2 lda exceptfds ora exceptfds+2 beq endpoll pea SEL_EXCEPT pei (exceptfds+2) pei (exceptfds) pei (fdtptr+2) pei (fdtptr) pea 0 tdc clc adc #retval pha jsl poll_mask sta x_mask stx x_mask+2 endpoll php sei lda >curProcInd tax lda >flags,x bit #FL_SELECTING bne noloop * Somebody cleared FL_SELECTING, we better check again plp jmp select_loop noloop and #FL_SELECTING.EOR.$FFFF sta >flags,x ; retval slept timeout SelTimExpired ; 0 0 0 X sleep ; 0 0 1 X set alarm, sleep ; 0 1 0 X return -1, EINTR ; 0 1 1 0 return -1, EINTR ; 0 1 1 1 return 0 ; 1 X X X return retval lda retval bne done1 ; we have a fd, kaptain! lda slept beq tosleep ; check to see how k_sleep woke up lda timeout ora timeout+2 beq interup jsr getSelTimIndex lda >SelTimExpired,x beq interup lda #0 sta >SelTimExpired,x done1 bra done ; we timed out! interup plp lda #EINTR sta [errnoptr] lda #-1 sta retval jmp goaway timeoutTMP dc i4'0' ; set up alarm here tosleep lda timeout ora timeout+2 beq noalrm setalrm anop MUL4 [timeout],#10,timeoutTMP ; FIXME: add microseconds to timeoutTMP too jsr getSelTimIndex lda timeoutTMP bne nofudge inc A ; so SelTimTimeout never starts at zero nofudge sta >SelTimTimeout,x lda timeoutTMP+2 sta >SelTimTimeout+2,x lda >curProcInd sta >SelTimPID,x noalrm lda >truepid pha pea 0 ph4 #selwait jsl k_sleep inc slept lda timeout ora timeout+2 beq noalrm2 ; remove alarm here jsr getSelTimIndex lda #0 sta >SelTimTimeout,x sta >SelTimTimeout+2,x noalrm2 plp jmp select_loop done plp ldy #2 lda r_mask sta [readfds] lda r_mask+2 sta [readfds],y lda w_mask sta [writefds] lda w_mask+2 sta [writefds],y lda x_mask sta [exceptfds] lda x_mask+2 sta [exceptfds],y goaway anop tsc clc adc #space tcs plb pld ldx #0 ldy #22 jmp >tool_exit END poll_mask START KERN2 poll_mask name using KernelStruct words_left equ 0 cur_fd equ 2 bitcount equ 4 wordind equ 6 fdPtr equ 8 outmask equ 12 subroutine (2:which,4:mask,4:fdtptr,4:fdsrdyptr),16 stz outmask stz outmask+2 ldy #FDTfdTableSize lda [fdtptr],y ; table size, divide by 16 lsr a lsr a lsr a lsr a sta words_left stz cur_fd stz wordind val_loop1 lda #16 sta bitcount ldy wordind lda [mask],y val_loop2 ror a ; rotate into carry flag bcc dontcheck1 ; do not check this fd pha pei (cur_fd) jsl getFDptr sta fdPtr stx fdPtr+2 ; dispatch to the driver's select routine, which will tell us whether there's ; data and do other sundry stuff lda [fdPtr] ; get device number dec a ; dec to get device index pha pei (which) ; tell the driver which I/O operation ; had to add this parm - DT lda >curProcInd ; current pid pha ; ldy #FDrefType lda [fdPtr],y cmp #FDsocket beq selsok1 cmp #FDgsos beq selsok2 ; otherwise, it is #FDtty ; need to load A with dev type here, not ref type - DT lda [fdPtr] ; get device number dec a ; dec to get device index ldy #t_select jsl LineDiscDispatch bra donesel1 ; we can always read and write #FDgsos, never except selsok2 anop pla ; current pid pla ; which operation plx ; device number cmp #SEL_EXCEPT beq gsos_nox sec bra donesel2 gsos_nox clc bra donesel2 selsok1 anop jsl SOCKselect donesel1 cmp #1 ; set carry properly donesel2 bcc notready lda [fdsrdyptr] adc #0 sta [fdsrdyptr] sec notready ldx wordind ror p_waitvec,x cmp #selwait bne ck_coll lda >p_waitvec+2,x cmp #^selwait bne ck_coll lda >ProcessState,x cmp #PS_SLEEP bne ck_coll ph4 #selwakeupdefer lda pid lsr a lsr a lsr a lsr a lsr a lsr a lsr a pha pea 1 jsl defer bra goaway ck_coll lda >flags,x and #FL_SELECTING.EOR.$FFFF sta >flags,x goaway return END SelTimStruct DATA SelTimTimeout dc i4'0' ; timeout in tenths of seconds SelTimPID dc i2'0' ; pid argument to call selwakeup with SelTimExpired dc i2'0' ; set by the HB routine when she blows ds 8*(NPROC-1) ; space for 31 more entries END getSelTimIndex START KERN2 getSelTimIndex name using KernelStruct lda >truepid asl a asl a asl a tax rts END ;KERNgetdtablesize START KERN2 ; using KernelStruct ; ;pPtr equ 0 ;fdPtr equ 4 ;ret equ 8 ; ; subroutine (4:errptr),10 ; ; mv4 >procPtr,pPtr ; ldy #openFiles-CKernData ; lda [pPtr],y ; sta fdPtr ; ldy #(openFiles-CKernData-2) ; lda [pPtr],y ; sta fdPtr+2 ; ; lda #0 ; sta [errptr] ; ; ldy #FDTfdTableSize ; lda [fdPtr],y ; sta ret ; return 2:ret ; END ; ;STACK START ~_STACK ; KIND $12 ; ds 1024 ; END