Moved poll handling to the generic part of the server objects.
Fixed busy waiting on POLLERR events.
Merged struct client into struct thread.
diff --git a/server/sock.c b/server/sock.c
index cb9928f..531231b 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -42,8 +42,6 @@
struct sock
{
struct object obj; /* object header */
- int fd; /* file descriptor */
- int select; /* select user */
unsigned int state; /* status bits */
unsigned int mask; /* event mask */
unsigned int hmask; /* held (blocked) events */
@@ -53,51 +51,36 @@
};
static void sock_dump( struct object *obj, int verbose );
-static int sock_add_queue( struct object *obj, struct wait_queue_entry *entry );
-static void sock_remove_queue( struct object *obj, struct wait_queue_entry *entry );
static int sock_signaled( struct object *obj, struct thread *thread );
+static int sock_get_poll_events( struct object *obj );
+static void sock_poll_event( struct object *obj, int event );
static int sock_get_fd( struct object *obj );
static void sock_destroy( struct object *obj );
static void sock_set_error(void);
static const struct object_ops sock_ops =
{
- sizeof(struct sock),
- sock_dump,
- sock_add_queue,
- sock_remove_queue,
- sock_signaled,
- no_satisfied,
- sock_get_fd,
- sock_get_fd,
- no_flush,
- no_get_file_info,
- sock_destroy
+ sizeof(struct sock), /* size */
+ sock_dump, /* dump */
+ add_queue, /* add_queue */
+ remove_queue, /* remove_queue */
+ sock_signaled, /* signaled */
+ no_satisfied, /* satisfied */
+ sock_get_poll_events, /* get_poll_events */
+ sock_poll_event, /* poll_event */
+ sock_get_fd, /* get_read_fd */
+ sock_get_fd, /* get_write_fd */
+ no_flush, /* flush */
+ no_get_file_info, /* get_file_info */
+ sock_destroy /* destroy */
};
-static int sock_event( struct sock *sock )
-{
- unsigned int mask = sock->mask & sock->state & ~sock->hmask;
- int ev = 0;
-
- if (sock->state & WS_FD_CONNECT)
- /* connecting, wait for writable */
- return POLLOUT;
- if (sock->state & WS_FD_LISTENING)
- /* listening, wait for readable */
- return (sock->hmask & FD_ACCEPT) ? 0 : POLLIN;
-
- if (mask & FD_READ) ev |= POLLIN;
- if (mask & FD_WRITE) ev |= POLLOUT;
- return ev;
-}
-
static void sock_reselect( struct sock *sock )
{
- int ev = sock_event( sock );
+ int ev = sock_get_poll_events( &sock->obj );
if (debug_level)
- fprintf(stderr,"sock_reselect(%d): new mask %x\n", sock->fd, ev);
- set_select_events( sock->select, ev );
+ fprintf(stderr,"sock_reselect(%d): new mask %x\n", sock->obj.fd, ev);
+ set_select_events( &sock->obj, ev );
}
inline static int sock_error(int s)
@@ -109,13 +92,13 @@
return optval;
}
-static void sock_select_event( int event, void *private )
+static void sock_poll_event( struct object *obj, int event )
{
- struct sock *sock = (struct sock *)private;
+ struct sock *sock = (struct sock *)obj;
unsigned int emask;
assert( sock->obj.ops == &sock_ops );
if (debug_level)
- fprintf(stderr, "socket %d select event: %x\n", sock->fd, event);
+ fprintf(stderr, "socket %d select event: %x\n", sock->obj.fd, event);
if (sock->state & WS_FD_CONNECT)
{
/* connecting */
@@ -127,16 +110,16 @@
sock->pmask |= FD_CONNECT;
sock->errors[FD_CONNECT_BIT] = 0;
if (debug_level)
- fprintf(stderr, "socket %d connection success\n", sock->fd);
+ fprintf(stderr, "socket %d connection success\n", sock->obj.fd);
}
else if (event & (POLLERR|POLLHUP))
{
/* we didn't get connected? */
sock->state &= ~WS_FD_CONNECT;
sock->pmask |= FD_CONNECT;
- sock->errors[FD_CONNECT_BIT] = sock_error( sock->fd );
+ sock->errors[FD_CONNECT_BIT] = sock_error( sock->obj.fd );
if (debug_level)
- fprintf(stderr, "socket %d connection failure\n", sock->fd);
+ fprintf(stderr, "socket %d connection failure\n", sock->obj.fd);
}
} else
if (sock->state & WS_FD_LISTENING)
@@ -153,7 +136,7 @@
{
/* failed incoming connection? */
sock->pmask |= FD_ACCEPT;
- sock->errors[FD_ACCEPT_BIT] = sock_error( sock->fd );
+ sock->errors[FD_ACCEPT_BIT] = sock_error( sock->obj.fd );
sock->hmask |= FD_ACCEPT;
}
} else
@@ -161,27 +144,12 @@
/* normal data flow */
if (event & POLLIN)
{
- /* make sure there's data here */
- int bytes = 0;
- ioctl(sock->fd, FIONREAD, (char*)&bytes);
- if (bytes)
- {
- /* incoming data */
- sock->pmask |= FD_READ;
- sock->hmask |= FD_READ;
- sock->errors[FD_READ_BIT] = 0;
- if (debug_level)
- fprintf(stderr, "socket %d has %d bytes\n", sock->fd, bytes);
- }
- else
- {
- /* 0 bytes readable == socket closed cleanly */
- sock->state &= ~(WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE);
- sock->pmask |= FD_CLOSE;
- sock->errors[FD_CLOSE_BIT] = 0;
- if (debug_level)
- fprintf(stderr, "socket %d is closing\n", sock->fd);
- }
+ /* incoming data */
+ sock->pmask |= FD_READ;
+ sock->hmask |= FD_READ;
+ sock->errors[FD_READ_BIT] = 0;
+ if (debug_level)
+ fprintf(stderr, "socket %d is readable\n", sock->obj.fd );
}
if (event & POLLOUT)
{
@@ -189,27 +157,24 @@
sock->hmask |= FD_WRITE;
sock->errors[FD_WRITE_BIT] = 0;
if (debug_level)
- fprintf(stderr, "socket %d is writable\n", sock->fd);
+ fprintf(stderr, "socket %d is writable\n", sock->obj.fd);
+ }
+ if (event & POLLPRI)
+ {
+ sock->pmask |= FD_OOB;
+ sock->hmask |= FD_OOB;
+ if (debug_level)
+ fprintf(stderr, "socket %d got OOB data\n", sock->obj.fd);
}
if (event & (POLLERR|POLLHUP))
{
- sock->errors[FD_CLOSE_BIT] = sock_error( sock->fd );
- if (sock->errors[FD_CLOSE_BIT])
- {
- /* we got an error, socket closing? */
- sock->state &= ~(WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE);
- sock->pmask |= FD_CLOSE;
- if (debug_level)
- fprintf(stderr, "socket %d aborted by error %d\n", sock->fd, sock->errors[FD_CLOSE_BIT]);
- }
- else
- {
- /* no error, OOB data? */
- sock->pmask |= FD_OOB;
- sock->hmask |= FD_OOB;
- if (debug_level)
- fprintf(stderr, "socket %d got OOB data\n", sock->fd);
- }
+ sock->errors[FD_CLOSE_BIT] = sock_error( sock->obj.fd );
+ /* we got an error, socket closing? */
+ sock->state &= ~(WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE);
+ sock->pmask |= FD_CLOSE;
+ if (debug_level)
+ fprintf(stderr, "socket %d aborted by error %d\n",
+ sock->obj.fd, sock->errors[FD_CLOSE_BIT]);
}
}
@@ -217,7 +182,7 @@
/* wake up anyone waiting for whatever just happened */
emask = sock->pmask & sock->mask;
if (debug_level && emask)
- fprintf(stderr, "socket %d pending events: %x\n", sock->fd, emask);
+ fprintf(stderr, "socket %d pending events: %x\n", sock->obj.fd, emask);
if (emask && sock->event) {
if (debug_level) fprintf(stderr, "signalling event ptr %p\n", sock->event);
set_event(sock->event);
@@ -233,34 +198,36 @@
struct sock *sock = (struct sock *)obj;
assert( obj->ops == &sock_ops );
printf( "Socket fd=%d, state=%x, mask=%x, pending=%x, held=%x\n",
- sock->fd, sock->state,
+ sock->obj.fd, sock->state,
sock->mask, sock->pmask, sock->hmask );
}
-static int sock_add_queue( struct object *obj, struct wait_queue_entry *entry )
-{
-/* struct sock *sock = (struct sock *)obj; */
- assert( obj->ops == &sock_ops );
-
- add_queue( obj, entry );
- return 1;
-}
-
-static void sock_remove_queue( struct object *obj, struct wait_queue_entry *entry )
-{
-/* struct sock *sock = (struct sock *)grab_object(obj); */
- assert( obj->ops == &sock_ops );
-
- remove_queue( obj, entry );
-/* release_object( obj ); */
-}
-
static int sock_signaled( struct object *obj, struct thread *thread )
{
struct sock *sock = (struct sock *)obj;
assert( obj->ops == &sock_ops );
- return check_select_events( sock->fd, sock_event( sock ) );
+ return check_select_events( sock->obj.fd, sock_get_poll_events( &sock->obj ) );
+}
+
+static int sock_get_poll_events( struct object *obj )
+{
+ struct sock *sock = (struct sock *)obj;
+ unsigned int mask = sock->mask & sock->state & ~sock->hmask;
+ int ev = 0;
+
+ assert( obj->ops == &sock_ops );
+
+ if (sock->state & WS_FD_CONNECT)
+ /* connecting, wait for writable */
+ return POLLOUT;
+ if (sock->state & WS_FD_LISTENING)
+ /* listening, wait for readable */
+ return (sock->hmask & FD_ACCEPT) ? 0 : POLLIN;
+
+ if (mask & FD_READ) ev |= POLLIN | POLLPRI;
+ if (mask & FD_WRITE) ev |= POLLOUT;
+ return ev;
}
static int sock_get_fd( struct object *obj )
@@ -268,7 +235,7 @@
struct sock *sock = (struct sock *)obj;
int fd;
assert( obj->ops == &sock_ops );
- fd = dup( sock->fd );
+ fd = dup( sock->obj.fd );
if (fd==-1)
sock_set_error();
return fd;
@@ -280,7 +247,6 @@
assert( obj->ops == &sock_ops );
/* FIXME: special socket shutdown stuff? */
- remove_select_user( sock->select );
if (sock->event)
{
/* if the service thread was waiting for the event object,
@@ -307,21 +273,12 @@
return NULL;
}
fcntl(sockfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
- if (!(sock = alloc_object( &sock_ops ))) {
- close( sockfd );
- return NULL;
- }
- sock->fd = sockfd;
+ if (!(sock = alloc_object( &sock_ops, sockfd ))) return NULL;
sock->state = (type!=SOCK_STREAM) ? WS_FD_READ|WS_FD_WRITE : 0;
sock->mask = 0;
sock->hmask = 0;
sock->pmask = 0;
sock->event = NULL;
- if ((sock->select = add_select_user( sockfd, sock_select_event, sock )) == -1)
- {
- release_object( sock );
- return NULL;
- }
sock_reselect( sock );
clear_error();
return &sock->obj;
@@ -345,32 +302,23 @@
* return.
*/
slen = sizeof(saddr);
- acceptfd = accept(sock->fd,&saddr,&slen);
+ acceptfd = accept(sock->obj.fd,&saddr,&slen);
if (acceptfd==-1) {
sock_set_error();
release_object( sock );
return NULL;
}
- if (!(acceptsock = alloc_object( &sock_ops )))
+ if (!(acceptsock = alloc_object( &sock_ops, acceptfd )))
{
- close( acceptfd );
release_object( sock );
return NULL;
}
- acceptsock->fd = acceptfd;
acceptsock->state = WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE;
acceptsock->mask = sock->mask;
acceptsock->hmask = 0;
acceptsock->pmask = 0;
acceptsock->event = NULL;
- acceptsock->select = add_select_user( acceptfd, sock_select_event, acceptsock );
- if (acceptsock->select == -1)
- {
- release_object( acceptsock );
- release_object( sock );
- return NULL;
- }
if (sock->event) acceptsock->event = (struct event *)grab_object( sock->event );
sock_reselect( acceptsock );