// $Header$ // Kernel Version: // VERSION = 2 // PATCHLEVEL = 5 // SUBLEVEL = 48 // EXTRAVERSION = --- 2.5/include/linux/poll.h 2002-11-19 23:07:35.000000000 +0100 +++ build-2.5/include/linux/poll.h 2002-11-19 23:12:11.000000000 +0100 @@ -35,10 +35,20 @@ /* * Structures and helpers for sys_poll/sys_poll */ +struct poll_table_entry { + struct file *filp; + wait_queue_t wait; + wait_queue_head_t *wait_address; +}; + +#define POLL_TABLE_INTERNAL 6 + struct poll_wqueues { poll_table pt; - struct poll_table_page * table; int error; + int nr; + struct poll_table_entry internal[POLL_TABLE_INTERNAL]; + struct poll_table_page *table; }; extern void poll_initwait(struct poll_wqueues *pwq); --- 2.5/fs/select.c 2002-11-19 23:07:35.000000000 +0100 +++ build-2.5/fs/select.c 2002-11-19 23:10:50.000000000 +0100 @@ -26,12 +26,6 @@ #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; @@ -53,18 +47,36 @@ * as all select/poll functions have to call it to add an entry to the * poll table. */ -void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p); +static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p); void poll_initwait(struct poll_wqueues *pwq) { init_poll_funcptr(&pwq->pt, __pollwait); pwq->error = 0; + pwq->nr = 0; pwq->table = NULL; } +/* + * Dynamic memory allocation is expensive, avoid it by + * saving a few bytes on the stack: + * - the poll table contains 6 wait queue entries. This means that no dynamic + * memory allocation is necessary for the wait queues if one of the first + * 6 file descriptors has new data. + * + */ void poll_freewait(struct poll_wqueues *pwq) { struct poll_table_page * p = pwq->table; + struct poll_table_entry *entry; + + entry = pwq->internal + pwq->nr; + while(pwq->nr > 0) { + pwq->nr--; + entry--; + remove_wait_queue(entry->wait_address,&entry->wait); + fput(entry->filp); + } while (p) { struct poll_table_entry * entry; struct poll_table_page *old; @@ -77,43 +89,46 @@ } while (entry > p->entries); old = p; p = p->next; - free_page((unsigned long) old); + kfree(old); } } -void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *_p) +static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *_p) { struct poll_wqueues *p = container_of(_p, struct poll_wqueues, pt); - struct poll_table_page *table = p->table; - - if (!table || POLL_TABLE_FULL(table)) { - struct poll_table_page *new_table; - - new_table = (struct poll_table_page *) __get_free_page(GFP_KERNEL); - if (!new_table) { - p->error = -ENOMEM; - __set_current_state(TASK_RUNNING); - return; + struct poll_table_entry *entry; + + if(p->nr < POLL_TABLE_INTERNAL) { + entry = p->internal+p->nr++; + } else { + struct poll_table_page *table = p->table; + + if (!table || POLL_TABLE_FULL(table)) { + struct poll_table_page *new_table; + + new_table = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!new_table) { + p->error = -ENOMEM; + __set_current_state(TASK_RUNNING); + return; + } + new_table->entry = new_table->entries; + new_table->next = table; + p->table = new_table; + table = new_table; } - new_table->entry = new_table->entries; - new_table->next = table; - p->table = new_table; - table = new_table; + entry = table->entry; + table->entry = entry+1; } /* Add a new entry */ - { - struct poll_table_entry * entry = table->entry; - table->entry = entry+1; - get_file(filp); - entry->filp = filp; - entry->wait_address = wait_address; - init_waitqueue_entry(&entry->wait, current); - add_wait_queue(wait_address,&entry->wait); - } + get_file(filp); + entry->filp = filp; + entry->wait_address = wait_address; + init_waitqueue_entry(&entry->wait, current); + add_wait_queue(wait_address,&entry->wait); } - #define __IN(fds, n) (fds->in + n) #define __OUT(fds, n) (fds->out + n) #define __EX(fds, n) (fds->ex + n)