.TITLE DRSEM .IDENT /01.2/ ; ; VERSION 01.2 ; WRITTEN MAY 18,1977 ; HARRY ATHERTON ; UNIVERSITY OF CINCINNATI MEDICAL CENTER ; 231 BETHESDA AVE. ; CINCINNATI, OHIO 45267 ; PHONE (513) 872-5341 ; ; MODIFIED OCT 31,1979 TO IMPLEMENT 20 SEMAPHORES ; $SEMNM == 20. ;NUMBER OF SEMAPHORE QUEUES ; ; ; THIS PROGRAM IMPLEMENTS THE VARIOUS SEMAPHORE OPERATIONS ; (P, V, AND TASK EXIT CLEANUP) ; ;+ ; **-$DRPOP-SEMAPHORE P OPERATION ; ; THIS DIRECTIVE PLACES THE ISSUING TASK TCB ADDRESS ON THE ; INDICATED SEMAPHORE QUEUE ; IF IT IS NOT THEN THE FIRST TASK ON THE QUEUE ; THE TASK IS SUSPENDED ; ; INPUTS (FROM DRDSP): ; R2 = ADDRESS OF THE SECOND STATUS WORD OF THE CURRENT TASK. ; R3 = ADDRESS OF THE SECOND WORD IN THE DPB. ; R4 = ADDRESS OF THE HEADER OF THE CURRENT TASK. ; R5 = ADDRESS OF THE TCB OF THE CURRENT TASK. ; ; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK) ; C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED. ; DIRECTIVE STATUS OF +1 RETURNS IF ; TASK IS NOT SUSPENDED ; DIRECTIVE STATUS OF 'D.RS22' IF ; TASK IS SUSPENDED ; ; C=1 IF DIRECTIVE IS REJECTED ; DIRECTIVE STATUS OF 'D.RS96' ; IF SEMAPHORE NUMBER IS OUT OF RANGE ; DIRECTIVE STATUS OF 'D.RS1' IF INSUFFICIENT DYNAMIC ; MEMORY TO ENTER TASK ON QUEUE ; ;- ; $DRPOP::CALL SEMCHK ;SUBROUTINE GETS SEMAPHORE NUMBER AND CHECKS IT ;IF INVALID SUBROUTINE RETURNS DIRECTLY TO ;CALLING TASK ;R3 NOW CONTAINS SEMAPHORE NUMBER MOV R2,-(SP) ;SAVE R2 MOV #C.TCB+2,R1 ;SIZE OF CORE BLOCK REQUESTED (BYTES) CALL $ALOCB ;GET BLOCK BCC 10$ ;BRANCH IF ALLOCATION MADE ;NO CORE AVAILABLE, RETURN FAILURE CODE DRSTS D.RS1 ; ; 10$: ;WE NOW HAVE: ;R0=ADDRESS OF CORE BLOCK ;R1=LENGTH OF BLOCK ;NOW FIND SEMAPHORE LIST HEAD DEC R3 ;CONVERT SEMAPHORE NUMBER TO OFFSET ASL R3 ASL R3 MOV R0,R1 ;ADDRESS OF CORE BLOCK MOV #$SEMHD,R0 ;BASE ADDRESS OF SEMAPHORE LIST HEADS ADD R3,R0 ;OFFSET TO SPECIFIED SEMAPHORE CALL $QINSF ;INSERT BLOCK ON QUEUE ;PUT ADDRESS OF TCB IN BLOCK MOV R5,C.TCB(R1) ;INSERT ADDRESS MOV (SP)+,R2 ;RESTORE STACK AND ADDRESS OF ;SECOND TASK STATUS WORD ;SEE IF THE CURRENT TASK IS AT THE HEAD OF THE LIST CMP (R0),R1 ;ADDRESS OF FIRST ENTRY, ADDRESS OF ;THIS TASK'S BLOCK BNE 20$ ;BRANCH IF NOT, MUST SUSPEND ;TASK IS FIRST IN LIST, IT MAY CONTINUE RETURN ; 20$: ;TASK MUST BE SUSPENDED CALLR $DRSPN ; ; ; ;+ ; **-$DRVOP-SEMAPHORE V OPERATION ; ; THIS DIRECTIVE REMOVES THE TASK'S BLOCK FROM THE FRONT OF ; THE SPECIFIED SEMAPHORE QUEUE ; ERROR RETURN IF THE ENTRY IS NOT THERE ; IF THERE IS ANOTHER TASK IN THE QUEUE IT IS RESUMED ; ; INPUTS (FROM DRDSP): ; R2 = ADDRESS OF THE SECOND STATUS WORD OF THE CURRENT TASK. ; R3 = ADDRESS OF THE SECOND WORD IN THE DPB. ; R4 = ADDRESS OF THE HEADER OF THE CURRENT TASK. ; R5 = ADDRESS OF THE TCB OF THE CURRENT TASK. ; ; ; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK) ; C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED. ; ; C=1 IF DIRECTIVE IS REJECTED ; DIRECTIVE STATUS OF 'D.RS96' IF SEMAPHORE NUMBER ; IS INVALID (OUT OF RANGE) ; ; DIRECTIVE STATUS OF 'D.RS5' IF TASK IS NOT AT HEAD ; OF SPECIFIED QUEUE ; ; DIRECTIVE STATUS OF 'D.RS7' OR 'D.RS8' MAY BE RETURNED ; BY $DRRES ; ;- $DRVOP::CALL SEMCHK ;GET AND CHECK SEMAPHORE NUMBER ;R3 NOW CONTAINS SEMAPHORE NUMBER ;FIND SEMAPHORE LIST HEAD DEC R3 ;CONVERT TO OFFSET ASL R3 ASL R3 MOV #$SEMHD,R0 ;BASE ADDRESS OF SEMAPHORE LIST HEADS ADD R3,R0 ;OFFSET TO SPECIFIED QUEUE MOV @R0,R1 ;IS THERE AN ENTRY ? BEQ 10$ ;BRANCH IF NOT ;CHECK TCB ADDRESS IN FIRST BLOCK CMP C.TCB(R1),R5 ;IS IT SAME AS CURRENT PROGRAM ? BEQ 20$ ;BRANCH IF YES, O.K. 10$: ;THIS TASK IS NOT AT THE HEAD OF THE SPECIFIED QUEUE DRSTS D.RS5 ;RETURN DIRECTIVE STATUS ; ; 20$: ;EVERYTHING CHECKS SO FAR, REMOVE TASK'S ENTRY CALL $QRMVF ;REMOVE BLOCK FROM QUEUE MOV R0,R4 ;SAVE ADDRESS OF LISTHEAD MOV R1,R0 ;ADDRESS OF BLOCK TO DEALLOCATE MOV #C.TCB+2,R1 ;SIZE OF BLOCK (BYTES) CALL $DEACB ;DE ALLOCATE ;NOW SEE IF THERE IS A TASK WAITING ON THE QUEUE MOV @R4,R1 ;ADDRESS OF FRONT ENTRY BEQ 30$ ;BRANCH IF NO ENTRY ;ENTRY, WE MUST RESUME IT MOV C.TCB(R1),R0 ;LOAD ADDRESS OF TCB MOV R0,R1 ;COPY ADD #T.STAT,R1 ;MOVE TO TASK STATUS WORD CALLR $DRRES ;RESUME TASK ;NOTE, $DRRES ISN'T THE BEST WAY TO RESUME A TASK ;SINCE IT HAS ERROR RETURNS WHICH COULD LEAVE A DEAD TASK ;ON THE SEMAPHORE QUEUE ; 30$: ;NO TASK TO RESUME RETURN ;GET THINGS GOING AGAIN ; ; ; ; ;+ ; **-$SEMCU-SEMAPHORE CLEAN UP CALLED BY TASK EXIT TO ; REMOVE ALL TASK ENTRIES AND RESUME ANY ELIGABLE TASKS ; ; INPUTS: REQUIRES ONLY R5 ; R5=ADDRESS OF THE TCB OF THE CURRENT TASK. ; ; OUTPUTS: PRESERVS ONLY R5 ; REMOVES ALL OF THE EXITING TASK'S ENTRIES FROM EACH OF ; THE SEMAPHORE QUEUES ; ;- ; $SEMCU:: ;SET UP TO LOOP ON ALL SEMAPHORE LIST HEADS MOV #$SEMNM,R4 ;NUMBER OF QUEUES DEC R4 ;CONVERT TO OFFSET ASL R4 ASL R4 10$: ;START OF QUEUE LOOP MOV #$SEMHD,R0 ;START OF LISTHEADS ADD R4,R0 ;OFFSET TO CURRENT LISTHEAD TST @R0 ;ARE THERE ANY ENTRIES ? BEQ 70$ ;BRANCH IF NOT, SKIP ALL OF THE FOLLOWING MOV @R0,-(SP) ;SAVE ADDRESS OF FIRST BLOCK ON QUEUE 20$: MOV R5,R1 ;TCB ADDRESS TO SEARCH FOR CALL $QRMVT ;REMOVE ENTRY 25$: BCS 30$ ;BRANCH IF NO ENTRY REMOVED ;NOW RETURN BLOCK TO CORE POOL MOV R0,-(SP) ;SAVE LISTHEAD ADDRESS MOV R1,R0 ;ADDRESS OF BLOCK MOV #C.TCB+2,R1 ;SIZE OF BLOCK CALL $DEACB ;RETURN BLOCK MOV (SP)+,R0 ;RESTORE LISTHEAD ADDRESS BR 20$ ;GO BACK AND SEE IF THERE IS ANOTHER ENTRY 30$: ;ALL MATCHING ENTRIES HAVE BEEN REMOVED ;SEE IF THE FIRST QUEUE ENTRY IS THE SAME ONE AS BEFORE CMP @R0,(SP)+ ;IS THE BLOCK ADDRESS THE SAME ? BEQ 70$ ;BRANCH IF YES, NOTHING TO RESUME ;NOW SEE IF THERE IS A TASK THERE MOV @R0,R3 ;SEE IF QUEUE IS EMPTY BEQ 70$ ;BRANCH IF YES ;WE HAVE A TASK TO RESUME ;USE OUR OWN LOGIC (SIMILAR TO $DRRES) ;SINCE WE CAN'T ALLOW A RETURN TO THE EXITING TASK MOV C.TCB(R3),R1 ;TASK'S TCB ADDRESS ADD #T.STAT,R1 ;POINT TO FIRST STATUS WORD TST (R1)+ ;TASK ACTIVE ? BMI 52$ ;IF MI NO MOV #T2.SPN,R2 ;GET SUSPENDED BIT BIT R2,(R1) ;TASK CURRENTLY SUSPENDED ? BNE 51$ ;IF NE YES TST (R1) ;AST IN PROGRESS ? BPL 53$ ;IF PL NO ASL R2 ;SET PRE AST SUSPEND BIT BIT R2,(R1) ;WAS TASK SUSPENDED ? BEQ 53$ ;IF EQ NO 51$: BIC R2,(R1) ;CLEAR SUSPEND STATE BR 70$ ;EXIT WILL PRODUCE SIGNIFICANT EVENT 52$: ;TASK IS NOT ACTIVE ;HOW COULD THAT HAPPEN ??????? ;BEST THING TO DO IS TO DEALLOCATE THE CORE BLOCK AND ;PRETEND EVERYTHING IS O.K. CLR -(SP) ;PUT DUMMY ORIGINAL BLOCK ADDRESS ON STACK CALL $QRMVF ;REMOVE THE BLOCK (FIRST ONE) BR 25$ ;REGULAR LOOP WILL TAKE CARE OF THINGS ; 53$: ;TASK IS NOT SUSPENDED ;THIS SHOULDN'T HAPPEN, BUT SINCE THE EXECUTIVE OR MCR RESUME ;COULD HAVE DONE IT WE WON'T GET TOO WORRIED ; ;WE WILL ASSUME THE TASK WILL DO A V OPERATION WHEN APPROPRIATE ; 70$: ;FINISHED WITH THIS QUEUE ;MOVE TO NEXT LISTHEAD SUB #4,R4 ;OFFSET BPL 10$ ;LOOP BACK IF MORE TO CHECK ;FINISHED, WE HAVE CLEANED ALL THE QUEUES RETURN ; ; SEMCHK: ;SEMAPHORE CHECK SUBROUTINE MOV (R3),R3 ;GET SEMAPHORE NUMBER BLE 20$ ;BRANCH IF ZERO OR NEGATIVE CMP R3,#$SEMNM ;CHECK UPPER LIMIT BGT 20$ ;BRANCH IF TOO BIG ;NUMBER IS O.K., RETURN RETURN ; 20$: ;INVALID SEMAPHORE NUMBER DRSTS D.RS96 ; ; ; ;SEMAPHORE DATA BASE ;SEMAPHORE LIST HEADER $SEMHD:: ;START OF HEADERS .REPT $SEMNM .WORD 0 ;LISTHEAD POINTER .WORD .-2 ;POINTER TO LAST ENTRY IN QUEUE .ENDM ; ; .END