aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo \'Blaisorblade\' Giarrusso <blaisorblade@yahoo.it>2005-03-30 16:35:02 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-03-30 16:35:02 -0800
commitad507c5a5370ded94b8fa7a0ff359461d6a10f2d (patch)
treef6f62e9e055b66b65793da51f84d232fc2de2e99
parent2106630ca40d6889f1609987db685e3bcf290d99 (diff)
downloadhistory-ad507c5a5370ded94b8fa7a0ff359461d6a10f2d.tar.gz
[PATCH] uml: fix sigio spinlock
I just saw a "take twice spinlock" deadlock with the Spinlock debugging enabled on this lock, and static code analysis revealed this is the culprit: update_thread can take (in an error path) the sigio_lock, which is already held by all its callers (it's a static function, so it's easy to verify). Added some comments to mark where this function needs the lock, in case someone wants to reduce the locking here. Also clean an exitcall to mark the thread as killed (won't hurt, and could be useful if things go wrong). As a bonus, some CodingStyle cleanups. Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/um/kernel/sigio_user.c29
1 files changed, 12 insertions, 17 deletions
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 82d19b451d5eae..668df13d8c9d67 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -108,12 +108,14 @@ static void tty_output(int master, int slave)
panic("check_sigio : write failed, errno = %d\n", errno);
while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
- if(got_sigio){
+ if (got_sigio) {
printk("Yes\n");
pty_output_sigio = 1;
+ } else if (n == -EAGAIN) {
+ printk("No, enabling workaround\n");
+ } else {
+ panic("check_sigio : read failed, err = %d\n", n);
}
- else if(n == -EAGAIN) printk("No, enabling workaround\n");
- else panic("check_sigio : read failed, err = %d\n", n);
}
static void tty_close(int master, int slave)
@@ -235,6 +237,8 @@ static int need_poll(int n)
return(0);
}
+/* Must be called with sigio_lock held, because it's needed by the marked
+ * critical section. */
static void update_thread(void)
{
unsigned long flags;
@@ -257,7 +261,7 @@ static void update_thread(void)
set_signals(flags);
return;
fail:
- sigio_lock();
+ /* Critical section start */
if(write_sigio_pid != -1)
os_kill_process(write_sigio_pid, 1);
write_sigio_pid = -1;
@@ -265,7 +269,7 @@ static void update_thread(void)
os_close_file(sigio_private[1]);
os_close_file(write_sigio_fds[0]);
os_close_file(write_sigio_fds[1]);
- sigio_unlock();
+ /* Critical section end */
set_signals(flags);
}
@@ -418,19 +422,10 @@ int read_sigio_fd(int fd)
static void sigio_cleanup(void)
{
- if(write_sigio_pid != -1)
+ if (write_sigio_pid != -1) {
os_kill_process(write_sigio_pid, 1);
+ write_sigio_pid = -1;
+ }
}
__uml_exitcall(sigio_cleanup);
-
-/*
- * 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:
- */