Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[cascardo/linux.git] / arch / um / os-Linux / signal.c
index 55b62e2..48d4934 100644 (file)
 #include <stdarg.h>
 #include <string.h>
 #include <sys/mman.h>
-#include "user_util.h"
 #include "user.h"
 #include "signal_kern.h"
 #include "sysdep/sigcontext.h"
+#include "sysdep/barrier.h"
 #include "sigcontext.h"
 #include "mode.h"
 #include "os.h"
 #define SIGALRM_BIT 2
 #define SIGALRM_MASK (1 << SIGALRM_BIT)
 
-static int signals_enabled = 1;
-static int pending = 0;
+/* These are used by both the signal handlers and
+ * block/unblock_signals.  I don't want modifications cached in a
+ * register - they must go straight to memory.
+ */
+static volatile int signals_enabled = 1;
+static volatile int pending = 0;
 
 void sig_handler(int sig, struct sigcontext *sc)
 {
@@ -55,15 +59,8 @@ void sig_handler(int sig, struct sigcontext *sc)
        set_signals(enabled);
 }
 
-extern int timer_irq_inited;
-
 static void real_alarm_handler(int sig, struct sigcontext *sc)
 {
-       if(!timer_irq_inited){
-               signals_enabled = 1;
-               return;
-       }
-
        if(sig == SIGALRM)
                switch_timers(0);
 
@@ -159,6 +156,12 @@ int change_sig(int signal, int on)
 void block_signals(void)
 {
        signals_enabled = 0;
+       /* This must return with signals disabled, so this barrier
+        * ensures that writes are flushed out before the return.
+        * This might matter if gcc figures out how to inline this and
+        * decides to shuffle this code into the caller.
+        */
+       mb();
 }
 
 void unblock_signals(void)
@@ -178,9 +181,23 @@ void unblock_signals(void)
                 */
                signals_enabled = 1;
 
+               /* Setting signals_enabled and reading pending must
+                * happen in this order.
+                */
+               mb();
+
                save_pending = pending;
-               if(save_pending == 0)
+               if(save_pending == 0){
+                       /* This must return with signals enabled, so
+                        * this barrier ensures that writes are
+                        * flushed out before the return.  This might
+                        * matter if gcc figures out how to inline
+                        * this (unlikely, given its size) and decides
+                        * to shuffle this code into the caller.
+                        */
+                       mb();
                        return;
+               }
 
                pending = 0;
 
@@ -225,8 +242,3 @@ int set_signals(int enable)
 
        return ret;
 }
-
-void os_usr1_signal(int on)
-{
-       change_sig(SIGUSR1, on);
-}