[PATCH] i386: use thread_info flags for debug regs and IO bitmaps
authorStephane Eranian <eranian@hpl.hp.com>
Mon, 10 Jul 2006 01:12:39 +0000 (21:12 -0400)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 10 Jul 2006 01:47:12 +0000 (18:47 -0700)
Use thread info flags to track use of debug registers and IO bitmaps.

 - add TIF_DEBUG to track when debug registers are active
 - add TIF_IO_BITMAP to track when I/O bitmap is used
 - modify __switch_to() to use the new TIF flags

Performance tested on Pentium II, ten runs of LMbench context switch
benchmark (smaller is better:)

before after
avg 3.65 3.39
min 3.55 3.33

Signed-off-by: Stephane Eranian <eranian@hpl.hp.com>
Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com>
Acked-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/i386/kernel/ioport.c
arch/i386/kernel/process.c
arch/i386/kernel/ptrace.c
include/asm-i386/thread_info.h

index 79026f0..498e8bc 100644 (file)
@@ -79,6 +79,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 
                memset(bitmap, 0xff, IO_BITMAP_BYTES);
                t->io_bitmap_ptr = bitmap;
+               set_thread_flag(TIF_IO_BITMAP);
        }
 
        /*
index 94e2c87..923bb29 100644 (file)
@@ -359,16 +359,16 @@ EXPORT_SYMBOL(kernel_thread);
  */
 void exit_thread(void)
 {
-       struct task_struct *tsk = current;
-       struct thread_struct *t = &tsk->thread;
-
        /* The process may have allocated an io port bitmap... nuke it. */
-       if (unlikely(NULL != t->io_bitmap_ptr)) {
+       if (unlikely(test_thread_flag(TIF_IO_BITMAP))) {
+               struct task_struct *tsk = current;
+               struct thread_struct *t = &tsk->thread;
                int cpu = get_cpu();
                struct tss_struct *tss = &per_cpu(init_tss, cpu);
 
                kfree(t->io_bitmap_ptr);
                t->io_bitmap_ptr = NULL;
+               clear_thread_flag(TIF_IO_BITMAP);
                /*
                 * Careful, clear this in the TSS too:
                 */
@@ -387,6 +387,7 @@ void flush_thread(void)
 
        memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
        memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));        
+       clear_tsk_thread_flag(tsk, TIF_DEBUG);
        /*
         * Forget coprocessor state..
         */
@@ -431,7 +432,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
        savesegment(gs,p->thread.gs);
 
        tsk = current;
-       if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) {
+       if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
                p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
                if (!p->thread.io_bitmap_ptr) {
                        p->thread.io_bitmap_max = 0;
@@ -439,6 +440,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
                }
                memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr,
                        IO_BITMAP_BYTES);
+               set_tsk_thread_flag(p, TIF_IO_BITMAP);
        }
 
        /*
@@ -533,10 +535,24 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
        return 1;
 }
 
-static inline void
-handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss)
+static noinline void __switch_to_xtra(struct task_struct *next_p,
+                                   struct tss_struct *tss)
 {
-       if (!next->io_bitmap_ptr) {
+       struct thread_struct *next;
+
+       next = &next_p->thread;
+
+       if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+               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(next->debugreg[6], 6);
+               set_debugreg(next->debugreg[7], 7);
+       }
+
+       if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
                /*
                 * Disable the bitmap via an invalid offset. We still cache
                 * the previous bitmap owner and the IO bitmap contents:
@@ -544,6 +560,7 @@ handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss)
                tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
                return;
        }
+
        if (likely(next == tss->io_bitmap_owner)) {
                /*
                 * Previous owner of the bitmap (hence the bitmap content)
@@ -671,20 +688,11 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
                set_iopl_mask(next->iopl);
 
        /*
-        * Now maybe reload the debug registers
+        * Now maybe handle debug registers and/or IO bitmaps
         */
-       if (unlikely(next->debugreg[7])) {
-               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(next->debugreg[6], 6);
-               set_debugreg(next->debugreg[7], 7);
-       }
-
-       if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))
-               handle_io_bitmap(next, tss);
+       if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
+           || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))
+               __switch_to_xtra(next_p, tss);
 
        disable_tsc(prev_p, next_p);
 
index fd7eaf7..d3db03f 100644 (file)
@@ -468,8 +468,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                                  for(i=0; i<4; i++)
                                          if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
                                                  goto out_tsk;
+                                 if (data)
+                                         set_tsk_thread_flag(child, TIF_DEBUG);
+                                 else
+                                         clear_tsk_thread_flag(child, TIF_DEBUG);
                          }
-
                          addr -= (long) &dummy->u_debugreg;
                          addr = addr >> 2;
                          child->thread.debugreg[addr] = data;
index 2833fa2..54d6d7a 100644 (file)
@@ -140,6 +140,8 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SECCOMP            8       /* secure computing */
 #define TIF_RESTORE_SIGMASK    9       /* restore signal mask in do_signal() */
 #define TIF_MEMDIE             16
+#define TIF_DEBUG              17      /* uses debug registers */
+#define TIF_IO_BITMAP          18      /* uses I/O bitmap */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
@@ -151,6 +153,8 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1<<TIF_SECCOMP)
 #define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
+#define _TIF_DEBUG             (1<<TIF_DEBUG)
+#define _TIF_IO_BITMAP         (1<<TIF_IO_BITMAP)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
@@ -159,6 +163,9 @@ static inline struct thread_info *current_thread_info(void)
 /* work to do on any return to u-space */
 #define _TIF_ALLWORK_MASK      (0x0000FFFF & ~_TIF_SECCOMP)
 
+/* flags to check in __switch_to() */
+#define _TIF_WORK_CTXSW (_TIF_DEBUG|_TIF_IO_BITMAP)
+
 /*
  * Thread-synchronous status.
  *