- Add a new argument to cpu_switch. This is a pointer to a mutex that

oldthread should point at before we return.
 - When cpu_switch() is called the td_lock pointer in the old thread may
   point at the blocked lock.  This prevents other processors from
   switching into this thread while we're still switching out.  Wait
   until we're done deactivating the vmspace before we release the
   thread by assigning to td_lock.
 - Before we can activate the new vmspace we must make sure that the new
   thread is not assigned to the blocked lock.  It may be in the process
   of switching out on another cpu.  Spin until the new thread is
   available.
This commit is contained in:
Jeff Roberson 2007-06-05 00:16:43 +00:00
parent ebb6b0c0ec
commit 5d68dad329

View File

@ -73,19 +73,16 @@ ENTRY(cpu_throw)
movq TD_PCB(%rsi),%rdx /* newtd->td_proc */
movq PCB_CR3(%rdx),%rdx
movq %rdx,%cr3 /* new address space */
/* set bit in new pm_active */
movq TD_PROC(%rsi),%rdx
movq P_VMSPACE(%rdx), %rdx
LK btsl %eax, VM_PMAP+PM_ACTIVE(%rdx) /* set new */
jmp sw1
jmp swact
/*
* cpu_switch(old, new)
* cpu_switch(old, new, mtx)
*
* Save the current thread state, then select the next thread to run
* and load its state.
* %rdi = oldtd
* %rsi = newtd
* %rdx = mtx
*/
ENTRY(cpu_switch)
/* Switch to new thread. First, save context. */
@ -147,17 +144,33 @@ ENTRY(cpu_switch)
movq TD_PCB(%rsi),%r8
/* switch address space */
movq PCB_CR3(%r8),%rdx
movq PCB_CR3(%r8),%rcx
movq %cr3,%rax
cmpq %rdx,%rax /* Same address space? */
je sw1
movq %rdx,%cr3 /* new address space */
cmpq %rcx,%rax /* Same address space? */
jne swinact
movq %rdx, TD_LOCK(%rdi) /* Release the old thread */
/* Wait for the new thread to become unblocked */
movq $blocked_lock, %rdx
1:
movq TD_LOCK(%rsi),%rcx
cmpq %rcx, %rdx
je 1b
jmp sw1
swinact:
movq %rcx,%cr3 /* new address space */
movl PCPU(CPUID), %eax
/* Release bit from old pmap->pm_active */
movq TD_PROC(%rdi), %rdx /* oldproc */
movq P_VMSPACE(%rdx), %rdx
LK btrl %eax, VM_PMAP+PM_ACTIVE(%rdx) /* clear old */
movq TD_PROC(%rdi), %rcx /* oldproc */
movq P_VMSPACE(%rcx), %rcx
LK btrl %eax, VM_PMAP+PM_ACTIVE(%rcx) /* clear old */
movq %rdx, TD_LOCK(%rdi) /* Release the old thread */
swact:
/* Wait for the new thread to become unblocked */
movq $blocked_lock, %rdx
1:
movq TD_LOCK(%rsi),%rcx
cmpq %rcx, %rdx
je 1b
/* Set bit in new pmap->pm_active */
movq TD_PROC(%rsi),%rdx /* newproc */