📄 rpcclient.c
字号:
_cache_copyback ( p_shadow_result_buf, result_buf_len );
}
return &shadow_block->header.command;
}
/*--------------------------- The Screwd Protocol Stuff ----------------------*/
/*
* Termination handler, which will be called by the sender
* of a host request after this request has completed.
* it contains some postprocessing, plus follow- up code
* for the three- stage read engine.
* The cache invalidation of the command buffer already
* has been done in the notification routine; invalidation
* of a result buffer, when present, must still be done.
*/
static void termination_handler( HostCall_command *command )
{
ShadowBlock *shadow_block = (ShadowBlock*)command->target_link;
HostCall_command *shadow_command = &shadow_block->header.command;
Int32 result_buf_len = shadow_block->header.result_buf_len;
Int32 result_buf_offset = shadow_block->header.result_buf_offset;
Address *pp_shadow_result_buf = (Pointer)(((Address)shadow_command)+result_buf_offset);
Address *pp_command_result_buf = (Pointer)(((Address)command )+result_buf_offset);
Address p_shadow_result_buf = *pp_shadow_result_buf;
Address p_command_result_buf;
Bool has_result_buffer = result_buf_len > 0;
Int32 readsize, reqsize;
/*
* Check if there is a result buffer to be copied
* back to the original command. In principle,
* this can be concluded from the result buffer size (!=0)
* However, some commands (getenv) may return Null,
* in which case the original buffer pointer is cleared:
*/
if (p_shadow_result_buf == Null) has_result_buffer= Null;
if ( has_result_buffer ) {
p_command_result_buf = *pp_command_result_buf;
_cache_invalidate( p_shadow_result_buf, result_buf_len );
memcpy( p_command_result_buf, p_shadow_result_buf, result_buf_len );
}
/*
* Accumulate the data which has been read in case
* of a read command, and flag premature termination
* when not all requested data could be returned:
*/
switch (command->code) {
case READ_PHASE_2:
_cache_invalidate(
shadow_command->parameters.read_args.buf,
shadow_command->parameters.read_args.retval
);
/*FALLTHROUGH*/
case READ_PHASE_1:
case READ_PHASE_3:
if (shadow_command->notification_status == HostCall_ERROR) {
readsize= 0;
} else {
readsize= shadow_command->parameters.read_args.retval;
}
reqsize= shadow_command->parameters.read_args.nbyte;
shadow_command->code= command->code;
shadow_command->parameters.read_args.retval = command->parameters.read_args.retval + readsize;
shadow_command->parameters.read_args.nbyte = command->parameters.read_args.nbyte - readsize;
if (has_result_buffer) {
/*
* Adapted read buffer start, to be patched
* into original command buffer after this switch:
*/
p_command_result_buf += readsize;
} else {
/*
* Adapted read buffer start, to be copied with
* rest of shadow command into original command
* buffer after this switch:
*/
shadow_command->parameters.read_args.buf = (Pointer)((Address)command->parameters.read_args.buf + readsize);
}
}
/*
* Copy the contents of the returned command buffer
* (returned results, original function code, and unmodified
* original contents) back to the command buffer.
* However, do not destroy the result buffer pointer.
* Afterwards: free up all allocated memory.
* NB: note that the buffer pointer is also implicitly
* incremented for read commands (see code in above switch):
*/
memcpy(command, shadow_command, sizeof(HostCall_command));
if (has_result_buffer) {
*pp_command_result_buf= p_command_result_buf;
}
_cache_free( shadow_block );
/*
* In case of read command, do the
* next read in recursion:
*/
switch (command->code) {
case READ_PHASE_2:
case READ_PHASE_1:
if (readsize < reqsize) {
command->code= HostCall_READ;
} else {
_HostCall_send(command);
}
break;
case READ_PHASE_3:
command->code= HostCall_READ;
break;
}
}
/*--------------------------- Interface Functions-----------------------------*/
/*
* Service request routine to host:
*/
void _HostCall_host_send( HostCall_command *command )
{
HostCall_command *shadow_command;
Address next_chunk_start;
Int32 chunk_len;
Int32 nbyte;
#define RESULT_BUFF_DEF(command,result_buf_len,result_buf,preserve) \
make_shadow(command,result_buf_len,result_buf,preserve)
#define XFER_DATA(addr,len) \
_cache_copyback(addr,len)
#define XFER_DATA2(addr,len) \
_cache_copyback(addr,len)
#undef SERIAL_RPC
#include "RPCSend.c"
if (command->status != HostCall_DONE)
{
if (shadow_command == Null)
{
command->status = HostCall_ERROR;
}
else
{
if (_HostIF_send (shadow_command))
{
if (shadow_command->status == HostCall_DONE)
{
command->status = HostCall_DONE;
_cache_invalidate
(
shadow_command,
sizeof (ShadowBlockHeader)
);
}
}
else
{
_cache_free (command->target_link);
command->status = HostCall_ERROR;
}
}
}
}
/*
* Reply routine which handles messages from host;
* such messages always are notifications of served
* commands; invalidate the cache pages in which the
* result buffer plus attached administration is mapped.
* This allows inspection for further processing without
* reading stale data; invalidation of any result buffer
* attached to the command is done in the termination
* handler.
*/
void _RPCClient_notify ( HostCall_command *command )
{
_cache_invalidate( command, sizeof( ShadowBlockHeader ) );
command->notification_handler( command );
}
/*--------------------------- Initialisation / Termination -------------------*/
Bool _HostCall_init( void )
{
return _HostIF_init();
}
void _HostCall_term( void )
{
_HostIF_term();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -