⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scs_protocol.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
 *		SCS protocol sequence timeout queue. * *		The CB is locked to synchronize access and to prevent deletion. *		Locking the CB also prevents PB deletion as required by PD *		routines which transmit messages.  Only those CBs retrieved by *		this routine from PB work queues are explicitly locked by it *		and these CBs are unlocked prior to exiting.  CBs provided to *		this routine must be locked EXTERNALLY and are never unlocked *		before exiting.  CBs are always indirectly locked through their *		CBVTEs.   * *		The PB is locked to synchronize access, to prevent deletion, *		and for PB insertion onto the SCS protocol sequence timeout *		queue.  PBs are always unlocked just prior to request *		transmission as required by PD routines which transmit *		messages in this particular case. */voidscs_request( request, cb, pb, scsbp )    register u_long	request;    register CB		*cb;    register PB		*pb;    register SCSH	*scsbp;{    register CBVTE	*cbvte;    static struct {	u_short	mtype;	u_short	mlength;	struct	{	    u_char credits	: 1;	    u_char conn_info	: 1;	    u_char		: 6;	} flags;    } format[ 5 ] = {	{ SCS_CONN_REQ,	   sizeof( CONN_REQ ),	  1,	1 },	{ SCS_ACCEPT_REQ,  sizeof( ACCEPT_REQ ),  1,	1 },	{ SCS_REJECT_REQ,  sizeof( REJECT_REQ ),  0,	0 },	{ SCS_DISCONN_REQ, sizeof( DISCONN_REQ ), 0,	0 },	{ SCS_CREDIT_REQ,  sizeof( CREDIT_REQ ),  1,	0 }	};    /* Servicing SCS requests and initiating transmission of SCS sequenced     * messages proceeds as follows:     *     *  1. Lock the PB.     *  2. Verify the path state.     *  3. Obtain both a CB on whose behalf the request is to be made and a     *	   port specific message buffer to contain the request as needed.     *  4. Lock the CB whenever it was obtained by this routine and not     *	   provided to it.     *  5. Format the SCS sequenced message according to the its type.     *  6. Unlock the PB.     *  7. Initiate sequenced message transmission.     *  8. Lock the PB.     *  9. Start a sanity check on this current protocol sequence provided the     *	   path is still open.     * 10. Unlock the PB.     * 11. Unlock the CB whenever it was obtained by this routine and not     *	   provided to it.     *     * Only failure of the path can result in a failure to verify the path     * state( Step 2 ).  Servicing of the current request is aborted and any     * message buffer provided to this routine is attached to the PB as its SCS     * send message buffer.  Provided CBs are not placed on the PB work queue     * because their requests would never be serviced anyway due to failure of     * the path.     *     * When obtaining CBs and message buffers( Step 3 ), the following two     * possibilities exist:     *     * 1. The message buffer is explicitly provided but the CB is not.     * 2. The CB is explicitly provided but the message buffer is not.     *     * The first possibility occurs when when servicing of a postponed request     * is to resume making use of the explicitly provided message buffer.  The     * very first CB on the PB's work queue is obtained( Step 3 ) and locked(     * Step 4 ).  The absence of connections with postponed requests or failure     * of the path immediately terminates next request processing.  The     * explicitly provided message buffer is attached to the PB as its SCS     * send message buffer and the PB is unlocked before returning.  The PB     * must always be unlocked and then re-locked after locking each CB in     * order to maintain the SCA locking hierarchy.  Cached PB addresses remain     * valid because possession of the SCA database lock prevents PB deletion.     *     * The second possibility occurs when servicing on behalf of a connection     * is directly requested.  The PB's SCS send message buffer is retrieved(     * Step 3 ).  Unavailability of this buffer forces postponement of the     * request by caching the request type and placing the CB on to the PB work     * queue.     *     * Sanity checks on current protocol sequences( Step 9 ) are initiated as     * follows:     *     * 1. Compute the maximum time interval for reception of the corresponding     *    response.     * 2. Place the PB on to the SCS protocol sequence timeout queue.     * 3. Schedule the SCS interval timer routine whenever the queue was     *    previously empty.     *     * PBs are removed from the SCS protocol sequence timeout queue when     * corresponding responses are received.  SCS assumes a path has failed if     * the proper response is not received before the PB's sanity interval     * timer expires and the path is crashed.     */    Lock_pb( pb )    if( pb->pinfo.state != PS_OPEN ) {	if( scsbp ) {	    pb->scs_msgbuf = scsbp;	}	Unlock_pb( pb )	return;    } else if( cb == NULL ) {	while( pb->scs_cb.flink != &pb->scs_cb ) {	    cb = Pos_to_cb( pb->scs_cb.flink, scs_cb );	    cbvte = Get_cbvte( cb->cinfo.lconnid );	    Unlock_pb( pb )	    Lock_cbvte( cbvte )	    Lock_pb( pb )	    if( pb->pinfo.state == PS_OPEN && &cb->scs_cb == pb->scs_cb.flink){		Remove_entry( cb->scs_cb )		request = cb->cinfo.cbstate;		cb->cinfo.cbstate = CB_NOT_WAIT;		break;	    } else {		Unlock_cbvte( cbvte )		if( pb->pinfo.state != PS_OPEN ) {		    break;		}	    }	}	if( request == CB_NOT_WAIT ) {	    pb->scs_msgbuf = scsbp;	    Unlock_pb( pb )	    return;	}    } else if(( scsbp = pb->scs_msgbuf )) {	pb->scs_msgbuf = NULL;	cbvte = NULL;    } else {	cb->cinfo.cbstate = request;	Insert_entry( cb->scs_cb, pb->scs_cb )	Unlock_pb( pb )	return;    }    if( request <= CB_MAX_PEND ) {	scsbp->mtype = format[ --request ].mtype;    } else {	( void )panic( SCSPANIC_SCSMSG );    }    if( format[ request ].flags.credits ) {	scsbp->credit = cb->cinfo.pend_rec_credit;	cb->cinfo.rec_credit += cb->cinfo.pend_rec_credit;	cb->cinfo.pend_rec_credit = 0;    } else {	scsbp->credit = 0;    }    Move_connid( cb->cinfo.rconnid, scsbp->rconnid )    Move_connid( cb->cinfo.lconnid, scsbp->sconnid )    if(( Reject_req( scsbp )->reason = cb->cinfo.reason )) {	cb->cinfo.reason = 0;    }    if( format[ request ].flags.conn_info ) {	Conn_req(  scsbp )->min_credit = cb->cinfo.min_snd_credit;	Move_name( cb->cinfo.rproc_name, Conn_req( scsbp )->rproc_name )	Move_name( cb->cinfo.lproc_name, Conn_req( scsbp )->sproc_name )	Move_name( cb->cinfo.lconn_data, Conn_req( scsbp )->sproc_data )    } else {	Conn_req( scsbp )->min_credit = 0;    }    if( pb->pinfo.status.sanity ) {	( void )panic( SCSPANIC_SANITY );    } else {	Unlock_pb( pb )	( void )( *cb->Send_msg )( cb->pccb,				   pb,				   scsbp,				   format[ request ].mlength,				   RECEIVE_BUF );	Lock_pb( pb )	if( pb->pinfo.state == PS_OPEN ) {	    pb->pinfo.status.sanity = 1;	    pb->pinfo.duetime = scs_sanity;	    Insert_entry( pb->timeout, scs_timeoutq )	    if( scs_timeoutq.flink == &scs_timeoutq ) {		( void )timeout( scs_timer, NULL, 1 );	    }	}    }    Unlock_pb( pb )    if( cbvte ) {	Unlock_cbvte( cbvte )    }}/*   Name:	scs_response	- Send SCS Sequenced Message Response * *   Abstract:	This routine initiates transmission of a SCS response over a *		specific path.  A SCS response is only transmitted following *		reception and processing of the corresponding SCS request. *		Five such responses are supported: * *		1. Response to a connection request *		2. Response to a connection acceptance request. *		3. Response to a connection rejection request. *		4. Response to a connection termination request. *		5. Response to a request for extension or withdrawal of send *		   credits. * *		SCS applies flow control to its own communication on a per path *		basis.  Only one SCS request is transmitted across each path at *		a given moment.  However, SCS responses may always be *		immediately transmitted because the message buffer containing *		the SCS request on the originating system is reserved for *		reception of its corresponding SCS response. * *		The message buffer containing the SCS response is always *		derived from recyclement of the message buffer containing the *		SCS request. * *   Inputs: * *   IPL_SCS			- Interrupt processor level *   scsbp			- Address of SCS header of message buffer *   pb				- Path Block pointer * *   Outputs: * *   IPL_SCS			- Interrupt processor level * *   SMP:	The SCA database is locked( EXTERNALLY ) to guarantee the *		validity of PB addresses and to prevent PB deletion. * *		The PB is locked to synchronize access to the path's current *		path state.  It is unlocked immediately following retrieval of *		the current path state as required by PD functions/routines *		which both transmit messages and add them to appropriate local *		port free pools in these particular cases. */voidscs_response( scsbp, pb )    register SCSH	*scsbp;    PB			*pb;{    CONNID		save_connid;    register u_long	state;    static u_short	rsp_lengths[] = {	sizeof( CONN_RSP ),	sizeof( ACCEPT_RSP ),	sizeof( REJECT_RSP ),	sizeof( DISCONN_RSP ),	sizeof( CREDIT_RSP )    };    /* The SCS response is formated from the SCS request and transmitted only     * if the path is currently open.  Otherwise the message buffer is added to     * the appropriate local port's free message pool or deallocated depending     * upon whether the path( but not the local port ) has failed.     *     * The PB is locked only for retrieval of the current path state because     * the interfaces to both the message transmission and message addition     * routines require it to be unlocked in this particular instance.     * Unlocking the PB does not present a problem for the following reasons:     *     * 1. It is not particularly crucial if the path state changes between the     *    time the PB is unlocked and the cached value is checked.  It is true     *    this could result in an attempt to transmit a SCS response on a     *	  failed path.  However, this possibility has always existed and there     *	  is no way to eliminate it.     *     * 2. It is acceptable to continue to reference PB contents even though it     *    the data structure is unlocked.  The cached PB address is valid     *	  because the SCA database is currently locked preventing PB deletion,     *    and the contents accessed are static.  This includes the path failure     *	  reason which can not change once set for a given path incarnation and     *	  is accessed only after the path has been found to have failed.     *     * NOTE: The SCS response message type is always 1 more then its     *	     corresponding SCS request message type.     *     * NOTE: The sending and receiving connection identification numbers of the     *	     SCS request are always the receiving and sending connection     *	     identification numbers of the corresponding SCS response.     */    if( scsbp->mtype > SCS_MAX_SCSMSG ) {	( void )panic( SCSPANIC_SCSMSG );    }    Lock_pb( pb )    state = pb->pinfo.state;    Unlock_pb( pb )    if( state == PS_OPEN ) {	++scsbp->mtype;	if( scsbp->mtype != SCS_CREDIT_RSP ) {	    scsbp->credit = 0;	}	Move_connid( scsbp->rconnid, save_connid )	Move_connid( scsbp->sconnid, scsbp->rconnid )	Move_connid( save_connid, scsbp->sconnid )	Accept_req( scsbp )->min_credit = 0;	( void )( *pb->Send_msg )( pb->pccb,				   pb,				   scsbp,				   rsp_lengths[(( scsbp->mtype - 1 ) >>1 )],				   RECEIVE_BUF );    } else if( state == PS_PATH_FAILURE && Port_failure( pb->pinfo.reason )) {	( void )( *pb->Dealloc_msg )( pb->pccb, scsbp );    } else {	( void )( *pb->Add_msg )( pb->pccb, scsbp );    }}/*   Name:	scs_timer	- SCS Protocol Interval Timer * *   Abstract:	This routine oversees all SCS timer related activities.  It is *		executed once per second per system but only when SCS requires *		some timer related function. * *		Timer related functions currently performed include: * *		1. Declaring SCS protocol sequence time outs on open paths. * *   Inputs: * *   IPL_SOFTCLOCK		- Interrupt processor level *   lk_scadb			- SCA database lock structure *   scs_timeoutq		- SCS protocol sequence timeout queue head * *   Outputs: * *   IPL_SOFTCLOCK		- Interrupt processor level * *   SMP:	The SCA database is locked for traversal of the SCS protocol *		sequence timeout queue and for removing PBs from this queue *		when it becomes necessary.  It also postpones premature PB *		deletion. * *		PBs are locked to synchronize access and for removing them from *		the SCS protocol sequence timeout queue when it becomes *		necessary.  PB locks are released before crashing the *		corresponding path. */voidscs_timer(){    register pbq	*qp;    register PB		*pb;    register u_long	save_ipl = Splscs();    /* Each timer interval the following sequence of actions occurs:     *     * 1. IPL is synchronized to IPL_SCS.     * 2. The SCA database is locked.     * 3. The SCS protocol sequence timeout queue of PBs is scanned and the     *	  corresponding paths crashed on protocol timer expirations.  Each PB     *	  is locked for the duration of its check.     * 4. The next invocation of the SCS interval timer is scheduled provided     *	  the SCS protocol sequence timeout queue is not empty following     *	  processing.     * 5. The SCA database is unlocked.     * 6. IPL is restored.     */    Lock_scadb()    for( qp = scs_timeoutq.flink; qp != &scs_timeoutq; ) {	pb = Pos_to_pb( qp, timeout );	qp = qp->flink;	Lock_pb( pb )	if( !pb->pinfo.status.sanity ) {	    ( void )panic( SCSPANIC_SANITY );	} else if( --pb->pinfo.duetime == 0 ) {	    Remove_scs_timeoutq( pb )	    ( void )( *pb->Crash_path )( pb->pccb, pb, E_TIMEOUT, 0, NULL );	}	Unlock_pb( pb )    }    if( scs_timeoutq.flink != &scs_timeoutq ) {	( void )timeout( scs_timer, NULL, hz );    }    Unlock_scadb()    ( void )splx( save_ipl );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -