Google
 

Trailing-Edge - PDP-10 Archives - AP-D471B-SB_1978 - msgout.bli
There are no other files named msgout.bli in the archive.
!***COPYRIGHT (C) 1974, 1975, 1976, 1977 DIGITAL EQUIPMENT CORP., MAYNARD, MASS.***
MODULE MSGOUT(RESERVE(#11,#12,#13,#14),SREG=#17,FREG=#16,DREGS=4,
	      VREG=#15,MLIST,TIMER=EXTERNAL(SIX12),FSAVE)=
BEGIN

REQUIRE  DATA.BLI;

	EXTERNAL	ROLIN,
			MOVE,
			UNDEFER;

	OWN		OPCHAIN;

	MACRO	FIRST = OPCHAIN<RH>$,
		LAST  = OPCHAIN<LH>$;

COMMENT;

!ROUTINE GETALTERNATE
!======= ============
! THIS ROUTINE GETS THE ALTERNATE OF A TERMINAL

ROUTINE GETALTERNATE(SRCPTR)=
	BEGIN
		MAP FORMAT SRCPTR;

		MACRO CURALT=(.SRCPTR[S0ALTPTR])<IF .SRCPTR[S0RIGHTALT] THEN RIGHT ELSE LEFT, HALFWORD >$; 

		IF .SRCPTR[S0SELF] THEN RETURN .SRCPTR;
		.CURALT
	END;
	EXTERNAL	DELGH,
			DELMH,
			DGPURGE,
			UNLINK,
			BUFAVAIL;

COMMENT;

! SUBROUTINE MSWRITE
! ========== =======
! LAST MODIFIED:	15 SEPT 76  BY  CDO

ROUTINE MSWRITE(DEST) =
    BEGIN
	REGISTER
		MHPTR,
		GHPTR,
		SRCPTR;

	LOCAL	SENDTO,
		SAVEREST,
		SAVECHNK,
		UDX;

	MAP	FORMAT MHPTR;
	MAP	FORMAT GHPTR;
	MAP	FORMAT SRCPTR;
	MAP	FORMAT SENDTO;

	SRCPTR _ .DEST;						! PICKUP THE SOURCE POINTER

	IF ( GHPTR _ .SRCPTR[S0FIGHPTR] ) EQL 0 THEN RETURN;	! IF NO MESSAGES, RETURN

	IF .GHPTR[G0SENDING] EQL 0 THEN				! IF OUTPUT NOT GOING ALREADY
	    BEGIN
		IF .SRCPTR[S0ED] EQL DISABLED THEN RETURN;	! CHECK FOR DISABLED NOW
		GHPTR[G0SENDING] _ 1				! NOT, MARK OUTPUT IN PROGRESS
	    END;

	IF ( SENDTO _ GETALTERNATE( .SRCPTR ) ) EQL 0 THEN RETURN; ! IF NO ONE TO SEND TO, RETURN

	IF .SENDTO<RH> NEQ .SRCPTR<RH> THEN
		IF .SENDTO[ S0IGHS ] NEQ 0 THEN RETURN;		! IF ALTERNATE IS OUTPUTTING, RETURN

	IF (UDX_.SENDTO[S0PORTPTR]) EQL 0 THEN RETURN;		! IF NO PORT CONNECTED, RETURN

	IF NOT BUFAVAIL(.UDX) THEN RETURN;			! IF NO OUTPUT BUFFERS AROUND, RETURN

	IF (MHPTR _ .GHPTR[G0OUTMH]) EQL 0 THEN RETURN;		! IF NO MESSAGES AVB YET, RETURN

	GHPTR[G0OUTMH] _ .MHPTR[M0FORE];			! SET UP FOR NEXT TIME

	IF .MHPTR[M0CHNKS] EQL 0 THEN				! IF NOT IN CORE
		IF .MHPTR[M0DSKADDR] NEQ 0 THEN			! IF ON DISK
			MHPTR[M0INCHNK]_MHPTR[M0OUTCHNK]_ROLIN(.MHPTR[M0DSKADDR],.GHPTR[G0DSKGHADDR])
			ELSE
			INFORM(PLIT ASCIZ 'FMESSAGE MARKED ON DISK BUT NO DISK ADDRESS@',
				0,0,0,0,0);

!  DECREMENT COUNT OF RECEIVERS AND IF = 0, CAN RELEASE THE MESSAGE

	SAVEREST _ IF (MHPTR[M0DSCNT] _ .MHPTR[M0DSCNT] - 1) LEQ 0 THEN FALSE
	    ELSE TRUE;
	SAVECHNK _ IF .SAVEREST AND .MHPTR[M0DSKADDR] EQL 0 THEN TRUE
	    ELSE FALSE;

	OUTMSG(.MHPTR[M0OUTCHNK],.UDX,.SAVECHNK,FALSE);			! OUTPUT THE MESSAGE

	IF NOT .SAVECHNK THEN MHPTR[M0CHNKS] _ 0;			! DONE BY OUTMSG

	IF .GHPTR[G0ENDI] AND (.GHPTR[G0OUTMH] EQL 0)  THEN		! IF THE GROUP IS DONE (I.E. EGI/EPI
									! ENCOUNTERED AND COMPLETELY TRANSMITTED)
	    BEGIN

		IF .GHPTR[G0ONDSK] THEN DGPURGE(.GHPTR[G0DSKGHADDR],.SAVEREST); ! CLEAR DISK IMAGE

		IF NOT .SAVEREST THEN DELGH(SRCPTR[S0IGHS],.GHPTR) ! DELETE THE GROUP IF NO MORE DESTINATIONS
		    ELSE DELETE( SRCPTR[S0IGHS], .GHPTR, G0SIZE, NOTCHUNK);	! ELSE DELETE ONLY
										! THE GROUP HEADER AND UNLINK

		IF .SRCPTR[S0IGHS] EQL 0 AND .PIGGYBACK NEQ 0 AND NOT .SRCPTR[S0DEFSENDING] THEN
									! IF THERE ARE NO MORE IMMEDIATE GROUPS
		    BEGIN						! AND THERE IS A PIGGY BACK QUOTA THEN
			SRCPTR[S0DEFSENDING] _ TRUE;			! SET A FLAG SO WE DON'T TRY TO UNDEFER
			UNDEFER( .SRCPTR, .PIGGYBACK)			! TRY TO UNDEFER SOME
									! ANY MORE UNTIL THE USER DOES ANOTHER
									! IMMEDIATE SEND

		    END
	    END;

	0

    END;
COMMENT;

! MSGCHN INSERTS A TERMINAL INTO THE OUTPUT CHAIN.  MSGOUT TAKES CARE OF THE REMOVAL

GLOBAL ROUTINE MSGCHN(DEST)=
	BEGIN
		REGISTER SRCPTR, OLAST;
		MAP FORMAT SRCPTR;
		MAP FORMAT OLAST;

		SRCPTR _ .DEST;		! PICK IT UP IN A REGISTER

		IF .SRCPTR[S0OPCHAIN] NEQ 0 THEN RETURN;	! RETURN IF ALREADY IN THE CHAIN
		IF (OLAST _ .LAST) EQL .SRCPTR THEN RETURN;	! RETURN IF ONLY IN CHAIN

		LAST _ .SRCPTR;		! THIS IS NOW THE LAST
		SRCPTR[S0OPPREV] _ .OLAST; ! OLD LAST IS THIS ONES PREVIOUS
		SRCPTR[S0OPNEXT] _ 0;	! NEW LAST HAS NO NEXT

		IF .OLAST EQL 0 THEN FIRST _ .SRCPTR ! IF ONLY, THEN FIRST TOO
			ELSE OLAST[S0OPNEXT] _ .SRCPTR; ! ELSE THIS IS ITS NEXT

		0
	END;
COMMENT;

!	MSGOUT SCHEDULES 1 OUTPUT FOR EACH TERMINAL DURING THE SCHEDULER LOOP

GLOBAL ROUTINE MSGOUT=
	BEGIN
		REGISTER SRCPTR,OPREV,ONEXT;
		MAP FORMAT SRCPTR;
		MAP FORMAT OPREV;
		MAP FORMAT ONEXT;

		SRCPTR _ .FIRST;	! GET FIRST TERMINAL IN OUTPUT CHAIN
		UNTIL .SRCPTR EQL 0 DO
		 BEGIN
			MSWRITE(.SRCPTR);	! TRY TO OUTPUT SOME DATA
			IF .SRCPTR[S0IGHS] NEQ 0 THEN SRCPTR _ .SRCPTR[S0OPNEXT]
			ELSE			! IF OUTPUT LAST GROUP, REMOVE FROM CHAIN
			BEGIN
			  OPREV _ .SRCPTR[S0OPPREV]; ! GET OLD PREVIOUS
			  ONEXT _ .SRCPTR[S0OPNEXT]; ! AND NEXT
			  SRCPTR[S0OPCHAIN] _ 0;     ! DISSOLVE LINKS
			  SRCPTR _ .ONEXT;	     ! SET UP FOR REST
			  IF .OPREV EQL 0 THEN       ! REMOVING THE FIRST
			    IF .ONEXT EQL 0 THEN OPCHAIN _ 0  ! REMOVING THE ONLY
			     ELSE
				BEGIN
				  FIRST _ .ONEXT;    ! RESET FIRST
				  ONEXT[S0OPPREV] _ 0 ! IT HAS NO PREVIOUS
				END
			   ELSE
				IF .ONEXT EQL 0 THEN	! REMOVING THE LAST
				   BEGIN
					LAST _ .OPREV;  ! RESET THE NEW LAST
					OPREV[S0OPNEXT] _ 0 ! IS HAS NO NEXT
				   END
				ELSE
				   BEGIN
					ONEXT[S0OPPREV] _ .OPREV; ! LINK REMAINING TOGETHER
					OPREV[S0OPNEXT] _ .ONEXT  ! TO COMPLETE THE CHAIN
				   END
			END
		 END
	END;
END;