Module Name: src
Committed By: riastradh
Date: Sun Mar 9 16:19:14 UTC 2014
Modified Files:
src/common/lib/libc/atomic: atomic_cas_by_cas32.c
Log Message:
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!
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/common/lib/libc/atomic/atomic_cas_by_cas32.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/common/lib/libc/atomic/atomic_cas_by_cas32.c
diff -u src/common/lib/libc/atomic/atomic_cas_by_cas32.c:1.2 src/common/lib/libc/atomic/atomic_cas_by_cas32.c:1.3
--- src/common/lib/libc/atomic/atomic_cas_by_cas32.c:1.2 Fri Mar 7 08:42:58 2014
+++ src/common/lib/libc/atomic/atomic_cas_by_cas32.c Sun Mar 9 16:19:14 2014
@@ -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 @@ _atomic_cas_16(volatile uint16_t *addr,
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 @@ _atomic_cas_8(volatile uint8_t *addr, ui
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;
}