Commit:     434f98c48fc1d2a1f562a28a1562a7b53e940957
Parent:     06cd9396778d5b70ba27fa8158db78d6bc0f007b
Author:     Robert Jennings <[EMAIL PROTECTED]>
AuthorDate: Wed Jan 17 10:50:20 2007 -0600
Committer:  Paul Mackerras <[EMAIL PROTECTED]>
CommitDate: Mon Jan 22 21:27:36 2007 +1100

    [POWERPC] atomic_dec_if_positive sign extension fix
    On 64-bit machines, if an atomic counter is explicitly set to a
    negative value, the atomic_dec_if_positive function will decrement and
    store the next smallest value in the atomic counter, contrary to its
    intended operation.
    The comparison to determine if the decrement will make the result
    negative was done by the "addic." instruction, which operates on a
    64-bit value, namely the zero-extended word loaded from the atomic
    variable.  This patch uses an explicit word compare (cmpwi) and
    changes the addic. to an addi (also changing "=&r" to "=&b" so that r0
    isn't used, and addi doesn't become li).
    This also fixes a bug for both 32-bit and 64-bit in that previously
    0x80000000 was considered positive, since the result after
    decrementing is positive.  Now it is considered negative.
    Also, I clarify the return value in the comments just to make it clear
    that the value returned is always the decremented value, even if that
    value is not stored back to the atomic counter.
    Signed-off-by: Robert Jennings <[EMAIL PROTECTED]>
    Signed-off-by: Paul Mackerras <[EMAIL PROTECTED]>
 include/asm-powerpc/atomic.h |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h
index 53283e2..f038e33 100644
--- a/include/asm-powerpc/atomic.h
+++ b/include/asm-powerpc/atomic.h
@@ -207,7 +207,8 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, 
int u)
  * Atomically test *v and decrement if it is greater than 0.
- * The function returns the old value of *v minus 1.
+ * The function returns the old value of *v minus 1, even if
+ * the atomic variable, v, was not decremented.
 static __inline__ int atomic_dec_if_positive(atomic_t *v)
@@ -216,14 +217,15 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)
        __asm__ __volatile__(
 "1:    lwarx   %0,0,%1         # atomic_dec_if_positive\n\
-       addic.  %0,%0,-1\n\
+       cmpwi   %0,1\n\
+       addi    %0,%0,-1\n\
        blt-    2f\n"
 "      stwcx.  %0,0,%1\n\
        bne-    1b"
-2:"    : "=&r" (t)
+2:"    : "=&b" (t)
        : "r" (&v->counter)
        : "cc", "memory");
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at

Reply via email to