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

📄 mscp_subr.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */u_longmscp_alloc_msg( event, rp )    u_long			event;    register REQB		*rp;{    register CONNB		*cp = rp->connb;    CSB				csb;    register CSB		*csp = ( CSB * )&csb;    register u_long		new_event = EV_MSGBUF;    /* ** TEMP **  Panic if this reqb already has a msg buffer.     */    if( rp->msgptr ) {	printf(" rp %x has non-zero msgptr %x\n", rp, rp->msgptr );	panic( "mscp_alloc_msg: double msg buffer allocation\n" );    }    /* Store the connection ID in the CSB.  If the message wait queue     * is empty, call SCS to allocate a message buffer.  If the allocation     * is successful, fill in the message buffer pointer in the request     * block, and return a message buffer available event to the caller.     */    Move_connid( cp->connid, csp->connid );    if(( cp->buffer_wq.flink == ( REQB * )&cp->buffer_wq.flink ) &&       ( scs_alloc_msg( csp ) == RET_SUCCESS )) {	    rp->msgptr = ( MSCP * )csp->buf;    /* If the wait queue is not empty or if allocation fails for any     * reason, insert the REQB at the tail of the message buffer wait     * queue for the connection, increment the wait reasons counter to     * stall new activity, and return a null event to the caller.     */    } else {	Insert_entry( rp->flink, cp->buffer_wq );	Incr_rwait( rp );	new_event = EV_NULL;    }    return( new_event );}/**//* * *   Name:	mscp_dealloc_msg - Deallocate a sequenced message buffer * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */voidmscp_dealloc_msg( rp )    register REQB		*rp;{    register REQB		*wrp;    register CONNB		*cp = rp->connb;    CSB				csb;    register CSB		*csp = ( CSB * )&csb;    u_long			scs_status;    /* Return the buffer to SCS.     */    Move_connid( cp->connid, csp->connid );    csp->buf = ( u_char * )rp->msgptr;    rp->msgptr = NULL;    if(( scs_status = scs_dealloc_msg( csp )) != RET_SUCCESS ) {	printf( "mscp_dealloc_msg: scs_status %x\n", scs_status );	panic( "mscp_dealloc_msg: bad connection state or ID\n" );    }    /* If there is a request packet waiting for a buffer, try to get     * the buffer that was just given back.  If the allocation request     * succeeds, restart the waiting thread with a message buffer      * available event.     */    if(( wrp = cp->buffer_wq.flink ) != ( REQB * )&cp->buffer_wq.flink ) {	if(( scs_status = scs_alloc_msg( csp )) == RET_SUCCESS ) {	    Remove_entry( wrp->flink );	    wrp->msgptr = ( MSCP * )csp->buf;	    mscp_dispatch( EV_MSGBUF, wrp );	    Decr_rwait( wrp );	}    }    return;}/**//* * *   Name:	mscp_service_bufferq - get buffers for waiting requests * *   Abstract:	This routine is called from mscp_timer to attempt to *		service requests that are waiting for message buffers. *		It is possible for a shared message buffer resource to *		become available on one connection without notification *		of waiting requests on other connections; this routine is *		periodically invoked to deal with that eventuality. * *   Inputs:    cp		    Connection block pointer. *		    buffer_wq.flink Map wait queue of request blocks. * *   Outputs:	 *		rp		    Request block pointer. *		    msgptr * * *   Return	NONE *   Values: */voidmscp_service_bufferq( cp )    register CONNB		*cp;{    CSB				csb;    register CSB		*csp = ( CSB * )&csb;    register REQB		*wrp;    u_long			status;    Move_connid( cp->connid, csp->connid );    /* Issue an allocate message request to SCS for each waiting REQB     * in turn until the queue is empty or until a request fails.  For     * each successful buffer allocation, do the wait queue bookkeeping     * and dispatch the REQB thread with the message buffer pointer     * in hand.     */    for( wrp = cp->buffer_wq.flink;	 wrp != (REQB * )&cp->buffer_wq.flink;	 wrp = cp->buffer_wq.flink ) {	if( scs_alloc_msg( csp ) == RET_SUCCESS ) {	    Remove_entry( wrp->flink );	    wrp->msgptr = ( MSCP * )csp->buf;	    mscp_dispatch( EV_MSGBUF, wrp );	    Decr_rwait( wrp );	} else {	    break;	}    }    return;}/**//* * *   Name:	mscp_map_buffer - map a data buffer * *   Abstract:	Allocate mapping resources for an MSCP data transfer *		operation. * *   Inputs:    rp			Request block pointer. * *   Outputs:	rp			Request block pointer. *		    lbhandle		Local buffer handle. * * *   Return	NONE *   Values: */u_longmscp_map_buffer( event, rp )    register REQB		*rp;{    register CONNB		*cp = rp->connb;    CSB				csb;    register CSB		*csp = ( CSB * )&csb;    u_long			new_event = EV_MAPPING;    /* ** TEMP **  Panic if this reqb already has a buffer handle.     */    if( !Test_bhandle( rp->lbhandle )) {	printf(" rp %x has non-zero buffer handle\n", rp );	panic( "mscp_map_buffer: double buffer handle allocation\n" );    }    /* *** TEMP ***     * Zero the buffer handle while we figure out who should really do it.     */    Zero_bhandle( csp->lbhandle );    /* Store the connection ID and the buf structure pointer in the CSB.     * If the map wait queue is empty, call SCS to map the buffer.  If     * the map request succeeds, store the local buffer handle in the     * request block and return a MAPPING event to the caller.     */    Move_connid( cp->connid, csp->connid );    csp->Sbh = rp->bufptr;    if(( cp->map_wq.flink == ( REQB * )&cp->map_wq.flink ) &&       ( scs_map_buf( csp ) == RET_SUCCESS )) {	    rp->lbhandle = csp->lbhandle;    /* If the map queue is not empty or the request fails for any reason,     * queue the request block, stall incoming requests and return a NULL     * event to the caller.     */    } else {	Insert_entry( rp->flink, cp->map_wq );	Incr_rwait( rp );	new_event = EV_NULL;    }    return( new_event );}/**//* * *   Name:	mscp_unmap_buffer - unmap a data buffer * *   Abstract:	Deallocate mapping resources after completion of *		an MSCP data transfer operation. * *   Inputs:    rp			Request block pointer. *		    lbhandle		Local buffer handle. * *   Outputs:	rp			Request block pointer. * * *   Return	NONE *   Values: */voidmscp_unmap_buffer( rp )    register REQB		*rp;{    register CONNB		*cp = rp->connb;    CSB				csb;    register CSB		*csp = ( CSB * )&csb;    register REQB		*wrp;    u_long			status;    Move_connid( cp->connid, csp->connid );    csp->lbhandle = rp->lbhandle;    csp->Sbh = rp->bufptr;    if(( status = scs_unmap_buf( csp )) == RET_SUCCESS ) {	/* Zero the buffer handle to prevent its inadvertant reuse.	 */	Zero_bhandle( rp->lbhandle );	/* If there are REQBs waiting for mapping resources, issue a map 	 * request for each one in turn until the wait queue is empty or	 * until a map request fails.	 */	for( wrp = cp->map_wq.flink;	     wrp != (REQB * )&cp->map_wq.flink;	     wrp = cp->map_wq.flink ) {	    csp->Sbh = wrp->bufptr;	    /* If the map request succeeds, do the wait queue bookkeeping	     * and dispatch the REQB thread with the local buffer handle	     * in hand.	     */	    if( scs_map_buf( csp ) == RET_SUCCESS ) {	        Remove_entry( wrp->flink );		wrp->lbhandle = csp->lbhandle;		mscp_dispatch( EV_MAPPING, wrp );		Decr_rwait( wrp );	    /* If the map request failed, break out of the for loop.	     */	    } else		break;	}        return;    } else	panic( "mscp_unmap_buffer: bad connection state or ID\n" );}/**//* * *   Name:	mscp_service_mapq - attempt to map waiting requests * *   Abstract:	This routine is called from mscp_timer to attempt to *		service requests that are waiting for mapping resources. *		It is possible for a shared mapping resource to become *		available on one connection without notification of *		waiting requests on other connections; this routine is *		periodically invoked to deal with that eventuality. * *   Inputs:    cp		    Connection block pointer. *		    map_wq.flink    Map wait queue of request blocks. *		        lbhandle    Local buffer handle. * *   Outputs:	 * * *   Return	NONE *   Values: */voidmscp_service_mapq( cp )    register CONNB		*cp;{    CSB				csb;    register CSB		*csp = ( CSB * )&csb;    register REQB		*wrp;    u_long			status;    Move_connid( cp->connid, csp->connid );    /* Issue a map request for each waiting REQB in turn until the queue     * is empty or until a map request fails.     */    for( wrp = cp->map_wq.flink;	 wrp != (REQB * )&cp->map_wq.flink;	 wrp = cp->map_wq.flink ) {	csp->Sbh = wrp->bufptr;	/* If the map request succeeds, do the wait queue bookkeeping	 * and dispatch the REQB thread with the local buffer handle	 * in hand.	 */	if( scs_map_buf( csp ) == RET_SUCCESS ) {	    Remove_entry( wrp->flink );	    wrp->lbhandle = csp->lbhandle;	    mscp_dispatch( EV_MAPPING, wrp );	    Decr_rwait( wrp );	/* If the map request failed, break out of the for loop.	 */	} else 	    break;    }    return;}/**//* * *   Name:	mscp_send_msg - Send an MSCP sequenced message * *   Abstract:	Fill in the appropriate CSB fields, and send a  *		MSCP sequenced message across a connection. * *   Inputs:	rp			Request block pointer * *   Outputs: * * *   Return	 *   Values: */u_longmscp_send_msg( rp )    register REQB		*rp;{    register CONNB		*cp = rp->connb;    CSB				csb;    register CSB		*csp = ( CSB * )&csb;    register u_long		status;    register u_long		new_event = EV_NULL;    /* Fill in the Communications services block portion of the     * request block with the connection ID, a pointer to the     * MSCP message buffer, the maximum MSCP command message size,     * and the message buffer disposition code.     */    Move_connid( cp->connid, csp->connid);    csp->buf = ( u_char * )rp->msgptr;    csp->size = sizeof( MSCP_CMDMSG );    csp->Disposal = RECEIVE_BUF;    /* If the credit wait queue is empty or the request is a connection     * management immediate message call SCS to send the message. If     * scs_send_msg returned success, queue the request to the active     * queue, and zero out the message buffer pointer to prevent its     * inadvertent reuse.     */    if(( cp->credit_wq.flink == ( REQB * )&cp->credit_wq.flink ||	 rp->flags.nocreditw ) &&	 ( status = scs_send_msg( csp )) == RET_SUCCESS ) {	Insert_entry( rp->flink, cp->active );	rp->msgptr = NULL;    /* If the request represents a connection management message, the     * scs_send_msg did not succeed.  Call SCS to add back the credit     * reserved for connection management, and call SCS to try again to     * send the message.  (The reserved credit must be added back here     * rather than above in order to avoid using the last credit for a     * non-immediate command, which would violate the MSCP spec.)  If     * either call fails, return a no credits event.  Otherwise, add the     * request to the active queue, and zero out the message buffer pointer     * to prevent its inadvertent reuse.     */    } else if( rp->flags.nocreditw ) {	if( scs_add_credit( csp ) == RET_SUCCESS  && 	    ( status = scs_send_msg( csp )) == RET_SUCCESS ) {	    cp->flags.need_cr = 1;	    Insert_entry( rp->flink, cp->active );	    rp->msgptr = NULL;	} else {	    new_event = EV_NOCREDITS;	}    /* The credit wait queue isn't empty or scs_send_msg returned an     * error on a non privileged request. Add the request to the credit     * wait queue and increment the resource wait count for the unit.     */    } else {	Insert_entry( rp->flink, cp->credit_wq );	Incr_rwait( rp );    }    /* Return status to the caller.     */    return( new_event );}/**//* * *   Name:	mscp_service_creditq - service requests in credit wait * *   Abstract:	This routine is called from mscp_control to service *		requests in the credit wait queue. * *   Inputs:    cp		    Connection block pointer. *		    credit_wq.flink Map wait queue of request blocks. * *   Outputs:	 * * *   Return	NONE *   Values: */voidmscp_service_creditq( rp )    register REQB		*rp;{    register CONNB		*cp = rp->connb;    CSB				csb;    register CSB		*csp = ( CSB * )&csb;    u_long			status;    /* If the connection management reserved credit has been expended,     * reserve it again.     */    if( cp->flags.need_cr ) 	mscp_reserve_credit( rp );    /* Issue a send message for each waiting REQB in turn until the queue     * is empty or until a send message fails.     */    for( rp = cp->credit_wq.flink;	 rp != (REQB * )&cp->credit_wq.flink;	 rp = cp->credit_wq.flink ) {	/* Fill in the CSB request block with the connection ID,	 * a pointer to the MSCP message buffer, the maximum MSCP	 * command message size, and the message buffer disposition	 * code.	 */

⌨️ 快捷键说明

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