Further server optimizations:
- merged request and reply structures
- build requests directly into the buffer to avoid a copy
diff --git a/server/console.c b/server/console.c
index a4792b8..4790f90 100644
--- a/server/console.c
+++ b/server/console.c
@@ -69,7 +69,7 @@
static void screen_buffer_destroy( struct object *obj );
/* common routine */
-static int console_get_info( struct object *obj, struct get_file_info_reply *reply );
+static int console_get_info( struct object *obj, struct get_file_info_request *req );
static const struct object_ops console_input_ops =
{
@@ -183,12 +183,11 @@
return 1;
}
-static int set_console_fd( int handle, int fd, int pid )
+static int set_console_fd( int handle, int fd_in, int fd_out, int pid )
{
struct console_input *input;
struct screen_buffer *output;
struct object *obj;
- int fd_in, fd_out;
if (!(obj = get_handle_obj( current->process, handle, 0, NULL )))
return 0;
@@ -215,21 +214,6 @@
assert( !input->obj.head );
assert( !output->obj.head );
- if ((fd_in = dup(fd)) == -1)
- {
- file_set_error();
- release_object( input );
- release_object( output );
- return 0;
- }
- if ((fd_out = dup(fd)) == -1)
- {
- file_set_error();
- close( fd_in );
- release_object( input );
- release_object( output );
- return 0;
- }
unregister_select_user( &input->select );
unregister_select_user( &output->select );
close( input->select.fd );
@@ -244,25 +228,21 @@
return 1;
}
-static int get_console_mode( int handle, int *mode )
+static int get_console_mode( int handle )
{
struct object *obj;
int ret = 0;
- if (!(obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL )))
- return 0;
- if (obj->ops == &console_input_ops)
+ if ((obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL )))
{
- *mode = ((struct console_input *)obj)->mode;
- ret = 1;
+ if (obj->ops == &console_input_ops)
+ ret = ((struct console_input *)obj)->mode;
+ else if (obj->ops == &screen_buffer_ops)
+ ret = ((struct screen_buffer *)obj)->mode;
+ else
+ set_error( ERROR_INVALID_HANDLE );
+ release_object( obj );
}
- else if (obj->ops == &screen_buffer_ops)
- {
- *mode = ((struct screen_buffer *)obj)->mode;
- ret = 1;
- }
- else set_error( ERROR_INVALID_HANDLE );
- release_object( obj );
return ret;
}
@@ -316,21 +296,6 @@
return 1;
}
-/* get misc console information (output handle only) */
-static int get_console_info( int handle, struct get_console_info_reply *reply, const char **title )
-{
- struct screen_buffer *console;
- if (!(console = (struct screen_buffer *)get_handle_obj( current->process, handle,
- GENERIC_READ, &screen_buffer_ops )))
- return 0;
- reply->cursor_size = console->cursor_size;
- reply->cursor_visible = console->cursor_visible;
- reply->pid = console->pid;
- *title = console->title;
- release_object( console );
- return 1;
-}
-
/* add input events to a console input queue */
static int write_console_input( int handle, int count, INPUT_RECORD *records )
{
@@ -355,16 +320,16 @@
}
/* retrieve a pointer to the console input records */
-static int read_console_input( int handle, int count, int flush )
+static int read_console_input( int handle, int count, INPUT_RECORD *rec, int max, int flush )
{
struct console_input *console;
- struct read_console_input_reply *reply = push_reply_data( current, sizeof(*reply) );
if (!(console = (struct console_input *)get_handle_obj( current->process, handle,
GENERIC_READ, &console_input_ops )))
return -1;
if ((count < 0) || (count > console->recnum)) count = console->recnum;
- add_reply_data( current, console->records, count * sizeof(INPUT_RECORD) );
+ if (count > max) count = max;
+ memcpy( rec, console->records, count * sizeof(INPUT_RECORD) );
if (flush)
{
int i;
@@ -440,10 +405,18 @@
return dup( console->select.fd );
}
-static int console_get_info( struct object *obj, struct get_file_info_reply *reply )
+static int console_get_info( struct object *obj, struct get_file_info_request *req )
{
- memset( reply, 0, sizeof(*reply) );
- reply->type = FILE_TYPE_CHAR;
+ req->type = FILE_TYPE_CHAR;
+ req->attr = 0;
+ req->access_time = 0;
+ req->write_time = 0;
+ req->size_high = 0;
+ req->size_low = 0;
+ req->links = 0;
+ req->index_high = 0;
+ req->index_low = 0;
+ req->serial = 0;
return 1;
}
@@ -517,14 +490,12 @@
unregister_select_user( &console->select );
close( console->select.fd );
if (console->input) console->input->output = NULL;
- if (console->pid) kill( console->pid, SIGTERM );
if (console->title) free( console->title );
}
/* allocate a console for the current process */
DECL_HANDLER(alloc_console)
{
- struct alloc_console_reply *reply = push_reply_data( current, sizeof(*reply) );
int in = -1, out = -1;
if (!alloc_console( current->process )) goto done;
@@ -541,8 +512,8 @@
free_console( current->process );
done:
- reply->handle_in = in;
- reply->handle_out = out;
+ req->handle_in = in;
+ req->handle_out = out;
}
/* free the console of the current process */
@@ -554,40 +525,61 @@
/* open a handle to the process console */
DECL_HANDLER(open_console)
{
- struct open_console_reply *reply = push_reply_data( current, sizeof(*reply) );
struct object *obj= req->output ? current->process->console_out : current->process->console_in;
- if (obj) reply->handle = alloc_handle( current->process, obj, req->access, req->inherit );
+ if (obj) req->handle = alloc_handle( current->process, obj, req->access, req->inherit );
else set_error( ERROR_ACCESS_DENIED );
}
/* set info about a console (output only) */
DECL_HANDLER(set_console_info)
{
- size_t len = get_req_strlen();
- set_console_info( req->handle, req, get_req_data( len + 1 ), len );
+ size_t len = get_req_strlen( req->title );
+ set_console_info( req->handle, req, req->title, len );
}
/* get info about a console (output only) */
DECL_HANDLER(get_console_info)
{
- struct get_console_info_reply *reply = push_reply_data( current, sizeof(*reply) );
- const char *title;
- get_console_info( req->handle, reply, &title );
- if (title) add_reply_data( current, title, strlen(title) + 1 );
+ struct screen_buffer *console;
+ if ((console = (struct screen_buffer *)get_handle_obj( current->process, req->handle,
+ GENERIC_READ, &screen_buffer_ops )))
+ {
+ req->cursor_size = console->cursor_size;
+ req->cursor_visible = console->cursor_visible;
+ req->pid = console->pid;
+ strcpy( req->title, console->title ? console->title : "" );
+ release_object( console );
+ }
}
/* set a console fd */
DECL_HANDLER(set_console_fd)
{
- set_console_fd( req->handle, fd, req->pid );
+ struct object *obj;
+ int fd_in, fd_out;
+
+ if (!(obj = get_handle_obj( current->process, req->file_handle,
+ GENERIC_READ | GENERIC_WRITE, NULL ))) return;
+ if ((fd_in = obj->ops->get_read_fd( obj )) == -1)
+ {
+ release_object( obj );
+ return;
+ }
+ fd_out = obj->ops->get_write_fd( obj );
+ release_object( obj );
+ if (fd_out != -1)
+ {
+ if (set_console_fd( req->handle, fd_in, fd_out, req->pid )) return;
+ close( fd_out );
+ }
+ close( fd_in );
}
/* get a console mode (input or output) */
DECL_HANDLER(get_console_mode)
{
- struct get_console_mode_reply *reply = push_reply_data( current, sizeof(*reply) );
- get_console_mode( req->handle, &reply->mode );
+ req->mode = get_console_mode( req->handle );
}
/* set a console mode (input or output) */
@@ -599,18 +591,17 @@
/* add input records to a console input queue */
DECL_HANDLER(write_console_input)
{
- struct write_console_input_reply *reply = push_reply_data( current, sizeof(*reply) );
+ int max = get_req_size( req + 1, sizeof(INPUT_RECORD) );
+ int count = req->count;
- if (check_req_data( req->count * sizeof(INPUT_RECORD)))
- {
- INPUT_RECORD *records = get_req_data( req->count * sizeof(INPUT_RECORD) );
- reply->written = write_console_input( req->handle, req->count, records );
- }
- else fatal_protocol_error( "write_console_input: bad length" );
+ if (count > max) count = max;
+ req->written = write_console_input( req->handle, count, (INPUT_RECORD *)(req + 1) );
}
/* fetch input records from a console input queue */
DECL_HANDLER(read_console_input)
{
- read_console_input( req->handle, req->count, req->flush );
+ int max = get_req_size( req + 1, sizeof(INPUT_RECORD) );
+ req->read = read_console_input( req->handle, req->count, (INPUT_RECORD *)(req + 1),
+ max, req->flush );
}