summaryrefslogtreecommitdiffstats
path: root/fs/select.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/select.c')
-rw-r--r--fs/select.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/fs/select.c b/fs/select.c
index a5c213930..0b3718309 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -24,6 +24,21 @@
#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
+struct poll_table_entry {
+ struct file * filp;
+ wait_queue_t wait;
+ wait_queue_head_t * wait_address;
+};
+
+struct poll_table_page {
+ struct poll_table_page * next;
+ struct poll_table_entry * entry;
+ struct poll_table_entry entries[0];
+};
+
+#define POLL_TABLE_FULL(table) \
+ ((unsigned long)(table->entry+1) > PAGE_SIZE + (unsigned long)(table))
+
/*
* Ok, Peter made a complicated, but straightforward multiple_wait() function.
* I have rewritten this, taking some shortcuts: This code may not be easy to
@@ -44,13 +59,12 @@ void poll_freewait(poll_table* pt)
struct poll_table_entry * entry;
struct poll_table_page *old;
- entry = p->entry + p->nr;
- while (p->nr > 0) {
- p->nr--;
+ entry = p->entry;
+ do {
entry--;
remove_wait_queue(entry->wait_address,&entry->wait);
fput(entry->filp);
- }
+ } while (entry > p->entries);
old = p;
p = p->next;
free_page((unsigned long) old);
@@ -61,7 +75,7 @@ void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table
{
struct poll_table_page *table = p->table;
- if (!table || table->nr >= __MAX_POLL_TABLE_ENTRIES) {
+ if (!table || POLL_TABLE_FULL(table)) {
struct poll_table_page *new_table;
new_table = (struct poll_table_page *) __get_free_page(GFP_KERNEL);
@@ -70,8 +84,7 @@ void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table
__set_current_state(TASK_RUNNING);
return;
}
- new_table->nr = 0;
- new_table->entry = (struct poll_table_entry *)(new_table + 1);
+ new_table->entry = new_table->entries;
new_table->next = table;
p->table = new_table;
table = new_table;
@@ -79,9 +92,8 @@ void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table
/* Add a new entry */
{
- struct poll_table_entry * entry;
- entry = table->entry + table->nr;
- table->nr++;
+ struct poll_table_entry * entry = table->entry;
+ table->entry = entry+1;
get_file(filp);
entry->filp = filp;
entry->wait_address = wait_address;