📄 mscp_subr.c
字号:
* * 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 + -