.TITLE DRSEM .IDENT /02.4/ ; ; VERSION 02.4 ; WRITTEN MAY 18,1977 ; HARRY ATHERTON ; UNIVERSITY OF CINCINNATI MEDICAL CENTER ; 231 BETHESDA AVE. ; CINCINNATI, OHIO 45267 ; PHONE (513) 872-5341 ; ; MODIFIED JULY 12,1982 TO ALLOW PLACEMENT IN EXCOM2 ; MODIFIED FEB 17, 1983 TO CHECK FOR TASK ALREADY ON LIST AT P-OPERATION ; MODIFIED JUNE 30, 1983 TO WORK WITH RSX-11M-PLUS V2.0 AND 2.1 AND ; RSX-11M V4.0 (DON'T KNOW ABOUT V4.1 YET) ; ; 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 ; AFTER CHECKING TO SEE THAT THE TCB IS NOT ALREADY AT THE HEAD OF THE LIST ; 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 ;NOW FIND SEMAPHORE LIST HEAD DEC R3 ;CONVERT SEMAPHORE NUMBER TO OFFSET ASL R3 ASL R3 MOV #$SEMHD,R0 ;BASE ADDRESS OF SEMAPHORE LIST HEADS ADD R3,R0 ;OFFSET TO SPECIFIED SEMAPHORE MOV R0,-(SP) ;SAVE THE LIST HEAD ADDRESS MOV @R0,R1 ;GET FIRST ENTRY ON LIST BEQ 5$ ;BRANCH IF NO ENTRY ;CHECK THE TCB ADDRESS OF THE FIRST ENTRY CMP 4(R1),R5 ;IS IT THE ADDRESS OF OUR TCB ? BNE 5$ ;BRANCH IF NOT, OK TO PROCEED ;WE ARE ALREADY ON THIS SEMAPHORE LIST TST (SP)+ ;RESTORE THE STACK TST (SP)+ DRSTS D.RS8 ;RETURN DIRECTIVE ERROR STATUS IE.ITS ; 5$: ;WE CAN ADD OURSELF TO THIS SEMAPHORE LIST ;GET A BLOCK FROM POOL MOV #6,R1 ;SIZE OF CORE BLOCK REQUESTED (BYTES) CALL $ALOCB ;GET BLOCK BCC 10$ ;BRANCH IF ALLOCATION MADE ;NO CORE AVAILABLE, RETURN FAILURE CODE TST (SP)+ ;RESTORE STACK TST (SP)+ DRSTS D.RS1 ; ; 10$: ;WE NOW HAVE: ;R0=ADDRESS OF CORE BLOCK ;R1=LENGTH OF BLOCK MOV R0,R1 ;ADDRESS OF CORE BLOCK MOV (SP)+,R0 ;ADDRESS OF CORRECT SEMAPHORE LIST HEAD CALL $QINSF ;INSERT BLOCK ON QUEUE ;PUT ADDRESS OF TCB IN BLOCK MOV R5,4(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 ; .IF DF D$$PAR ;IF EXCOM'S ARE USED, DUPLICATE DRSPN LOGIC HERE ; BIS #T2.SPN,(R2) ;SUSPEND CURRENT TASK CALL $SETRT ;FORCE A REDISPATCHING OF PROCESSOR DRSTS D.RS22 ;SET DIRECTIVE STATUS ; .IFF ;D$$PAR ;IF WE ARE ALL TOGETHER JUST JUMP OVER ; CALLR $DRSPN ; .IFTF ; ; ; ;+ ; **-$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 4(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 #6,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 4(R1),R0 ;LOAD ADDRESS OF TCB MOV R0,R1 ;COPY ADD #T.STAT,R1 ;MOVE TO TASK STATUS WORD ; .IFT ;D$$PAR SEPARATE EXCOM ; DUPLICATE RESUME LOGIC RATHER THAN LINK BACK THROUGH ROOT ; TST (R1)+ ;TASK ACTIVE? BMI 24$ ;IF MI NO MOV #T2.SPN,R2 ;GET SUSPEND BIT BIT R2,(R1) ;TASK CURRENTLY SUSPENDED? BNE 22$ ;IF NE YES TST (R1) ;AST IN PROGRESS? BPL 26$ ;IF PL NO ASL R2 ;SET PRE AST SUSPEND BIT BIT R2,(R1) ;WAS TASK SUSPENDED? BEQ 26$ ;IF EQ NO ; 22$: BIC R2,(R1) ;CLEAR TASK'S SUSPEND BIT CALLR $SETCR ;SET A CONDITIONAL SCHEDULE REQUEST ; 24$: DRSTS D.RS7 ;SET DIRECTIVE STATUS 26$: DRSTS D.RS8 ;SET DIRECTIVE STATUS ; .IFF ;D$$PAR NO DIRECTIVE COMMON ; THEN IT SAVES CORE JUST TO JUMP TO DRRES ; CALLR $DRRES ;RESUME TASK ; ;NOTE REGARDING ABOVE; $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 ; .ENDC ;D$$PAR ; 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 ; ; IMPORTANT ! ; SINCE THIS ROUTINE IS CALLED AS A SUBROUTINE FROM DREIF IT MUST ; A L W A Y S COMPLETE VIA A RETURN ! ;- ; $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 #6,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 4(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 ; ; ; .END