From b8db34d2801c0c22aa95ab0fd352b462b73c84d9 Mon Sep 17 00:00:00 2001 From: Jeff Roberson Date: Tue, 1 Apr 2003 00:18:55 +0000 Subject: [PATCH] - 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 --- sys/alpha/alpha/machdep.c | 6 ++++++ sys/amd64/amd64/support.S | 31 +++++++++++++++++++++++++++++++ sys/amd64/amd64/support.s | 31 +++++++++++++++++++++++++++++++ sys/i386/i386/support.s | 31 +++++++++++++++++++++++++++++++ sys/ia64/ia64/machdep.c | 7 +++++++ sys/pc98/i386/machdep.c | 8 ++++++++ sys/pc98/pc98/machdep.c | 8 ++++++++ sys/powerpc/aim/machdep.c | 8 ++++++++ sys/powerpc/powerpc/machdep.c | 8 ++++++++ sys/sparc64/sparc64/machdep.c | 7 +++++++ sys/sys/systm.h | 1 + 11 files changed, 146 insertions(+) diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c index 055d3f8e689..50627d9f32d 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 5e573159804..cc53683b0a8 100644 --- a/sys/amd64/amd64/support.S +++ b/sys/amd64/amd64/support.S @@ -1172,6 +1172,37 @@ fastmove_tail_fault: ret #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 * diff --git a/sys/amd64/amd64/support.s b/sys/amd64/amd64/support.s index 5e573159804..cc53683b0a8 100644 --- a/sys/amd64/amd64/support.s +++ b/sys/amd64/amd64/support.s @@ -1172,6 +1172,37 @@ fastmove_tail_fault: ret #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 * diff --git a/sys/i386/i386/support.s b/sys/i386/i386/support.s index 5e573159804..cc53683b0a8 100644 --- a/sys/i386/i386/support.s +++ b/sys/i386/i386/support.s @@ -1172,6 +1172,37 @@ fastmove_tail_fault: ret #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 * diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index bdc8dca4d55..fb16a72d8e0 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 2b2b979e515..ac597ff4912 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 2b2b979e515..ac597ff4912 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 54661aa08c6..e904fa320fb 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 54661aa08c6..e904fa320fb 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 fa2ba40fa1c..b6629615278 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 5443d015c76..698ff07b452 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 *);