]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - arch/um/os-Linux/sigio.c
[PATCH] uml: fix thread startup race
[mv-sheeva.git] / arch / um / os-Linux / sigio.c
index 7604c404c4c2f390fe6d360c6ef8ebbfcc4d1c2c..9ba9429471468ce3f8b338b2c337db3f3bcd26aa 100644 (file)
@@ -29,8 +29,10 @@ static int write_sigio_pid = -1;
  * the descriptors closed after it is killed.  So, it can't see them change.
  * On the UML side, they are changed under the sigio_lock.
  */
-static int write_sigio_fds[2] = { -1, -1 };
-static int sigio_private[2] = { -1, -1 };
+#define SIGIO_FDS_INIT {-1, -1}
+
+static int write_sigio_fds[2] = SIGIO_FDS_INIT;
+static int sigio_private[2] = SIGIO_FDS_INIT;
 
 struct pollfds {
        struct pollfd *poll;
@@ -270,49 +272,46 @@ void write_sigio_workaround(void)
        /* Did we race? Don't try to optimize this, please, it's not so likely
         * to happen, and no more than once at the boot. */
        if(write_sigio_pid != -1)
-               goto out_unlock;
-
-       write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
-                                           CLONE_FILES | CLONE_VM, &stack, 0);
+               goto out_free;
 
-       if (write_sigio_pid < 0)
-               goto out_clear;
+       current_poll = ((struct pollfds) { .poll        = p,
+                                          .used        = 1,
+                                          .size        = 1 });
 
        if (write_sigio_irq(l_write_sigio_fds[0]))
-               goto out_kill;
+               goto out_clear_poll;
 
-       /* Success, finally. */
        memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
        memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
 
-       current_poll = ((struct pollfds) { .poll        = p,
-                                          .used        = 1,
-                                          .size        = 1 });
+       write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
+                                           CLONE_FILES | CLONE_VM, &stack, 0);
 
-       sigio_unlock();
-       return;
+       if (write_sigio_pid < 0)
+               goto out_clear;
 
- out_kill:
-       l_write_sigio_pid = write_sigio_pid;
-       write_sigio_pid = -1;
        sigio_unlock();
-       /* Going to call waitpid, avoid holding the lock. */
-       os_kill_process(l_write_sigio_pid, 1);
-       goto out_free;
+       return;
 
- out_clear:
+out_clear:
        write_sigio_pid = -1;
- out_unlock:
-       sigio_unlock();
- out_free:
+       write_sigio_fds[0] = -1;
+       write_sigio_fds[1] = -1;
+       sigio_private[0] = -1;
+       sigio_private[1] = -1;
+out_clear_poll:
+       current_poll = ((struct pollfds) { .poll        = NULL,
+                                          .size        = 0,
+                                          .used        = 0 });
+out_free:
        kfree(p);
- out_close2:
+       sigio_unlock();
+out_close2:
        close(l_sigio_private[0]);
        close(l_sigio_private[1]);
- out_close1:
+out_close1:
        close(l_write_sigio_fds[0]);
        close(l_write_sigio_fds[1]);
-       return;
 }
 
 void sigio_cleanup(void)