Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d90f953 authored by Jason Sams's avatar Jason Sams Committed by Android (Google) Code Review
Browse files

Merge "First cut of atomics for renderscript."

parents 41909118 71767c55
Loading
Loading
Loading
Loading
+103 −0
Original line number Diff line number Diff line
@@ -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 }
};

+222 −0
Original line number Diff line number Diff line
@@ -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