Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b3cf2576 authored by Stephane Eranian's avatar Stephane Eranian Committed by Linus Torvalds
Browse files

[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: default avatarStephane Eranian <eranian@hpl.hp.com>
Signed-off-by: default avatarChuck Ebbert <76306.1226@compuserve.com>
Acked-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 09075ef0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
	}

	/*
+29 −21
Original line number Diff line number Diff line
@@ -359,16 +359,16 @@ EXPORT_SYMBOL(kernel_thread);
 */
void exit_thread(void)
{
	/* The process may have allocated an io port bitmap... nuke it. */
	if (unlikely(test_thread_flag(TIF_IO_BITMAP))) {
		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)) {
		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);

+4 −1
Original line number Diff line number Diff line
@@ -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;
+7 −0
Original line number Diff line number Diff line
@@ -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.
 *