diff options
author | Jeff Dike <jdike@addtoit.com> | 2008-05-12 14:01:58 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-05-13 08:02:22 -0700 |
commit | 5d33e4d7fd9a52d2673e5c730eab81856e100a74 (patch) | |
tree | c4d5014fa21ebde900441b4a5b51092a09c47823 /arch/um/include | |
parent | 60a2988aea701a6424809a5432bf068667aac177 (diff) |
uml: random driver fixes
The random driver would essentially hang if the host's /dev/random returned
-EAGAIN. There was a test of need_resched followed by a schedule inside the
loop, but that didn't help and it's the wrong way to work anyway.
The right way is to ask for an interrupt when there is input available from
the host and handle it then rather than polling.
Now, when the host's /dev/random returns -EAGAIN, the driver asks for a wakeup
when there's randomness available again and sleeps. The interrupt routine
just wakes up whatever processes are sleeping on host_read_wait.
There is an atomic_t, host_sleep_count, which counts the number of processes
waiting for randomness. When this reaches zero, the interrupt is disabled.
An added complication is that async I/O notification was only recently added
to /dev/random (by me), so essentially all hosts will lack it. So, we use the
sigio workaround here, which is to have a separate thread poll on the
descriptor and send an interrupt when there is input on it. This mechanism is
activated when a process gets -EAGAIN (activating this multiple times is
harmless, if a bit wasteful) and deactivated by the last process still
waiting.
The module name was changed from "random" to "hw_random" in order for udev to
recognize it.
The sigio workaround needed some changes. sigio_broken was added for cases
when we know that async notification doesn't work. This is now called from
maybe_sigio_broken, which deals with pts devices.
Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/um/include')
-rw-r--r-- | arch/um/include/os.h | 1 | ||||
-rw-r--r-- | arch/um/include/process.h | 16 |
2 files changed, 5 insertions, 12 deletions
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 32c799e3a49..e2716ac8889 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -290,6 +290,7 @@ extern void os_set_ioignore(void); extern int add_sigio_fd(int fd); extern int ignore_sigio_fd(int fd); extern void maybe_sigio_broken(int fd, int read); +extern void sigio_broken(int fd, int read); /* sys-x86_64/prctl.c */ extern int os_arch_prctl(int pid, int code, unsigned long *addr); diff --git a/arch/um/include/process.h b/arch/um/include/process.h index 5af9157ff54..838b4802ce5 100644 --- a/arch/um/include/process.h +++ b/arch/um/include/process.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -8,18 +8,10 @@ #include <signal.h> +/* Copied from linux/compiler-gcc.h since we can't include it directly */ +#define barrier() __asm__ __volatile__("": : :"memory") + extern void sig_handler(int sig, struct sigcontext sc); extern void alarm_handler(int sig, struct sigcontext sc); #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ |