On 10/10/17(Tue) 20:19, Mateusz Guzik wrote:
> On Tue, Oct 10, 2017 at 10:15:48AM +0200, Martin Pieuchot wrote:
> > Hello Mateusz,
> >
> > On 09/10/17(Mon) 21:43, Mateusz Guzik wrote:
> > > I was looking at rw lock code out of curiosity and noticed you always do
> > > membar_enter which on MP-enabled amd64 kernel translates to mfence.
> > > This makes the entire business a little bit slower.
> > >
> > > Interestingly you already have relevant macros for amd64:
> > > #define membar_enter_after_atomic() __membar("")
> > > #define membar_exit_before_atomic() __membar("")
> >
> > If you look at the history, you'll see that theses macro didn't exist
> > when membar_* where added to rw locks.
> >
> 
> I know. Addition of such a macro sounds like an accelent opportunity to
> examine existing users. I figured rw locks were ommitted by accident
> as the original posting explicitly mentions mutexes.
> 
> https://marc.info/?l=openbsd-tech&m=149555411827749&w=2
> 
> > > And there is even a default variant for archs which don't provide one.
> > > I guess the switch should be easy.
> >
> > Then please do it :)  At lot of stuff is easy on OpenBSD but we are not
> > enough.
> >
> > Do it, test it, explain it, get oks and commit it 8)
> >
> 
> As noted earlier the patch is trivial. I have no easy means to even
> compile-test it though as I'm not using OpenBSD. Only had a look out of
> curiosity.

Why don't you start using it?  Testing is what makes the difference.
Many of us have ideas of how to improve the kernel but we're lacking
the time to test & debug them all.

Sometimes a "correct" change exposes a bug and we try not to break
-current, so we cannot afford to commit a non-tested diff.

> Nonetheless, here is the diff which can be split in 2. One part deals
> with barriers, another one cleans up rw_status.
>
> [...]
>
> Read from the lock only once in rw_status. The lock word is marked as
> volatile which forces re-read on each access. There is no correctness
> issue here, but the assembly is worse than it needs to be and in case
> of contention this adds avoidable cache traffic.

Here's the diff to cleans rw_status.  The difference on amd64 with
clang 4.0  is the following:

        48 8b 0f                mov    (%rdi),%rcx
        f6 c1 04                test   $0x4,%cl
        75 0c                   jne    738 <rrw_status+0x18>
        31 c0                   xor    %eax,%eax
-       48 83 3f 00             cmpq   $0x0,(%rdi)
+       48 85 c9                test   %rcx,%rcx

ok?

Index: kern/kern_rwlock.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_rwlock.c,v
retrieving revision 1.30
diff -u -p -r1.30 kern_rwlock.c
--- kern/kern_rwlock.c  12 Aug 2017 23:27:44 -0000      1.30
+++ kern/kern_rwlock.c  11 Oct 2017 12:59:19 -0000
@@ -312,13 +312,15 @@ _rw_exit(struct rwlock *rwl LOCK_FL_VARS
 int
 rw_status(struct rwlock *rwl)
 {
-       if (rwl->rwl_owner & RWLOCK_WRLOCK) {
-               if (RW_PROC(curproc) == RW_PROC(rwl->rwl_owner))
+       unsigned long owner = rwl->rwl_owner;
+
+       if (owner & RWLOCK_WRLOCK) {
+               if (RW_PROC(curproc) == RW_PROC(owner))
                        return RW_WRITE;
                else
                        return RW_WRITE_OTHER;
        }
-       if (rwl->rwl_owner)
+       if (owner)
                return RW_READ;
        return (0);
 }

Reply via email to