Messages in this thread Patch in this message | | | Date | Fri, 30 Jul 1999 19:34:01 +0200 | From | Manfred Spraul <> | Subject | [RFC] [PATCH] lazy TLB: possible bug, some notes (2.3.12) |
| |
1) I've attached a small patch which should fix 2 possible problems on the i386. * mm->cpu_vm_mask was not set on crossing TLB flushes. * there was a race in flush_tlb_current_task() between setting mm->cpu_vm_mask and the IPI which could modify cpu_vm_mask.
Since flush_tlb_current_task() is now identical to flush_tlb_mm(current->mm), I'd remove flush_tlb_current_task() and change the macro for flush_tlb(). [in include/asm/pgtable.h]
2) I think it should be possible to call start_lazy_tlb() even if the thread is already in the lazy-tlb mode. i.e. multiple calls to start_lazy_tlb() should be possible as long as you call end_lazy_tlb() for every start_lazy_tlb() call. Curently, this would oops.
3) I noticed that 2.3.12 breaks the PPC mm implementation: mmu_context_overflow() assumes that it can get to all mm's by looking at tsk->mm for all tasks in the system. (arch/ppc/mm/init.c)
This is not correct any more: if a user thread executes sys_bdflush(), then this mm will not be referenced from tsk->mm. [I don't have a PPC, but it looks wrong]
-- Manfred--- 2.3/arch/i386/kernel/smp.c Thu Jul 29 15:23:06 1999 +++ build-2.3/arch/i386/kernel/smp.c Fri Jul 30 19:27:02 1999 @@ -1617,6 +1617,8 @@ if (test_bit(cpu, &smp_invalidate_needed)) { clear_bit(cpu, &smp_invalidate_needed); local_flush_tlb(); + if(current->mm) + atomic_set_mask(1 << cpu, ¤t->mm->cpu_vm_mask); } --stuck; if (!stuck) { @@ -1637,14 +1639,16 @@ */ void flush_tlb_current_task(void) { - unsigned long vm_mask = 1 << current->processor; struct mm_struct *mm = current->mm; + unsigned long vm_mask = 1 << current->processor; + unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask; - if (mm->cpu_vm_mask != vm_mask) { - flush_tlb_others(mm->cpu_vm_mask & ~vm_mask); + mm->cpu_vm_mask = 0; + if (current->active_mm == mm) { mm->cpu_vm_mask = vm_mask; + local_flush_tlb(); } - local_flush_tlb(); + flush_tlb_others(cpu_mask); } void flush_tlb_mm(struct mm_struct * mm)
| |