Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/common/lib/libc/atomic Fix subword atomic_cas.



details:   https://anonhg.NetBSD.org/src/rev/e27d5865837a
branches:  trunk
changeset: 327488:e27d5865837a
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sun Mar 09 16:19:14 2014 +0000

description:
Fix subword atomic_cas.

- Don't loop forever on failure.
- Don't shift away the result and return zero on success.

Evidently we lack automatic tests for these!

diffstat:

 common/lib/libc/atomic/atomic_cas_by_cas32.c |  22 +++++++++++++++-------
 1 files changed, 15 insertions(+), 7 deletions(-)

diffs (51 lines):

diff -r 51f93eadf38e -r e27d5865837a common/lib/libc/atomic/atomic_cas_by_cas32.c
--- a/common/lib/libc/atomic/atomic_cas_by_cas32.c      Sun Mar 09 16:18:00 2014 +0000
+++ b/common/lib/libc/atomic/atomic_cas_by_cas32.c      Sun Mar 09 16:19:14 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: atomic_cas_by_cas32.c,v 1.2 2014/03/07 08:42:58 martin Exp $   */
+/*     $NetBSD: atomic_cas_by_cas32.c,v 1.3 2014/03/09 16:19:14 riastradh Exp $        */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -48,14 +48,18 @@
        volatile uint32_t * ptr = (volatile uint32_t *)base;
        const size_t shift = off*8;
        const uint32_t mask = 0x0ffff << shift;
+       const uint32_t old32_part = (uint32_t)old << shift;
+       const uint32_t new32_part = (uint32_t)new << shift;
        uint32_t old32, new32;
 
        do {
                old32 = *ptr;
-               new32 = (old32 & ~mask) | (uint32_t)new << shift;
-               old32 = (old32 & ~mask) | (uint32_t)old << shift;
+               if ((old32 & mask) != old32_part)
+                       return (uint16_t)((old32 & mask) >> shift);
+               new32 = (old32 & ~mask) | new32_part;
        } while (_atomic_cas_32(ptr, old32, new32) != old32);
-       return (old & mask) >> shift;
+
+       return old;
 }
 
 uint8_t
@@ -66,12 +70,16 @@
        volatile uint32_t * ptr = (volatile uint32_t *)base;
        const size_t shift = off*8;
        const uint32_t mask = 0x0ff << shift;
+       const uint32_t old32_part = (uint32_t)old << shift;
+       const uint32_t new32_part = (uint32_t)new << shift;
        uint32_t old32, new32;
 
        do {
                old32 = *ptr;
-               new32 = (old32 & ~mask) | (uint32_t)new << shift;
-               old32 = (old32 & ~mask) | (uint32_t)old << shift;
+               if ((old32 & mask) != old32_part)
+                       return (uint8_t)((old32 & mask) >> shift);
+               new32 = (old32 & ~mask) | new32_part;
        } while (_atomic_cas_32(ptr, old32, new32) != old32);
-       return (old & mask) >> shift;
+
+       return old;
 }



Home | Main Index | Thread Index | Old Index