Convert async I/O queues to standard lists.

This commit is contained in:
Alexandre Julliard 2005-02-24 17:06:31 +00:00
parent 91fc881d1f
commit dd81ac50a9
5 changed files with 74 additions and 88 deletions

View File

@ -991,10 +991,23 @@ struct async
void *sb;
struct timeval when;
struct timeout_user *timeout;
struct async *next;
struct async **head;
struct list entry;
};
/* notifies client thread of new status of its async request */
/* destroys the server side of it */
static void async_terminate( struct async *async, int status )
{
thread_queue_apc( async->thread, NULL, async->apc, APC_ASYNC_IO,
1, async->user, async->sb, (void *)status );
if (async->timeout) remove_timeout_user( async->timeout );
async->timeout = NULL;
list_remove( &async->entry );
release_object( async->thread );
free( async );
}
/* cb for timeout on an async request */
static void async_callback(void *private)
{
@ -1006,12 +1019,10 @@ static void async_callback(void *private)
}
/* create an async on a given queue of a fd */
struct async *create_async(struct fd *fd, struct thread *thread,
int timeout, struct async **head,
struct async *create_async(struct fd *fd, struct thread *thread, int timeout, struct list *queue,
void *io_apc, void *io_user, void* io_sb)
{
struct async *async = mem_alloc( sizeof(struct async) );
struct async **p;
if (!async) return NULL;
@ -1020,11 +1031,8 @@ struct async *create_async(struct fd *fd, struct thread *thread,
async->apc = io_apc;
async->user = io_user;
async->sb = io_sb;
async->head = head;
async->next = NULL;
for (p = head; *p; p = &(*p)->next);
*p = async;
list_add_tail( queue, &async->entry );
if (timeout)
{
@ -1037,29 +1045,11 @@ struct async *create_async(struct fd *fd, struct thread *thread,
return async;
}
/* notifies client thread of new status of its async request */
/* destroys the server side of it */
void async_terminate( struct async *async, int status )
/* terminate the async operation at the head of the queue */
void async_terminate_head( struct list *queue, int status )
{
struct async** p;
thread_queue_apc( async->thread, NULL, async->apc, APC_ASYNC_IO,
1, async->user, async->sb, (void *)status );
if (async->timeout) remove_timeout_user( async->timeout );
async->timeout = NULL;
for (p = async->head; *p; p = &(*p)->next)
{
if (*p == async)
{
*p = async->next;
break;
}
}
release_object( async->thread );
free( async );
struct list *ptr = list_head( queue );
if (ptr) async_terminate( LIST_ENTRY( ptr, struct async, entry ), status );
}
/****************************************************************/

View File

@ -57,8 +57,8 @@ struct file
struct fd *fd; /* file descriptor for this file */
unsigned int access; /* file access (GENERIC_READ/WRITE) */
unsigned int options; /* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */
struct async *read_q;
struct async *write_q;
struct list read_q;
struct list write_q;
};
static void file_dump( struct object *obj, int verbose );
@ -160,10 +160,8 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
file->access = access;
file->options = options;
if (is_overlapped( file ))
{
file->read_q = file->write_q = NULL;
}
list_init( &file->read_q );
list_init( &file->write_q );
/* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */
if (!(file->fd = alloc_fd( &file_fd_ops, &file->obj )) ||
@ -237,14 +235,14 @@ static void file_poll_event( struct fd *fd, int event )
assert( file->obj.ops == &file_ops );
if (is_overlapped( file ))
{
if ( file->read_q && (POLLIN & event) )
if (!list_empty( &file->read_q ) && (POLLIN & event) )
{
async_terminate( file->read_q, STATUS_ALERTED );
async_terminate_head( &file->read_q, STATUS_ALERTED );
return;
}
if ( file->write_q && (POLLOUT & event) )
if (!list_empty( &file->write_q ) && (POLLOUT & event) )
{
async_terminate( file->write_q, STATUS_ALERTED );
async_terminate_head( &file->write_q, STATUS_ALERTED );
return;
}
}
@ -271,7 +269,7 @@ static void file_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
int type, int count )
{
struct file *file = get_fd_user( fd );
struct async **head;
struct list *queue;
int events;
assert( file->obj.ops == &file_ops );
@ -285,17 +283,17 @@ static void file_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
switch (type)
{
case ASYNC_TYPE_READ:
head = &file->read_q;
queue = &file->read_q;
break;
case ASYNC_TYPE_WRITE:
head = &file->write_q;
queue = &file->write_q;
break;
default:
set_error( STATUS_INVALID_PARAMETER );
return;
}
if (!create_async( fd, current, 0, head, apc, user, iosb ))
if (!create_async( fd, current, 0, queue, apc, user, iosb ))
return;
/* Check if the new pending request can be served immediately */

View File

@ -112,12 +112,12 @@ extern struct object *create_serial( struct fd *fd, unsigned int options );
/* async I/O functions */
extern struct async *create_async( struct fd *fd, struct thread *thread, int timeout,
struct async **head, void *, void *, void *);
extern void async_terminate( struct async *async, int status );
struct list *queue, void *, void *, void *);
extern void async_terminate_head( struct list *queue, int status );
static inline void async_terminate_queue( struct async **head, int status )
static inline void async_terminate_queue( struct list *queue, int status )
{
while (*head) async_terminate( *head, status );
while (!list_empty( queue )) async_terminate_head( queue, status );
}
#endif /* __WINE_SERVER_FILE_H */

View File

@ -83,9 +83,9 @@ struct serial
struct termios original;
struct async *read_q;
struct async *write_q;
struct async *wait_q;
struct list read_q;
struct list write_q;
struct list wait_q;
/* FIXME: add dcb, comm status, handler module, sharing */
};
@ -145,7 +145,9 @@ struct object *create_serial( struct fd *fd, unsigned int options )
serial->writeconst = 0;
serial->eventmask = 0;
serial->commerror = 0;
serial->read_q = serial->write_q = serial->wait_q = NULL;
list_init( &serial->read_q );
list_init( &serial->write_q );
list_init( &serial->wait_q );
if (!(serial->fd = create_anonymous_fd( &serial_fd_ops, unix_fd, &serial->obj )))
{
release_object( serial );
@ -188,9 +190,9 @@ static int serial_get_poll_events( struct fd *fd )
int events = 0;
assert( serial->obj.ops == &serial_ops );
if (serial->read_q) events |= POLLIN;
if (serial->write_q) events |= POLLOUT;
if (serial->wait_q) events |= POLLIN;
if (!list_empty( &serial->read_q )) events |= POLLIN;
if (!list_empty( &serial->write_q )) events |= POLLOUT;
if (!list_empty( &serial->wait_q )) events |= POLLIN;
/* fprintf(stderr,"poll events are %04x\n",events); */
@ -221,14 +223,14 @@ static void serial_poll_event(struct fd *fd, int event)
/* fprintf(stderr,"Poll event %02x\n",event); */
if (serial->read_q && (POLLIN & event) )
async_terminate( serial->read_q, STATUS_ALERTED );
if (!list_empty( &serial->read_q ) && (POLLIN & event) )
async_terminate_head( &serial->read_q, STATUS_ALERTED );
if (serial->write_q && (POLLOUT & event) )
async_terminate( serial->write_q, STATUS_ALERTED );
if (!list_empty( &serial->write_q ) && (POLLOUT & event) )
async_terminate_head( &serial->write_q, STATUS_ALERTED );
if (serial->wait_q && (POLLIN & event) )
async_terminate( serial->wait_q, STATUS_ALERTED );
if (!list_empty( &serial->wait_q ) && (POLLIN & event) )
async_terminate_head( &serial->wait_q, STATUS_ALERTED );
set_fd_events( fd, serial_get_poll_events(fd) );
}
@ -237,7 +239,7 @@ static void serial_queue_async( struct fd *fd, void *apc, void *user, void *iosb
int type, int count )
{
struct serial *serial = get_fd_user( fd );
struct async **head;
struct list *queue;
int timeout;
int events;
@ -246,15 +248,15 @@ static void serial_queue_async( struct fd *fd, void *apc, void *user, void *iosb
switch (type)
{
case ASYNC_TYPE_READ:
head = &serial->read_q;
queue = &serial->read_q;
timeout = serial->readconst + serial->readmult*count;
break;
case ASYNC_TYPE_WAIT:
head = &serial->wait_q;
queue = &serial->wait_q;
timeout = 0;
break;
case ASYNC_TYPE_WRITE:
head = &serial->write_q;
queue = &serial->write_q;
timeout = serial->writeconst + serial->writemult*count;
break;
default:
@ -262,7 +264,7 @@ static void serial_queue_async( struct fd *fd, void *apc, void *user, void *iosb
return;
}
if (!create_async( fd, current, timeout, head, apc, user, iosb ))
if (!create_async( fd, current, timeout, queue, apc, user, iosb ))
return;
/* Check if the new pending request can be served immediately */

View File

@ -81,8 +81,8 @@ struct sock
obj_handle_t wparam; /* message wparam (socket handle) */
int errors[FD_MAX_EVENTS]; /* event errors */
struct sock *deferred; /* socket that waits for a deferred accept */
struct async *read_q; /* Queue for asynchronous reads */
struct async *write_q; /* Queue for asynchronous writes */
struct list read_q; /* queue for asynchronous reads */
struct list write_q; /* queue for asynchronous writes */
};
static void sock_dump( struct object *obj, int verbose );
@ -237,16 +237,16 @@ static void sock_wake_up( struct sock *sock, int pollev )
if ( sock->flags & WSA_FLAG_OVERLAPPED )
{
if ( pollev & (POLLIN|POLLPRI) && sock->read_q )
if ( pollev & (POLLIN|POLLPRI) && !list_empty( &sock->read_q ))
{
if (debug_level) fprintf( stderr, "activating read queue for socket %p\n", sock );
async_terminate( sock->read_q, STATUS_ALERTED );
async_terminate_head( &sock->read_q, STATUS_ALERTED );
async_active = 1;
}
if ( pollev & POLLOUT && sock->write_q )
if ( pollev & POLLOUT && !list_empty( &sock->write_q ))
{
if (debug_level) fprintf( stderr, "activating write queue for socket %p\n", sock );
async_terminate( sock->write_q, STATUS_ALERTED );
async_terminate_head( &sock->write_q, STATUS_ALERTED );
async_active = 1;
}
}
@ -466,9 +466,9 @@ static int sock_get_poll_events( struct fd *fd )
/* listening, wait for readable */
return (sock->hmask & FD_ACCEPT) ? 0 : POLLIN;
if (mask & (FD_READ) || (sock->flags & WSA_FLAG_OVERLAPPED && sock->read_q))
if (mask & (FD_READ) || (sock->flags & WSA_FLAG_OVERLAPPED && !list_empty( &sock->read_q )))
ev |= POLLIN | POLLPRI;
if (mask & FD_WRITE || (sock->flags & WSA_FLAG_OVERLAPPED && sock->write_q))
if (mask & FD_WRITE || (sock->flags & WSA_FLAG_OVERLAPPED && !list_empty( &sock->write_q )))
ev |= POLLOUT;
/* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */
if ( sock->type == SOCK_STREAM && ( sock->mask & ~sock->hmask & FD_CLOSE) )
@ -496,9 +496,9 @@ static void sock_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
int type, int count )
{
struct sock *sock = get_fd_user( fd );
struct async **head;
struct list *queue;
int pollev;
assert( sock->obj.ops == &sock_ops );
if ( !(sock->flags & WSA_FLAG_OVERLAPPED) )
@ -510,11 +510,11 @@ static void sock_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
switch (type)
{
case ASYNC_TYPE_READ:
head = &sock->read_q;
queue = &sock->read_q;
sock->hmask &= ~FD_CLOSE;
break;
case ASYNC_TYPE_WRITE:
head = &sock->write_q;
queue = &sock->write_q;
break;
default:
set_error( STATUS_INVALID_PARAMETER );
@ -528,7 +528,7 @@ static void sock_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
}
else
{
if (!create_async( fd, current, 0, head, apc, user, iosb ))
if (!create_async( fd, current, 0, queue, apc, user, iosb ))
return;
}
@ -608,10 +608,8 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
release_object( sock );
return NULL;
}
if (sock->flags & WSA_FLAG_OVERLAPPED)
{
sock->read_q = sock->write_q = NULL;
}
list_init( &sock->read_q );
list_init( &sock->write_q );
sock_reselect( sock );
clear_error();
return &sock->obj;
@ -682,10 +680,8 @@ static struct sock *accept_socket( obj_handle_t handle )
release_object( sock );
return NULL;
}
if ( acceptsock->flags & WSA_FLAG_OVERLAPPED )
{
acceptsock->read_q = acceptsock->write_q = NULL;
}
list_init( &acceptsock->read_q );
list_init( &acceptsock->write_q );
}
clear_error();
sock->pmask &= ~FD_ACCEPT;