Fix bugs with unsigned rsAtomicCas/Max/Min.

BUG=5888007

rsAtomicMax/Min did not have proper semantics for unsigned integers. They were
always using signed comparisons. rsAtomicCas had the wrong function signature
in our math library, leading to no way to properly link/execute it.

Change-Id: I336cdd8cd9f2d8093f12e101b55b2797515f039b
diff --git a/libs/rs/driver/rsdRuntimeMath.cpp b/libs/rs/driver/rsdRuntimeMath.cpp
index e315539..753ef73 100644
--- a/libs/rs/driver/rsdRuntimeMath.cpp
+++ b/libs/rs/driver/rsdRuntimeMath.cpp
@@ -329,6 +329,16 @@
     return prev;
 }
 
+static uint32_t SC_AtomicUMin(volatile uint32_t *ptr, uint32_t value) {
+    uint32_t prev, status;
+    do {
+        prev = *ptr;
+        uint32_t n = rsMin(value, prev);
+        status = android_atomic_release_cas((int32_t) prev, (int32_t)n, (volatile int32_t*) ptr);
+    } while (CC_UNLIKELY(status != 0));
+    return prev;
+}
+
 static int32_t SC_AtomicMin(volatile int32_t *ptr, int32_t value) {
     int32_t prev, status;
     do {
@@ -339,6 +349,16 @@
     return prev;
 }
 
+static uint32_t SC_AtomicUMax(volatile uint32_t *ptr, uint32_t value) {
+    uint32_t prev, status;
+    do {
+        prev = *ptr;
+        uint32_t n = rsMax(value, prev);
+        status = android_atomic_release_cas((int32_t) prev, (int32_t) n, (volatile int32_t*) ptr);
+    } while (CC_UNLIKELY(status != 0));
+    return prev;
+}
+
 static int32_t SC_AtomicMax(volatile int32_t *ptr, int32_t value) {
     int32_t prev, status;
     do {
@@ -524,9 +544,9 @@
     { "_Z11rsAtomicXorPVii", (void *)&SC_AtomicXor, true },
     { "_Z11rsAtomicXorPVjj", (void *)&SC_AtomicXor, true },
     { "_Z11rsAtomicMinPVii", (void *)&SC_AtomicMin, true },
-    { "_Z11rsAtomicMinPVjj", (void *)&SC_AtomicMin, true },
+    { "_Z11rsAtomicMinPVjj", (void *)&SC_AtomicUMin, true },
     { "_Z11rsAtomicMaxPVii", (void *)&SC_AtomicMax, true },
-    { "_Z11rsAtomicMaxPVjj", (void *)&SC_AtomicMax, true },
+    { "_Z11rsAtomicMaxPVjj", (void *)&SC_AtomicUMax, true },
     { "_Z11rsAtomicCasPViii", (void *)&SC_AtomicCas, true },
     { "_Z11rsAtomicCasPVjjj", (void *)&SC_AtomicCas, true },
 
diff --git a/libs/rs/scriptc/rs_atomic.rsh b/libs/rs/scriptc/rs_atomic.rsh
index 87c6c02..a455edd 100644
--- a/libs/rs/scriptc/rs_atomic.rsh
+++ b/libs/rs/scriptc/rs_atomic.rsh
@@ -242,7 +242,7 @@
  * @return old value
  */
 extern uint32_t __attribute__((overloadable))
-    rsAtomicCas(volatile uint32_t* addr, int32_t compareValue, int32_t newValue);
+    rsAtomicCas(volatile uint32_t* addr, uint32_t compareValue, uint32_t newValue);
 
 #endif //defined(RS_VERSION) && (RS_VERSION >= 14)
 
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
index c038478..5ab2c58 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2011 The Android Open Source Project
+ * Copyright (C) 2008-2012 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -72,6 +72,7 @@
         unitTests.add(new UT_alloc(this, mRes, mCtx));
         unitTests.add(new UT_refcount(this, mRes, mCtx));
         unitTests.add(new UT_foreach(this, mRes, mCtx));
+        unitTests.add(new UT_atomic(this, mRes, mCtx));
         unitTests.add(new UT_math(this, mRes, mCtx));
         unitTests.add(new UT_fp_mad(this, mRes, mCtx));
         /*
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_atomic.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_atomic.java
new file mode 100644
index 0000000..267c5b2
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_atomic.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_atomic extends UnitTest {
+    private Resources mRes;
+
+    protected UT_atomic(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Atomics", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_atomic s = new ScriptC_atomic(pRS, mRes, R.raw.atomic);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_atomic_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/atomic.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/atomic.rs
new file mode 100644
index 0000000..f0a5041
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/atomic.rs
@@ -0,0 +1,77 @@
+#include "shared.rsh"
+
+// Testing atomic operations
+static bool testUMax(uint32_t dst, uint32_t src) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst > src ? dst : src);
+    uint32_t ret = rsAtomicMax(&dst, src);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool testUMin(uint32_t dst, uint32_t src) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst < src ? dst : src);
+    uint32_t ret = rsAtomicMin(&dst, src);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool testUCas(uint32_t dst, uint32_t cmp, uint32_t swp) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst == cmp ? swp : dst);
+    uint32_t ret = rsAtomicCas(&dst, cmp, swp);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool test_atomics() {
+    bool failed = false;
+
+    failed |= testUMax(5, 6);
+    failed |= testUMax(6, 5);
+    failed |= testUMax(5, 0xf0000006);
+    failed |= testUMax(0xf0000006, 5);
+
+    failed |= testUMin(5, 6);
+    failed |= testUMin(6, 5);
+    failed |= testUMin(5, 0xf0000006);
+    failed |= testUMin(0xf0000006, 5);
+
+    failed |= testUCas(4, 4, 5);
+    failed |= testUCas(4, 5, 5);
+    failed |= testUCas(5, 5, 4);
+    failed |= testUCas(5, 4, 4);
+    failed |= testUCas(0xf0000004, 0xf0000004, 0xf0000005);
+    failed |= testUCas(0xf0000004, 0xf0000005, 0xf0000005);
+    failed |= testUCas(0xf0000005, 0xf0000005, 0xf0000004);
+    failed |= testUCas(0xf0000005, 0xf0000004, 0xf0000004);
+
+    if (failed) {
+        rsDebug("test_atomics FAILED", 0);
+    }
+    else {
+        rsDebug("test_atomics PASSED", 0);
+    }
+
+    return failed;
+}
+
+void atomic_test() {
+    bool failed = false;
+    failed |= test_atomics();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+