* Atomicity & preemptive kernels @ 2002-06-10 19:44 Justin Carlson 2002-06-10 22:14 ` Jun Sun 0 siblings, 1 reply; 5+ messages in thread From: Justin Carlson @ 2002-06-10 19:44 UTC (permalink / raw) To: linux-mips I know we're not there yet, but I'm trying to understand some issues with rml's preemptive kernel and ASID's. While doing a virtually-tagged hit invalidate of a cache, I was going to write code something like this; set_entryhi(CPU_CONTEXT(cpu, mm->vm_mm)); hit_invalidate_range(start, end); set_entryhi(CPU_CONTEXT(cpu, current->mm)); Insofar as I understand current kernel scheduling guarantees, this is safe because we won't reschedule while running in kernel mode. But, if I'm looking ahead to the preemptive kernel, then I think there is a slight window for a race in between the reading of current->mm and the setting of entryhi. Something like this: current->mm->context is read * kernel reschedules. * switch_mm() called * current->mm->context changes on return to this process entryhi is set to the wrong context. Is this a real race? If so, is there any way around it other than locally disabling interrupts around the restoration of the context? -Justin ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Atomicity & preemptive kernels 2002-06-10 19:44 Atomicity & preemptive kernels Justin Carlson @ 2002-06-10 22:14 ` Jun Sun 2002-06-11 0:00 ` Justin Carlson 0 siblings, 1 reply; 5+ messages in thread From: Jun Sun @ 2002-06-10 22:14 UTC (permalink / raw) To: Justin Carlson; +Cc: linux-mips Justin Carlson wrote: > I know we're not there yet, but I'm trying to understand some issues > with rml's preemptive kernel and ASID's. > > While doing a virtually-tagged hit invalidate of a cache, I was going to > write code something like this; > > set_entryhi(CPU_CONTEXT(cpu, mm->vm_mm)); > hit_invalidate_range(start, end); > set_entryhi(CPU_CONTEXT(cpu, current->mm)); > > Insofar as I understand current kernel scheduling guarantees, this is > safe because we won't reschedule while running in kernel mode. But, if > I'm looking ahead to the preemptive kernel, then I think there is a > slight window for a race in between the reading of current->mm and > the setting of entryhi. Something like this: > > current->mm->context is read > * kernel reschedules. > * switch_mm() called > * current->mm->context changes on return to this process > entryhi is set to the wrong context. > > Is this a real race? I am not sure if I am following your logic, but I don't see a race condition here. Once current->mm is read into a register, the register is saved into stack when an interrupt happens (which later incurs a reschedule presumbably). When the current preempted process comes back later, it goes back to the "tail" of do_IRQ(), followed by restoring the registers. Since the register now holds the right value, set_entryhi() should be correct. BTW, I have preemptiable kernel working fine under both UP and SMP. If there is much interestes, I will publish it on the list. Jun ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Atomicity & preemptive kernels 2002-06-10 22:14 ` Jun Sun @ 2002-06-11 0:00 ` Justin Carlson 2002-06-11 18:44 ` Jun Sun 0 siblings, 1 reply; 5+ messages in thread From: Justin Carlson @ 2002-06-11 0:00 UTC (permalink / raw) To: Jun Sun; +Cc: linux-mips On Mon, 2002-06-10 at 15:14, Jun Sun wrote: > I am not sure if I am following your logic, but I don't see a race condition here. > > Once current->mm is read into a register, the register is saved into stack > when an interrupt happens (which later incurs a reschedule presumbably). When > the current preempted process comes back later, it goes back to the "tail" of > do_IRQ(), followed by restoring the registers. Since the register now holds > the right value, set_entryhi() should be correct. > You've described exactly what happens. The only problem is, it's possible the underlying value for current->mm has changed. It's a *really* narrow window, at most a cycle or two, but I think it is there. In addition, even if you hit the window, to trigger wrong behavior it requires that you also saturate the local ASID space, invoking the tlb flush and asid reset in get_mmu_context(). The change that's introduced by the preemptive kernel is that switch_mm() can be called after an interrupt. So, with some hypothetical assembly, the code flow looks like this: lw $1, 120($29) ; Load current->mm->context into a register * Interrupt happens * * reschedule happens, switch_mm() is called * * get_new_mmu_context() invoked, starts a new ASID cycle. * current->mm->context for the original process changes * (sometime later) switch back to original process mtc0 $entryhi, $1 ; stale context put back into entryhi! Does that make more sense? It's really a tiny race, but I think it's a real one. -Justin ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Atomicity & preemptive kernels 2002-06-11 0:00 ` Justin Carlson @ 2002-06-11 18:44 ` Jun Sun 2002-06-11 19:56 ` Justin Carlson 0 siblings, 1 reply; 5+ messages in thread From: Jun Sun @ 2002-06-11 18:44 UTC (permalink / raw) To: Justin Carlson; +Cc: linux-mips Justin Carlson wrote: > On Mon, 2002-06-10 at 15:14, Jun Sun wrote: > >>I am not sure if I am following your logic, but I don't see a race condition here. >> >>Once current->mm is read into a register, the register is saved into stack >>when an interrupt happens (which later incurs a reschedule presumbably). When >>the current preempted process comes back later, it goes back to the "tail" of >>do_IRQ(), followed by restoring the registers. Since the register now holds >>the right value, set_entryhi() should be correct. >> >> > > You've described exactly what happens. The only problem is, it's > possible the underlying value for current->mm has changed. It's a > *really* narrow window, at most a cycle or two, but I think it is > there. In addition, even if you hit the window, to trigger wrong > behavior it requires that you also saturate the local ASID space, > invoking the tlb flush and asid reset in get_mmu_context(). > > The change that's introduced by the preemptive kernel is that > switch_mm() can be called after an interrupt. So, with some > hypothetical assembly, the code flow looks like this: > > lw $1, 120($29) ; Load current->mm->context into a register > * Interrupt happens * > * reschedule happens, switch_mm() is called * > * get_new_mmu_context() invoked, starts a new ASID cycle. > * current->mm->context for the original process changes > * (sometime later) switch back to original process > mtc0 $entryhi, $1 ; stale context put back into entryhi! > > Does that make more sense? It's really a tiny race, but I think it's a > real one. > I see your point now. However, the race is not there. switch_mm() is only called from inside schedule() function, which as a whole is preemption-safe. In other words, the above event sequence won't cause a context switch until we exit from schedule() function. Jun ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Atomicity & preemptive kernels 2002-06-11 18:44 ` Jun Sun @ 2002-06-11 19:56 ` Justin Carlson 0 siblings, 0 replies; 5+ messages in thread From: Justin Carlson @ 2002-06-11 19:56 UTC (permalink / raw) To: Jun Sun; +Cc: linux-mips On Tue, 2002-06-11 at 11:44, Jun Sun wrote: > I see your point now. > > However, the race is not there. switch_mm() is only called from inside > schedule() function, which as a whole is preemption-safe. In other words, the > above event sequence won't cause a context switch until we exit from > schedule() function. > Yes, but the initial code I cited was explicitly not in the schedule function. It was an icache_flush_page() implementation. Just something to be careful of. I think it's going to bite more than a few people as a bug that's about impossible to track down... -Justin ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2002-06-11 19:55 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2002-06-10 19:44 Atomicity & preemptive kernels Justin Carlson 2002-06-10 22:14 ` Jun Sun 2002-06-11 0:00 ` Justin Carlson 2002-06-11 18:44 ` Jun Sun 2002-06-11 19:56 ` Justin Carlson
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.