diff options
author | Jason Sams <rjsams@android.com> | 2011-06-21 16:42:30 -0700 |
---|---|---|
committer | Jason Sams <rjsams@android.com> | 2011-06-21 17:07:18 -0700 |
commit | 71767c5577c9708a5e0eeefca89cb2c85f8aeac6 (patch) | |
tree | da2685cd493725413d01019943c16b228d02dd19 | |
parent | ea1ca952c625d51dc71e1cc3d955b239921888c7 (diff) | |
download | frameworks_base-71767c5577c9708a5e0eeefca89cb2c85f8aeac6.zip frameworks_base-71767c5577c9708a5e0eeefca89cb2c85f8aeac6.tar.gz frameworks_base-71767c5577c9708a5e0eeefca89cb2c85f8aeac6.tar.bz2 |
First cut of atomics for renderscript.
Change-Id: Iefc0228d802e6f5348ae787553c9252fb90ba110
update atomic patch.
Change-Id: Idd0596439c092f570b6b226e9a9c7102ddffe88e
-rw-r--r-- | libs/rs/driver/rsdRuntimeMath.cpp | 103 | ||||
-rw-r--r-- | libs/rs/scriptc/rs_math.rsh | 222 |
2 files changed, 325 insertions, 0 deletions
diff --git a/libs/rs/driver/rsdRuntimeMath.cpp b/libs/rs/driver/rsdRuntimeMath.cpp index acb990d..d29da7e 100644 --- a/libs/rs/driver/rsdRuntimeMath.cpp +++ b/libs/rs/driver/rsdRuntimeMath.cpp @@ -268,6 +268,87 @@ static float SC_frac(float v) { } +static int32_t SC_AtomicCas(volatile int32_t *ptr, int32_t expectedValue, int32_t newValue) { + int32_t prev; + + do { + int32_t ret = android_atomic_release_cas(expectedValue, newValue, ptr); + if (!ret) { + // The android cas return 0 if it wrote the value. This means the + // previous value was the expected value and we can return. + return expectedValue; + } + // We didn't write the value and need to load the "previous" value. + prev = *ptr; + + // A race condition exists where the expected value could appear after our cas failed + // above. In this case loop until we have a legit previous value or the + // write passes. + } while (prev == expectedValue); + return prev; +} + + +static int32_t SC_AtomicInc(volatile int32_t *ptr) { + return android_atomic_inc(ptr); +} + +static int32_t SC_AtomicDec(volatile int32_t *ptr) { + return android_atomic_dec(ptr); +} + +static int32_t SC_AtomicAdd(volatile int32_t *ptr, int32_t value) { + return android_atomic_add(value, ptr); +} + +static int32_t SC_AtomicSub(volatile int32_t *ptr, int32_t value) { + int32_t prev, status; + do { + prev = *ptr; + status = android_atomic_release_cas(prev, prev - value, ptr); + } while (__builtin_expect(status != 0, 0)); + return prev; +} + +static int32_t SC_AtomicAnd(volatile int32_t *ptr, int32_t value) { + return android_atomic_and(value, ptr); +} + +static int32_t SC_AtomicOr(volatile int32_t *ptr, int32_t value) { + return android_atomic_or(value, ptr); +} + +static int32_t SC_AtomicXor(volatile int32_t *ptr, int32_t value) { + int32_t prev, status; + do { + prev = *ptr; + status = android_atomic_release_cas(prev, prev ^ value, ptr); + } while (__builtin_expect(status != 0, 0)); + return prev; +} + +static int32_t SC_AtomicMin(volatile int32_t *ptr, int32_t value) { + int32_t prev, status; + do { + prev = *ptr; + int32_t n = rsMin(value, prev); + status = android_atomic_release_cas(prev, n, ptr); + } while (__builtin_expect(status != 0, 0)); + return prev; +} + +static int32_t SC_AtomicMax(volatile int32_t *ptr, int32_t value) { + int32_t prev, status; + do { + prev = *ptr; + int32_t n = rsMax(value, prev); + status = android_atomic_release_cas(prev, n, ptr); + } while (__builtin_expect(status != 0, 0)); + return prev; +} + + + ////////////////////////////////////////////////////////////////////////////// // Class implementation ////////////////////////////////////////////////////////////////////////////// @@ -425,6 +506,28 @@ static RsdSymbolTable gSyms[] = { { "_Z6rsRandff", (void *)&SC_randf2, true }, { "_Z6rsFracf", (void *)&SC_frac, true }, + // Atomics + { "_Z11rsAtomicIncPVi", (void *)&SC_AtomicInc, true }, + { "_Z11rsAtomicIncPVj", (void *)&SC_AtomicInc, true }, + { "_Z11rsAtomicDecPVi", (void *)&SC_AtomicDec, true }, + { "_Z11rsAtomicDecPVj", (void *)&SC_AtomicDec, true }, + { "_Z11rsAtomicAddPVii", (void *)&SC_AtomicAdd, true }, + { "_Z11rsAtomicAddPVjj", (void *)&SC_AtomicAdd, true }, + { "_Z11rsAtomicSubPVii", (void *)&SC_AtomicSub, true }, + { "_Z11rsAtomicSubPVjj", (void *)&SC_AtomicSub, true }, + { "_Z11rsAtomicAndPVii", (void *)&SC_AtomicAnd, true }, + { "_Z11rsAtomicAndPVjj", (void *)&SC_AtomicAnd, true }, + { "_Z10rsAtomicOrPVii", (void *)&SC_AtomicOr, true }, + { "_Z10rsAtomicOrPVjj", (void *)&SC_AtomicOr, true }, + { "_Z11rsAtomicXorPVii", (void *)&SC_AtomicXor, true }, + { "_Z11rsAtomicXorPVjj", (void *)&SC_AtomicXor, true }, + { "_Z11rsAtomicMinPVii", (void *)&SC_AtomicMin, true }, + { "_Z11rsAtomicMinPVjj", (void *)&SC_AtomicMin, true }, + { "_Z11rsAtomicMaxPVii", (void *)&SC_AtomicMax, true }, + { "_Z11rsAtomicMaxPVjj", (void *)&SC_AtomicMax, true }, + { "_Z11rsAtomicCasPViii", (void *)&SC_AtomicCas, true }, + { "_Z11rsAtomicCasPVjjj", (void *)&SC_AtomicCas, true }, + { NULL, NULL, false } }; diff --git a/libs/rs/scriptc/rs_math.rsh b/libs/rs/scriptc/rs_math.rsh index 584317e..f38f72c 100644 --- a/libs/rs/scriptc/rs_math.rsh +++ b/libs/rs/scriptc/rs_math.rsh @@ -258,4 +258,226 @@ extern void __attribute__((overloadable)) rs_allocation output, const void * usrData, const rs_script_call_t *); + + +/** + * Atomic add one to the value at addr. + * Equal to rsAtomicAdd(addr, 1) + * + * @param addr Address of value to increment + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicInc(volatile int32_t* addr); +/** + * Atomic add one to the value at addr. + * Equal to rsAtomicAdd(addr, 1) + * + * @param addr Address of value to increment + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicInc(volatile uint32_t* addr); + +/** + * Atomic subtract one from the value at addr. Equal to rsAtomicSub(addr, 1) + * + * @param addr Address of value to decrement + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicDec(volatile int32_t* addr); +/** + * Atomic subtract one from the value at addr. Equal to rsAtomicSub(addr, 1) + * + * @param addr Address of value to decrement + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicDec(volatile uint32_t* addr); + +/** + * Atomic add a value to the value at addr. addr[0] += value + * + * @param addr Address of value to modify + * @param value Amount to add to the value at addr + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicAdd(volatile int32_t* addr, int32_t value); +/** + * Atomic add a value to the value at addr. addr[0] += value + * + * @param addr Address of value to modify + * @param value Amount to add to the value at addr + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicAdd(volatile uint32_t* addr, uint32_t value); + +/** + * Atomic Subtract a value from the value at addr. addr[0] -= value + * + * @param addr Address of value to modify + * @param value Amount to subtract from the value at addr + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicSub(volatile int32_t* addr, int32_t value); +/** + * Atomic Subtract a value from the value at addr. addr[0] -= value + * + * @param addr Address of value to modify + * @param value Amount to subtract from the value at addr + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicSub(volatile uint32_t* addr, uint32_t value); + +/** + * Atomic Bitwise and a value from the value at addr. addr[0] &= value + * + * @param addr Address of value to modify + * @param value Amount to and with the value at addr + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicAnd(volatile int32_t* addr, int32_t value); +/** + * Atomic Bitwise and a value from the value at addr. addr[0] &= value + * + * @param addr Address of value to modify + * @param value Amount to and with the value at addr + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicAnd(volatile uint32_t* addr, uint32_t value); + +/** + * Atomic Bitwise or a value from the value at addr. addr[0] |= value + * + * @param addr Address of value to modify + * @param value Amount to or with the value at addr + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicOr(volatile int32_t* addr, int32_t value); +/** + * Atomic Bitwise or a value from the value at addr. addr[0] |= value + * + * @param addr Address of value to modify + * @param value Amount to or with the value at addr + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicOr(volatile uint32_t* addr, uint32_t value); + +/** + * Atomic Bitwise xor a value from the value at addr. addr[0] ^= value + * + * @param addr Address of value to modify + * @param value Amount to xor with the value at addr + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicXor(volatile uint32_t* addr, uint32_t value); +/** + * Atomic Bitwise xor a value from the value at addr. addr[0] ^= value + * + * @param addr Address of value to modify + * @param value Amount to xor with the value at addr + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicXor(volatile int32_t* addr, int32_t value); + +/** + * Atomic Set the value at addr to the min of addr and value + * addr[0] = rsMin(addr[0], value) + * + * @param addr Address of value to modify + * @param value comparison value + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicMin(volatile uint32_t* addr, uint32_t value); +/** + * Atomic Set the value at addr to the min of addr and value + * addr[0] = rsMin(addr[0], value) + * + * @param addr Address of value to modify + * @param value comparison value + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicMin(volatile int32_t* addr, int32_t value); + +/** + * Atomic Set the value at addr to the max of addr and value + * addr[0] = rsMax(addr[0], value) + * + * @param addr Address of value to modify + * @param value comparison value + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicMax(volatile uint32_t* addr, uint32_t value); +/** + * Atomic Set the value at addr to the max of addr and value + * addr[0] = rsMin(addr[0], value) + * + * @param addr Address of value to modify + * @param value comparison value + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicMax(volatile int32_t* addr, int32_t value); + +/** + * Compare-and-set operation with a full memory barrier. + * + * If the value at addr matches compareValue then newValue is written. + * + * @param addr The address to compare and replace if the compare passes. + * @param compareValue The value to test addr[0] against. + * @param newValue The value to write if the test passes. + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicCas(volatile int32_t* addr, int32_t compareValue, int32_t newValue); + +/** + * Compare-and-set operation with a full memory barrier. + * + * If the value at addr matches compareValue then newValue is written. + * + * @param addr The address to compare and replace if the compare passes. + * @param compareValue The value to test addr[0] against. + * @param newValue The value to write if the test passes. + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicCas(volatile uint32_t* addr, int32_t compareValue, int32_t newValue); + + #endif |