Index: linux-2.4/drivers/acpi/ospm/busmgr/bm_osl.c diff -u linux-2.4/drivers/acpi/ospm/busmgr/bm_osl.c:1.1.1.1 linux-2.4/drivers/acpi/ospm/busmgr/bm_osl.c:1.3 --- linux-2.4/drivers/acpi/ospm/busmgr/bm_osl.c:1.1.1.1 Mon Jul 9 10:50:50 2001 +++ linux-2.4/drivers/acpi/ospm/busmgr/bm_osl.c Wed Aug 22 16:06:44 2001 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include "bm.h" @@ -217,60 +218,88 @@ size_t count, loff_t *ppos) { - char str[BM_MAX_STRING_LENGTH]; - int size; BM_OSL_EVENT *event = NULL; unsigned long flags = 0; + static char str[BM_MAX_STRING_LENGTH]; + static int strsize; + static char *ptr; - DECLARE_WAITQUEUE(wait, current); + if (!strsize) { + DECLARE_WAITQUEUE(wait, current); - if (count < BM_MAX_STRING_LENGTH) { - return 0; - } - - if (list_empty(&bm_event_list)) { - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&bm_event_wait_queue, &wait); - if (list_empty(&bm_event_list)) { - schedule(); + if (file->f_flags & O_NONBLOCK) { + return -EAGAIN; + } + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&bm_event_wait_queue, &wait); + + if (list_empty(&bm_event_list)) { + schedule(); + } + + remove_wait_queue(&bm_event_wait_queue, &wait); + set_current_state(TASK_RUNNING); + + if (signal_pending(current)) { + return -ERESTARTSYS; + } } - remove_wait_queue(&bm_event_wait_queue, &wait); - set_current_state(TASK_RUNNING); + spin_lock_irqsave(&bm_osl_event_lock, flags); + event = list_entry(bm_event_list.next, BM_OSL_EVENT, list); + list_del(&event->list); + spin_unlock_irqrestore(&bm_osl_event_lock, flags); + + /* BUG: buffer overrun? */ + strsize = sprintf(str, "%s %s %08x %08x\n", + event->device_type, event->device_instance, + event->event_type, event->event_data); + ptr = str; - if (signal_pending(current)) { - return -ERESTARTSYS; - } + acpi_os_free(event->device_type); + acpi_os_free(event->device_instance); + acpi_os_free(event); } - spin_lock_irqsave(&bm_osl_event_lock, flags); - event = list_entry(bm_event_list.next, BM_OSL_EVENT, list); - list_del(&event->list); - spin_unlock_irqrestore(&bm_osl_event_lock, flags); - - /* BUG: buffer overrun? */ - size = sprintf(str, "%s %s %08x %08x\n", - event->device_type, event->device_instance, - event->event_type, event->event_data); + if (strsize < count) + count = strsize; - acpi_os_free(event->device_type); - acpi_os_free(event->device_instance); - acpi_os_free(event); - - if (copy_to_user(buf, str, size)) + if (copy_to_user(buf, ptr, count)) return -EFAULT; - *ppos += size; + *ppos += count; + strsize -= count; + ptr += count; - return size; + return count; +} + +/**************************************************************************** + * + * FUNCTION: bm_osl_poll_event + * + * DESCRIPTION: Handles poll() of the 'event' file by blocking user-mode + * threads until data (an event) is generated. + * + ****************************************************************************/ +static unsigned int +bm_osl_poll_event( + struct file *file, + poll_table *wait) +{ + poll_wait(file, &bm_event_wait_queue, wait); + if (!list_empty(&bm_event_list)) + return POLLIN | POLLRDNORM; + return 0; } struct file_operations proc_event_operations = { open: bm_osl_open_event, read: bm_osl_read_event, release: bm_osl_close_event, + poll: bm_osl_poll_event, }; /****************************************************************************