- Prevent LOCKDEBUG from complaining if we do rw_tryenter() on a lock

that we already own.
- Add an assembly stub for rw_tryenter().
This commit is contained in:
ad 2008-01-25 19:02:31 +00:00
parent 85adc21249
commit 501eb05cc2
4 changed files with 95 additions and 15 deletions

View File

@ -1,7 +1,7 @@
/* $NetBSD: lock_stubs.S,v 1.12 2007/12/21 19:18:13 dsl Exp $ */
/* $NetBSD: lock_stubs.S,v 1.13 2008/01/25 19:02:32 ad Exp $ */
/*-
* Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -242,6 +242,43 @@ NENTRY(rw_exit)
3: jmp _C_LABEL(rw_vector_exit)
/*
* int rw_tryenter(krwlock_t *rwl, krw_t op);
*
* Try to acquire one hold on a RW lock.
*/
NENTRY(rw_tryenter)
cmpl $RW_READER, %esi
jne 2f
/*
* Reader: this is the most common case.
*/
1: movq RW_OWNER(%rdi), %rax
testb $(RW_WRITE_LOCKED|RW_WRITE_WANTED), %al
leaq RW_READ_INCR(%rax), %rdx
jnz 3f
LOCK(8)
cmpxchgq %rdx, RW_OWNER(%rdi)
movl $0, %eax
setz %al
ret
/*
* Writer: if the compare-and-set fails, don't bother retrying.
*/
2: movq CPUVAR(CURLWP), %rcx
xorq %rax, %rax
orq $RW_WRITE_LOCKED, %rcx
LOCK(9)
cmpxchgq %rcx, RW_OWNER(%rdi)
movl $0, %eax
setz %al
ret
3: xorl %eax, %eax
ret
#endif /* LOCKDEBUG */
/*
@ -285,7 +322,8 @@ NENTRY(__cpu_simple_lock_try)
#ifndef LOCKDEBUG
LABEL(x86_lockpatch)
.quad .Lpatch1, .Lpatch2, .Lpatch3, .Lpatch4
.quad .Lpatch5, .Lpatch6, .Lpatch7
.quad .Lpatch5, .Lpatch6, .Lpatch7, .Lpatch8
.quad .Lpatch9
#ifdef FULL
.quad .Lpatch11
#endif

View File

@ -1,7 +1,7 @@
/* $NetBSD: lock_stubs.S,v 1.12 2007/12/20 23:46:10 ad Exp $ */
/* $NetBSD: lock_stubs.S,v 1.13 2008/01/25 19:02:32 ad Exp $ */
/*-
* Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -44,7 +44,7 @@
*/
#include <machine/asm.h>
__KERNEL_RCSID(0, "$NetBSD: lock_stubs.S,v 1.12 2007/12/20 23:46:10 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: lock_stubs.S,v 1.13 2008/01/25 19:02:32 ad Exp $");
#include "opt_multiprocessor.h"
#include "opt_lockdebug.h"
@ -171,6 +171,44 @@ ENTRY(rw_exit)
*/
3: jmp _C_LABEL(rw_vector_exit)
/*
* int rw_tryenter(krwlock_t *rwl, krw_t op);
*
* Try to acquire one hold on a RW lock.
*/
ENTRY(rw_tryenter)
movl 4(%esp), %edx
cmpl $RW_READER, 8(%esp)
jne 2f
/*
* Reader
*/
1: movl RW_OWNER(%edx), %eax
testb $(RW_WRITE_LOCKED|RW_WRITE_WANTED), %al
leal RW_READ_INCR(%eax), %ecx
jnz 3f
LOCK(12)
cmpxchgl %ecx, RW_OWNER(%edx)
movl $0, %eax
setz %al
ret
/*
* Writer
*/
2: movl CPUVAR(CURLWP), %ecx
xorl %eax, %eax
orl $RW_WRITE_LOCKED, %ecx
LOCK(13)
cmpxchgl %ecx, RW_OWNER(%edx)
movl $0, %eax
setz %al
ret
3: xorl %eax, %eax
ret
#ifndef __XEN__
/*
@ -313,7 +351,8 @@ NENTRY(__cpu_simple_lock_try)
#ifndef LOCKDEBUG
LABEL(x86_lockpatch)
.long .Lpatch1, .Lpatch2, .Lpatch3, .Lpatch4
.long .Lpatch5, .Lpatch6, .Lpatch7
.long .Lpatch5, .Lpatch6, .Lpatch7, .Lpatch12
.long .Lpatch13
#if defined(FULL) && !defined(__XEN__)
.long .Lpatch11
#endif

View File

@ -1,7 +1,7 @@
/* $NetBSD: kern_rwlock.c,v 1.15 2008/01/04 21:54:49 ad Exp $ */
/* $NetBSD: kern_rwlock.c,v 1.16 2008/01/25 19:02:31 ad Exp $ */
/*-
* Copyright (c) 2002, 2006, 2007 The NetBSD Foundation, Inc.
* Copyright (c) 2002, 2006, 2007, 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -45,7 +45,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_rwlock.c,v 1.15 2008/01/04 21:54:49 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_rwlock.c,v 1.16 2008/01/25 19:02:31 ad Exp $");
#include "opt_multiprocessor.h"
@ -155,6 +155,7 @@ RW_SET_WAITERS(krwlock_t *rw, uintptr_t need, uintptr_t set)
#ifndef __HAVE_RW_STUBS
__strong_alias(rw_enter,rw_vector_enter);
__strong_alias(rw_exit,rw_vector_exit);
__strong_alias(rw_tryenter,rw_vector_tryenter);
#endif
static void rw_dump(volatile void *);
@ -474,19 +475,18 @@ rw_vector_exit(krwlock_t *rw)
}
/*
* rw_tryenter:
* rw_vector_tryenter:
*
* Try to acquire a rwlock.
*/
int
rw_tryenter(krwlock_t *rw, const krw_t op)
rw_vector_tryenter(krwlock_t *rw, const krw_t op)
{
uintptr_t curthread, owner, incr, need_wait;
curthread = (uintptr_t)curlwp;
RW_ASSERT(rw, curthread != 0);
RW_WANTLOCK(rw, op);
if (op == RW_READER) {
incr = RW_READ_INCR;
@ -509,6 +509,7 @@ rw_tryenter(krwlock_t *rw, const krw_t op)
return 0;
}
RW_WANTLOCK(rw, op);
RW_LOCKED(rw, op);
RW_DASSERT(rw, (op != RW_READER && RW_OWNER(rw) == curthread) ||
(op == RW_READER && RW_COUNT(rw) != 0));

View File

@ -1,7 +1,7 @@
/* $NetBSD: rwlock.h,v 1.3 2007/11/21 10:19:11 yamt Exp $ */
/* $NetBSD: rwlock.h,v 1.4 2008/01/25 19:02:31 ad Exp $ */
/*-
* Copyright (c) 2002, 2006, 2007 The NetBSD Foundation, Inc.
* Copyright (c) 2002, 2006, 2007, 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -113,6 +113,7 @@
*
* rw_enter()
* rw_exit()
* rw_tryenter()
*/
#if defined(_KERNEL_OPT)
@ -151,6 +152,7 @@ typedef struct krwlock krwlock_t;
void rw_vector_enter(krwlock_t *, const krw_t);
void rw_vector_exit(krwlock_t *);
int rw_vector_tryenter(krwlock_t *, const krw_t);
#endif /* __RWLOCK_PRIVATE */
#include <machine/rwlock.h>