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/file.c b/server/file.c
index c80ecce..3cc46bd 100644
--- a/server/file.c
+++ b/server/file.c
@@ -32,8 +32,6 @@
struct file
{
struct object obj; /* object header */
- int fd; /* file descriptor */
- int select; /* select user id */
struct file *next; /* next file in hashing list */
char *name; /* file name */
unsigned int access; /* file access (GENERIC_READ/WRITE) */
@@ -46,9 +44,7 @@
static struct file *file_hash[NAME_HASH_SIZE];
static void file_dump( struct object *obj, int verbose );
-static int file_add_queue( struct object *obj, struct wait_queue_entry *entry );
-static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry );
-static int file_signaled( struct object *obj, struct thread *thread );
+static int file_get_poll_events( struct object *obj );
static int file_get_read_fd( struct object *obj );
static int file_get_write_fd( struct object *obj );
static int file_flush( struct object *obj );
@@ -57,17 +53,19 @@
static const struct object_ops file_ops =
{
- sizeof(struct file),
- file_dump,
- file_add_queue,
- file_remove_queue,
- file_signaled,
- no_satisfied,
- file_get_read_fd,
- file_get_write_fd,
- file_flush,
- file_get_info,
- file_destroy
+ sizeof(struct file), /* size */
+ file_dump, /* dump */
+ default_poll_add_queue, /* add_queue */
+ default_poll_remove_queue, /* remove_queue */
+ default_poll_signaled, /* signaled */
+ no_satisfied, /* satisfied */
+ file_get_poll_events, /* get_poll_events */
+ default_poll_event, /* poll_event */
+ file_get_read_fd, /* get_read_fd */
+ file_get_write_fd, /* get_write_fd */
+ file_flush, /* flush */
+ file_get_info, /* get_file_info */
+ file_destroy /* destroy */
};
@@ -103,23 +101,19 @@
return 0;
}
+/* create a file from a file descriptor */
+/* if the function fails the fd is closed */
static struct file *create_file_for_fd( int fd, unsigned int access, unsigned int sharing,
unsigned int attrs )
{
struct file *file;
- if ((file = alloc_object( &file_ops )))
+ if ((file = alloc_object( &file_ops, fd )))
{
file->name = NULL;
file->next = NULL;
- file->fd = fd;
file->access = access;
file->flags = attrs;
file->sharing = sharing;
- if ((file->select = add_select_user( fd, default_select_event, file )) == -1)
- {
- release_object( file );
- file = NULL;
- }
}
return file;
}
@@ -171,7 +165,11 @@
goto error;
}
- if (!(file = create_file_for_fd( fd, access, sharing, attrs ))) goto error;
+ if (!(file = create_file_for_fd( fd, access, sharing, attrs )))
+ {
+ free( name );
+ return NULL;
+ }
file->name = name;
file->next = file_hash[hash];
file_hash[hash] = file;
@@ -212,81 +210,41 @@
/* Create a temp file for anonymous mappings */
struct file *create_temp_file( int access )
{
- struct file *file;
int fd;
if ((fd = create_anonymous_file()) == -1) return NULL;
- if (!(file = create_file_for_fd( fd, access, 0, 0 ))) close( fd );
- return file;
+ return create_file_for_fd( fd, access, 0, 0 );
}
static void file_dump( struct object *obj, int verbose )
{
struct file *file = (struct file *)obj;
assert( obj->ops == &file_ops );
- fprintf( stderr, "File fd=%d flags=%08x name='%s'\n", file->fd, file->flags, file->name );
+ fprintf( stderr, "File fd=%d flags=%08x name='%s'\n", file->obj.fd, file->flags, file->name );
}
-static int file_add_queue( struct object *obj, struct wait_queue_entry *entry )
+static int file_get_poll_events( struct object *obj )
{
struct file *file = (struct file *)obj;
- assert( obj->ops == &file_ops );
- if (!obj->head) /* first on the queue */
- {
- int events = 0;
- if (file->access & GENERIC_READ) events |= POLLIN;
- if (file->access & GENERIC_WRITE) events |= POLLOUT;
- set_select_events( file->select, events );
- }
- add_queue( obj, entry );
- return 1;
-}
-
-static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry )
-{
- struct file *file = (struct file *)grab_object(obj);
- assert( obj->ops == &file_ops );
-
- remove_queue( obj, entry );
- if (!obj->head) /* last on the queue is gone */
- set_select_events( file->select, 0 );
- release_object( obj );
-}
-
-static int file_signaled( struct object *obj, struct thread *thread )
-{
int events = 0;
- struct file *file = (struct file *)obj;
assert( obj->ops == &file_ops );
-
if (file->access & GENERIC_READ) events |= POLLIN;
if (file->access & GENERIC_WRITE) events |= POLLOUT;
- if (check_select_events( file->fd, events ))
- {
- /* stop waiting on select() if we are signaled */
- set_select_events( file->select, 0 );
- return 1;
- }
- else
- {
- /* restart waiting on select() if we are no longer signaled */
- if (obj->head) set_select_events( file->select, events );
- return 0;
- }
+ return events;
}
static int file_get_read_fd( struct object *obj )
{
struct file *file = (struct file *)obj;
assert( obj->ops == &file_ops );
- return dup( file->fd );
+ return dup( file->obj.fd );
}
static int file_get_write_fd( struct object *obj )
{
struct file *file = (struct file *)obj;
assert( obj->ops == &file_ops );
- return dup( file->fd );
+ return dup( file->obj.fd );
}
static int file_flush( struct object *obj )
@@ -295,7 +253,7 @@
struct file *file = (struct file *)grab_object(obj);
assert( obj->ops == &file_ops );
- ret = (fsync( file->fd ) != -1);
+ ret = (fsync( file->obj.fd ) != -1);
if (!ret) file_set_error();
release_object( file );
return ret;
@@ -307,13 +265,13 @@
struct file *file = (struct file *)obj;
assert( obj->ops == &file_ops );
- if (fstat( file->fd, &st ) == -1)
+ if (fstat( file->obj.fd, &st ) == -1)
{
file_set_error();
return 0;
}
if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) ||
- S_ISSOCK(st.st_mode) || isatty(file->fd)) req->type = FILE_TYPE_CHAR;
+ S_ISSOCK(st.st_mode) || isatty(file->obj.fd)) req->type = FILE_TYPE_CHAR;
else req->type = FILE_TYPE_DISK;
if (S_ISDIR(st.st_mode)) req->attr = FILE_ATTRIBUTE_DIRECTORY;
else req->attr = FILE_ATTRIBUTE_ARCHIVE;
@@ -344,7 +302,6 @@
if (file->flags & FILE_FLAG_DELETE_ON_CLOSE) unlink( file->name );
free( file->name );
}
- remove_select_user( file->select );
}
/* set the last error depending on errno */
@@ -379,7 +336,7 @@
int file_get_mmap_fd( struct file *file )
{
- return dup( file->fd );
+ return dup( file->obj.fd );
}
static int set_file_pointer( int handle, int *low, int *high, int whence )
@@ -396,7 +353,7 @@
if (!(file = get_file_obj( current->process, handle, 0 )))
return 0;
- if ((result = lseek( file->fd, *low, whence )) == -1)
+ if ((result = lseek( file->obj.fd, *low, whence )) == -1)
{
/* Check for seek before start of file */
if ((errno == EINVAL) && (whence != SEEK_SET) && (*low < 0))
@@ -418,8 +375,8 @@
if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
return 0;
- if (((result = lseek( file->fd, 0, SEEK_CUR )) == -1) ||
- (ftruncate( file->fd, result ) == -1))
+ if (((result = lseek( file->obj.fd, 0, SEEK_CUR )) == -1) ||
+ (ftruncate( file->obj.fd, result ) == -1))
{
file_set_error();
release_object( file );
@@ -440,13 +397,13 @@
set_error( ERROR_INVALID_PARAMETER );
return 0;
}
- if (fstat( file->fd, &st ) == -1)
+ if (fstat( file->obj.fd, &st ) == -1)
{
file_set_error();
return 0;
}
if (st.st_size >= size_low) return 1; /* already large enough */
- if (ftruncate( file->fd, size_low ) != -1) return 1;
+ if (ftruncate( file->obj.fd, size_low ) != -1) return 1;
file_set_error();
return 0;
}
@@ -518,7 +475,6 @@
req->handle = alloc_handle( current->process, file, req->access, 0 );
release_object( file );
}
- else close( fd );
}
else file_set_error();
}