summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2003-04-01 00:18:55 +0000
committerjeff <jeff@FreeBSD.org>2003-04-01 00:18:55 +0000
commit420a77ecd5237fe6d8d85dfc52e0e7050554b768 (patch)
treed76cda4e540786cf76f11bcb84ebefd1fd2bfd17
parent56865cc54968bbe0d21f2909d13cfade62bb789d (diff)
downloadFreeBSD-src-420a77ecd5237fe6d8d85dfc52e0e7050554b768.zip
FreeBSD-src-420a77ecd5237fe6d8d85dfc52e0e7050554b768.tar.gz
- Define a new md function 'casuptr'. This atomically compares and sets
a pointer that is in user space. It will be used as the basic primitive for a kernel supported user space lock implementation. - Implement this function in x86's support.s - Provide stubs that return -1 in all other architectures. Implementations will follow along shortly. Reviewed by: jake
-rw-r--r--sys/alpha/alpha/machdep.c6
-rw-r--r--sys/amd64/amd64/support.S31
-rw-r--r--sys/amd64/amd64/support.s31
-rw-r--r--sys/i386/i386/support.s31
-rw-r--r--sys/ia64/ia64/machdep.c7
-rw-r--r--sys/pc98/i386/machdep.c8
-rw-r--r--sys/pc98/pc98/machdep.c8
-rw-r--r--sys/powerpc/aim/machdep.c8
-rw-r--r--sys/powerpc/powerpc/machdep.c8
-rw-r--r--sys/sparc64/sparc64/machdep.c7
-rw-r--r--sys/sys/systm.h1
11 files changed, 146 insertions, 0 deletions
diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c
index 055d3f8..50627d9 100644
--- a/sys/alpha/alpha/machdep.c
+++ b/sys/alpha/alpha/machdep.c
@@ -2324,3 +2324,9 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
pcpu->pc_idlepcb.apcb_ptbr = thread0.td_pcb->pcb_hw.apcb_ptbr;
pcpu->pc_current_asngen = 1;
}
+
+intptr_t
+casuptr(intptr_t *p, intptr_t old, intptr_t new)
+{
+ return (-1);
+}
diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S
index 5e57315..cc53683 100644
--- a/sys/amd64/amd64/support.S
+++ b/sys/amd64/amd64/support.S
@@ -1173,6 +1173,37 @@ fastmove_tail_fault:
#endif /* I586_CPU && defined(DEV_NPX) */
/*
+ * casuptr. Compare and set user pointer. Returns -1 or the current value.
+ */
+ENTRY(casuptr)
+ movl PCPU(CURPCB),%ecx
+ movl $fusufault,PCB_ONFAULT(%ecx)
+ movl 4(%esp),%edx /* dst */
+ movl 8(%esp),%eax /* old */
+ movl 12(%esp),%ecx /* new */
+
+ cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */
+ ja fusufault
+
+#if defined(SMP)
+ lock cmpxchgl %ecx, (%edx) /* Compare and set. */
+#else /* !SMP */
+ cmpxchgl %ecx, (%edx)
+#endif /* !SMP */
+
+ /*
+ * We store the current value regardless of the success of the
+ * cmpxchg. Calling code checks for new == return to determine
+ * success.
+ */
+ movl (%edx), %eax
+
+ movl PCPU(CURPCB),%ecx
+ movl $fusufault,PCB_ONFAULT(%ecx)
+ movl $0,PCB_ONFAULT(%ecx)
+ ret
+
+/*
* fu{byte,sword,word} - MP SAFE
*
* Fetch a byte (sword, word) from user memory
diff --git a/sys/amd64/amd64/support.s b/sys/amd64/amd64/support.s
index 5e57315..cc53683 100644
--- a/sys/amd64/amd64/support.s
+++ b/sys/amd64/amd64/support.s
@@ -1173,6 +1173,37 @@ fastmove_tail_fault:
#endif /* I586_CPU && defined(DEV_NPX) */
/*
+ * casuptr. Compare and set user pointer. Returns -1 or the current value.
+ */
+ENTRY(casuptr)
+ movl PCPU(CURPCB),%ecx
+ movl $fusufault,PCB_ONFAULT(%ecx)
+ movl 4(%esp),%edx /* dst */
+ movl 8(%esp),%eax /* old */
+ movl 12(%esp),%ecx /* new */
+
+ cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */
+ ja fusufault
+
+#if defined(SMP)
+ lock cmpxchgl %ecx, (%edx) /* Compare and set. */
+#else /* !SMP */
+ cmpxchgl %ecx, (%edx)
+#endif /* !SMP */
+
+ /*
+ * We store the current value regardless of the success of the
+ * cmpxchg. Calling code checks for new == return to determine
+ * success.
+ */
+ movl (%edx), %eax
+
+ movl PCPU(CURPCB),%ecx
+ movl $fusufault,PCB_ONFAULT(%ecx)
+ movl $0,PCB_ONFAULT(%ecx)
+ ret
+
+/*
* fu{byte,sword,word} - MP SAFE
*
* Fetch a byte (sword, word) from user memory
diff --git a/sys/i386/i386/support.s b/sys/i386/i386/support.s
index 5e57315..cc53683 100644
--- a/sys/i386/i386/support.s
+++ b/sys/i386/i386/support.s
@@ -1173,6 +1173,37 @@ fastmove_tail_fault:
#endif /* I586_CPU && defined(DEV_NPX) */
/*
+ * casuptr. Compare and set user pointer. Returns -1 or the current value.
+ */
+ENTRY(casuptr)
+ movl PCPU(CURPCB),%ecx
+ movl $fusufault,PCB_ONFAULT(%ecx)
+ movl 4(%esp),%edx /* dst */
+ movl 8(%esp),%eax /* old */
+ movl 12(%esp),%ecx /* new */
+
+ cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */
+ ja fusufault
+
+#if defined(SMP)
+ lock cmpxchgl %ecx, (%edx) /* Compare and set. */
+#else /* !SMP */
+ cmpxchgl %ecx, (%edx)
+#endif /* !SMP */
+
+ /*
+ * We store the current value regardless of the success of the
+ * cmpxchg. Calling code checks for new == return to determine
+ * success.
+ */
+ movl (%edx), %eax
+
+ movl PCPU(CURPCB),%ecx
+ movl $fusufault,PCB_ONFAULT(%ecx)
+ movl $0,PCB_ONFAULT(%ecx)
+ ret
+
+/*
* fu{byte,sword,word} - MP SAFE
*
* Fetch a byte (sword, word) from user memory
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c
index bdc8dca..fb16a72 100644
--- a/sys/ia64/ia64/machdep.c
+++ b/sys/ia64/ia64/machdep.c
@@ -1444,3 +1444,10 @@ ia64_rse_previous_frame(u_int64_t *bsp, int size)
return bsp - size - rnats;
}
+
+intptr_t
+casuptr(intptr_t *p, intptr_t old, intptr_t new)
+{
+ return (-1);
+}
+
diff --git a/sys/pc98/i386/machdep.c b/sys/pc98/i386/machdep.c
index 2b2b979..ac597ff 100644
--- a/sys/pc98/i386/machdep.c
+++ b/sys/pc98/i386/machdep.c
@@ -2803,3 +2803,11 @@ outb(u_int port, u_char data)
}
#endif /* DDB */
+
+
+intptr_t
+casuptr(intptr_t *p, intptr_t old, intptr_t new)
+{
+ return (-1);
+}
+
diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c
index 2b2b979..ac597ff 100644
--- a/sys/pc98/pc98/machdep.c
+++ b/sys/pc98/pc98/machdep.c
@@ -2803,3 +2803,11 @@ outb(u_int port, u_char data)
}
#endif /* DDB */
+
+
+intptr_t
+casuptr(intptr_t *p, intptr_t old, intptr_t new)
+{
+ return (-1);
+}
+
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index 54661aa..e904fa3 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -752,3 +752,11 @@ kcopy(const void *src, void *dst, size_t len)
td->td_pcb->pcb_onfault = oldfault;
return (0);
}
+
+
+intptr_t
+casuptr(intptr_t *p, intptr_t old, intptr_t new)
+{
+ return (-1);
+}
+
diff --git a/sys/powerpc/powerpc/machdep.c b/sys/powerpc/powerpc/machdep.c
index 54661aa..e904fa3 100644
--- a/sys/powerpc/powerpc/machdep.c
+++ b/sys/powerpc/powerpc/machdep.c
@@ -752,3 +752,11 @@ kcopy(const void *src, void *dst, size_t len)
td->td_pcb->pcb_onfault = oldfault;
return (0);
}
+
+
+intptr_t
+casuptr(intptr_t *p, intptr_t old, intptr_t new)
+{
+ return (-1);
+}
+
diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c
index fa2ba40..b662961 100644
--- a/sys/sparc64/sparc64/machdep.c
+++ b/sys/sparc64/sparc64/machdep.c
@@ -703,3 +703,10 @@ set_fpregs(struct thread *td, struct fpreg *fpregs)
tf->tf_gsr = fpregs->fr_gsr;
return (0);
}
+
+intptr_t
+casuptr(intptr_t *p, intptr_t old, intptr_t new)
+{
+ return (-1);
+}
+
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 5443d01..698ff07 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -197,6 +197,7 @@ int suword(void *base, long word);
int suword16(void *base, int word);
int suword32(void *base, int32_t word);
int suword64(void *base, int64_t word);
+intptr_t casuptr(intptr_t *p, intptr_t old, intptr_t new);
void realitexpire(void *);
OpenPOWER on IntegriCloud