Fix up incorrect "unlikely()" on %gs reload in x86 __switch_to
authorLinus Torvalds <torvalds@evo.osdl.org>
Fri, 22 Jul 2005 19:23:47 +0000 (15:23 -0400)
committerLinus Torvalds <torvalds@evo.osdl.org>
Fri, 22 Jul 2005 19:23:47 +0000 (15:23 -0400)
These days %gs is normally the TLS segment, so it's no longer zero.  As
a result, we shouldn't just assume that %fs/%gs tend to be zero
together, but test them independently instead.

Also, fix setting of debug registers to use the "next" pointer instead
of "current".  It so happens that the scheduler will have set the new
current pointer before calling __switch_to(), but that's just an
implementation detail.

arch/i386/kernel/process.c

index ba243a4..d949205 100644 (file)
@@ -700,23 +700,27 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
 
        /*
         * Restore %fs and %gs if needed.
+        *
+        * Glibc normally makes %fs be zero, and %gs is one of
+        * the TLS segments.
         */
-       if (unlikely(prev->fs | prev->gs | next->fs | next->gs)) {
+       if (unlikely(prev->fs | next->fs))
                loadsegment(fs, next->fs);
+
+       if (prev->gs | next->gs)
                loadsegment(gs, next->gs);
-       }
 
        /*
         * Now maybe reload the debug registers
         */
        if (unlikely(next->debugreg[7])) {
-               set_debugreg(current->thread.debugreg[0], 0);
-               set_debugreg(current->thread.debugreg[1], 1);
-               set_debugreg(current->thread.debugreg[2], 2);
-               set_debugreg(current->thread.debugreg[3], 3);
+               set_debugreg(next->debugreg[0], 0);
+               set_debugreg(next->debugreg[1], 1);
+               set_debugreg(next->debugreg[2], 2);
+               set_debugreg(next->debugreg[3], 3);
                /* no 4 and 5 */
-               set_debugreg(current->thread.debugreg[6], 6);
-               set_debugreg(current->thread.debugreg[7], 7);
+               set_debugreg(next->debugreg[6], 6);
+               set_debugreg(next->debugreg[7], 7);
        }
 
        if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))