Commit 37804f1e authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

server: Keep ifchange queue through sock object life time.

parent 54234b8a
...@@ -123,8 +123,8 @@ static void sock_dump( struct object *obj, int verbose ); ...@@ -123,8 +123,8 @@ static void sock_dump( struct object *obj, int verbose );
static int sock_signaled( struct object *obj, struct wait_queue_entry *entry ); static int sock_signaled( struct object *obj, struct wait_queue_entry *entry );
static struct fd *sock_get_fd( struct object *obj ); static struct fd *sock_get_fd( struct object *obj );
static void sock_destroy( struct object *obj ); static void sock_destroy( struct object *obj );
static struct async_queue *sock_get_ifchange_q( struct sock *sock ); static struct object *sock_get_ifchange( struct sock *sock );
static void sock_destroy_ifchange_q( struct sock *sock ); static void sock_release_ifchange( struct sock *sock );
static int sock_get_poll_events( struct fd *fd ); static int sock_get_poll_events( struct fd *fd );
static void sock_poll_event( struct fd *fd, int event ); static void sock_poll_event( struct fd *fd, int event );
...@@ -537,7 +537,6 @@ static enum server_fd_type sock_get_fd_type( struct fd *fd ) ...@@ -537,7 +537,6 @@ static enum server_fd_type sock_get_fd_type( struct fd *fd )
static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
{ {
struct sock *sock = get_fd_user( fd ); struct sock *sock = get_fd_user( fd );
struct async_queue *ifchange_q;
assert( sock->obj.ops == &sock_ops ); assert( sock->obj.ops == &sock_ops );
...@@ -549,8 +548,9 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) ...@@ -549,8 +548,9 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
set_error( STATUS_CANT_WAIT ); set_error( STATUS_CANT_WAIT );
return 0; return 0;
} }
if (!(ifchange_q = sock_get_ifchange_q( sock ))) return 0; if (!sock_get_ifchange( sock )) return 0;
queue_async( ifchange_q, async ); if (!sock->ifchange_q && !(sock->ifchange_q = create_async_queue( sock->fd ))) return 0;
queue_async( sock->ifchange_q, async );
set_error( STATUS_PENDING ); set_error( STATUS_PENDING );
return 1; return 1;
default: default:
...@@ -618,10 +618,11 @@ static void sock_destroy( struct object *obj ) ...@@ -618,10 +618,11 @@ static void sock_destroy( struct object *obj )
if ( sock->deferred ) if ( sock->deferred )
release_object( sock->deferred ); release_object( sock->deferred );
async_wake_up( sock->ifchange_q, STATUS_CANCELLED );
sock_release_ifchange( sock );
free_async_queue( sock->read_q ); free_async_queue( sock->read_q );
free_async_queue( sock->write_q ); free_async_queue( sock->write_q );
async_wake_up( sock->ifchange_q, STATUS_CANCELLED ); free_async_queue( sock->ifchange_q );
sock_destroy_ifchange_q( sock );
if (sock->event) release_object( sock->event ); if (sock->event) release_object( sock->event );
if (sock->fd) if (sock->fd)
{ {
...@@ -1038,9 +1039,9 @@ static void ifchange_wake_up( struct object *obj, unsigned int status ) ...@@ -1038,9 +1039,9 @@ static void ifchange_wake_up( struct object *obj, unsigned int status )
{ {
struct sock *sock = LIST_ENTRY( ptr, struct sock, ifchange_entry ); struct sock *sock = LIST_ENTRY( ptr, struct sock, ifchange_entry );
assert( sock->ifchange_q ); assert( sock->ifchange_obj );
async_wake_up( sock->ifchange_q, status ); /* issue ifchange notification for the socket */ async_wake_up( sock->ifchange_q, status ); /* issue ifchange notification for the socket */
sock_destroy_ifchange_q( sock ); /* remove socket from list and decrement ifchange refcount */ sock_release_ifchange( sock ); /* remove socket from list and decrement ifchange refcount */
} }
} }
...@@ -1145,40 +1146,30 @@ static void ifchange_add_sock( struct object *obj, struct sock *sock ) ...@@ -1145,40 +1146,30 @@ static void ifchange_add_sock( struct object *obj, struct sock *sock )
} }
/* create a new ifchange queue for a specific socket or, if one already exists, reuse the existing one */ /* create a new ifchange queue for a specific socket or, if one already exists, reuse the existing one */
static struct async_queue *sock_get_ifchange_q( struct sock *sock ) static struct object *sock_get_ifchange( struct sock *sock )
{ {
struct object *ifchange; struct object *ifchange;
if (sock->ifchange_q) /* reuse existing ifchange_q for this socket */ if (sock->ifchange_obj) /* reuse existing ifchange_obj for this socket */
return sock->ifchange_q; return sock->ifchange_obj;
if (!(ifchange = get_ifchange())) if (!(ifchange = get_ifchange()))
return NULL; return NULL;
/* create the ifchange notification queue */
sock->ifchange_q = create_async_queue( sock->fd );
if (!sock->ifchange_q)
{
release_object( ifchange );
set_error( STATUS_NO_MEMORY );
return NULL;
}
/* add the socket to the ifchange notification list */ /* add the socket to the ifchange notification list */
ifchange_add_sock( ifchange, sock ); ifchange_add_sock( ifchange, sock );
sock->ifchange_obj = ifchange; sock->ifchange_obj = ifchange;
return sock->ifchange_q; return ifchange;
} }
/* destroy an existing ifchange queue for a specific socket */ /* destroy an existing ifchange queue for a specific socket */
static void sock_destroy_ifchange_q( struct sock *sock ) static void sock_release_ifchange( struct sock *sock )
{ {
if (sock->ifchange_q) if (sock->ifchange_obj)
{ {
list_remove( &sock->ifchange_entry ); list_remove( &sock->ifchange_entry );
free_async_queue( sock->ifchange_q );
sock->ifchange_q = NULL;
release_object( sock->ifchange_obj ); release_object( sock->ifchange_obj );
sock->ifchange_obj = NULL;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment