diff options
author | Stephane Eranian <eranian@hpl.hp.com> | 2006-07-09 21:12:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-09 21:47:12 -0400 |
commit | b3cf257623fabd8f1ee6700a6d328cc1c5da5a1d (patch) | |
tree | 28b98f21dd108864d2edc11d179cb48c118b2cf8 /arch/i386 | |
parent | 09075ef0fd585fb093bb9a6cd1240272114f89cf (diff) |
[PATCH] i386: use thread_info flags for debug regs and IO bitmaps
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>
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/kernel/ioport.c | 1 | ||||
-rw-r--r-- | arch/i386/kernel/process.c | 50 | ||||
-rw-r--r-- | arch/i386/kernel/ptrace.c | 5 |
3 files changed, 34 insertions, 22 deletions
diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c index 79026f026b85..498e8bc197d5 100644 --- a/arch/i386/kernel/ioport.c +++ b/arch/i386/kernel/ioport.c | |||
@@ -79,6 +79,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) | |||
79 | 79 | ||
80 | memset(bitmap, 0xff, IO_BITMAP_BYTES); | 80 | memset(bitmap, 0xff, IO_BITMAP_BYTES); |
81 | t->io_bitmap_ptr = bitmap; | 81 | t->io_bitmap_ptr = bitmap; |
82 | set_thread_flag(TIF_IO_BITMAP); | ||
82 | } | 83 | } |
83 | 84 | ||
84 | /* | 85 | /* |
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 94e2c87edeaa..923bb292f47f 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c | |||
@@ -359,16 +359,16 @@ EXPORT_SYMBOL(kernel_thread); | |||
359 | */ | 359 | */ |
360 | void exit_thread(void) | 360 | void exit_thread(void) |
361 | { | 361 | { |
362 | struct task_struct *tsk = current; | ||
363 | struct thread_struct *t = &tsk->thread; | ||
364 | |||
365 | /* The process may have allocated an io port bitmap... nuke it. */ | 362 | /* The process may have allocated an io port bitmap... nuke it. */ |
366 | if (unlikely(NULL != t->io_bitmap_ptr)) { | 363 | if (unlikely(test_thread_flag(TIF_IO_BITMAP))) { |
364 | struct task_struct *tsk = current; | ||
365 | struct thread_struct *t = &tsk->thread; | ||
367 | int cpu = get_cpu(); | 366 | int cpu = get_cpu(); |
368 | struct tss_struct *tss = &per_cpu(init_tss, cpu); | 367 | struct tss_struct *tss = &per_cpu(init_tss, cpu); |
369 | 368 | ||
370 | kfree(t->io_bitmap_ptr); | 369 | kfree(t->io_bitmap_ptr); |
371 | t->io_bitmap_ptr = NULL; | 370 | t->io_bitmap_ptr = NULL; |
371 | clear_thread_flag(TIF_IO_BITMAP); | ||
372 | /* | 372 | /* |
373 | * Careful, clear this in the TSS too: | 373 | * Careful, clear this in the TSS too: |
374 | */ | 374 | */ |
@@ -387,6 +387,7 @@ void flush_thread(void) | |||
387 | 387 | ||
388 | memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); | 388 | memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); |
389 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); | 389 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); |
390 | clear_tsk_thread_flag(tsk, TIF_DEBUG); | ||
390 | /* | 391 | /* |
391 | * Forget coprocessor state.. | 392 | * Forget coprocessor state.. |
392 | */ | 393 | */ |
@@ -431,7 +432,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, | |||
431 | savesegment(gs,p->thread.gs); | 432 | savesegment(gs,p->thread.gs); |
432 | 433 | ||
433 | tsk = current; | 434 | tsk = current; |
434 | if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) { | 435 | if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) { |
435 | p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); | 436 | p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); |
436 | if (!p->thread.io_bitmap_ptr) { | 437 | if (!p->thread.io_bitmap_ptr) { |
437 | p->thread.io_bitmap_max = 0; | 438 | p->thread.io_bitmap_max = 0; |
@@ -439,6 +440,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, | |||
439 | } | 440 | } |
440 | memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr, | 441 | memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr, |
441 | IO_BITMAP_BYTES); | 442 | IO_BITMAP_BYTES); |
443 | set_tsk_thread_flag(p, TIF_IO_BITMAP); | ||
442 | } | 444 | } |
443 | 445 | ||
444 | /* | 446 | /* |
@@ -533,10 +535,24 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) | |||
533 | return 1; | 535 | return 1; |
534 | } | 536 | } |
535 | 537 | ||
536 | static inline void | 538 | static noinline void __switch_to_xtra(struct task_struct *next_p, |
537 | handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss) | 539 | struct tss_struct *tss) |
538 | { | 540 | { |
539 | if (!next->io_bitmap_ptr) { | 541 | struct thread_struct *next; |
542 | |||
543 | next = &next_p->thread; | ||
544 | |||
545 | if (test_tsk_thread_flag(next_p, TIF_DEBUG)) { | ||
546 | set_debugreg(next->debugreg[0], 0); | ||
547 | set_debugreg(next->debugreg[1], 1); | ||
548 | set_debugreg(next->debugreg[2], 2); | ||
549 | set_debugreg(next->debugreg[3], 3); | ||
550 | /* no 4 and 5 */ | ||
551 | set_debugreg(next->debugreg[6], 6); | ||
552 | set_debugreg(next->debugreg[7], 7); | ||
553 | } | ||
554 | |||
555 | if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | ||
540 | /* | 556 | /* |
541 | * Disable the bitmap via an invalid offset. We still cache | 557 | * Disable the bitmap via an invalid offset. We still cache |
542 | * the previous bitmap owner and the IO bitmap contents: | 558 | * the previous bitmap owner and the IO bitmap contents: |
@@ -544,6 +560,7 @@ handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss) | |||
544 | tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; | 560 | tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; |
545 | return; | 561 | return; |
546 | } | 562 | } |
563 | |||
547 | if (likely(next == tss->io_bitmap_owner)) { | 564 | if (likely(next == tss->io_bitmap_owner)) { |
548 | /* | 565 | /* |
549 | * Previous owner of the bitmap (hence the bitmap content) | 566 | * 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 | |||
671 | set_iopl_mask(next->iopl); | 688 | set_iopl_mask(next->iopl); |
672 | 689 | ||
673 | /* | 690 | /* |
674 | * Now maybe reload the debug registers | 691 | * Now maybe handle debug registers and/or IO bitmaps |
675 | */ | 692 | */ |
676 | if (unlikely(next->debugreg[7])) { | 693 | if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW)) |
677 | set_debugreg(next->debugreg[0], 0); | 694 | || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) |
678 | set_debugreg(next->debugreg[1], 1); | 695 | __switch_to_xtra(next_p, tss); |
679 | set_debugreg(next->debugreg[2], 2); | ||
680 | set_debugreg(next->debugreg[3], 3); | ||
681 | /* no 4 and 5 */ | ||
682 | set_debugreg(next->debugreg[6], 6); | ||
683 | set_debugreg(next->debugreg[7], 7); | ||
684 | } | ||
685 | |||
686 | if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) | ||
687 | handle_io_bitmap(next, tss); | ||
688 | 696 | ||
689 | disable_tsc(prev_p, next_p); | 697 | disable_tsc(prev_p, next_p); |
690 | 698 | ||
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index fd7eaf7866e0..d3db03f4085d 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c | |||
@@ -468,8 +468,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
468 | for(i=0; i<4; i++) | 468 | for(i=0; i<4; i++) |
469 | if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1) | 469 | if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1) |
470 | goto out_tsk; | 470 | goto out_tsk; |
471 | if (data) | ||
472 | set_tsk_thread_flag(child, TIF_DEBUG); | ||
473 | else | ||
474 | clear_tsk_thread_flag(child, TIF_DEBUG); | ||
471 | } | 475 | } |
472 | |||
473 | addr -= (long) &dummy->u_debugreg; | 476 | addr -= (long) &dummy->u_debugreg; |
474 | addr = addr >> 2; | 477 | addr = addr >> 2; |
475 | child->thread.debugreg[addr] = data; | 478 | child->thread.debugreg[addr] = data; |