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

Commit 71767c55 authored by Jason Sams's avatar Jason Sams
Browse files

First cut of atomics for renderscript.

Change-Id: Iefc0228d802e6f5348ae787553c9252fb90ba110

update atomic patch.

Change-Id: Idd0596439c092f570b6b226e9a9c7102ddffe88e
parent ea1ca952
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