Esempio n. 1
0
/* lifted from a VM test */
static int64_t testAtomicSpeedSub(int repeatCount) {
    static int value = 7;
    int *valuePtr = &value;
    int64_t start, end;
    int i;

    start = getRelativeTimeNsec();

    for (i = repeatCount / 10; i != 0; i--) {
        if (USE_ATOMIC) {
            // succeed 10x
            android_atomic_release_cas(7, 7, valuePtr);
            android_atomic_release_cas(7, 7, valuePtr);
            android_atomic_release_cas(7, 7, valuePtr);
            android_atomic_release_cas(7, 7, valuePtr);
            android_atomic_release_cas(7, 7, valuePtr);
            android_atomic_release_cas(7, 7, valuePtr);
            android_atomic_release_cas(7, 7, valuePtr);
            android_atomic_release_cas(7, 7, valuePtr);
            android_atomic_release_cas(7, 7, valuePtr);
            android_atomic_release_cas(7, 7, valuePtr);
        } else {
            // succeed 10x
            compareAndSwap(7, 7, valuePtr);
            compareAndSwap(7, 7, valuePtr);
            compareAndSwap(7, 7, valuePtr);
            compareAndSwap(7, 7, valuePtr);
            compareAndSwap(7, 7, valuePtr);
            compareAndSwap(7, 7, valuePtr);
            compareAndSwap(7, 7, valuePtr);
            compareAndSwap(7, 7, valuePtr);
            compareAndSwap(7, 7, valuePtr);
            compareAndSwap(7, 7, valuePtr);
        }
    }

    end = getRelativeTimeNsec();

    dvmFprintf(stdout, ".");
    fflush(stdout);
    return end - start;
}
Esempio n. 2
0
/*
 * Exercise several of the atomic ops.
 */
static void doAtomicTest(int num) {
    int addVal = (num & 0x01) + 1;

    int i;
    for (i = 0; i < ITERATION_COUNT; i++) {
        if (USE_ATOMIC) {
            android_atomic_inc(&incTest);
            android_atomic_dec(&decTest);
            android_atomic_add(addVal, &addTest);

            int val;
            do {
                val = casTest;
            } while (android_atomic_release_cas(val, val + 3, &casTest) != 0);
            do {
                val = casTest;
            } while (android_atomic_acquire_cas(val, val - 1, &casTest) != 0);

            int64_t wval;
            do {
                wval = dvmQuasiAtomicRead64(&wideCasTest);
            } while (dvmQuasiAtomicCas64(wval,
                                         wval + 0x0000002000000001LL, &wideCasTest) != 0);
            do {
                wval = dvmQuasiAtomicRead64(&wideCasTest);
            } while (dvmQuasiAtomicCas64(wval,
                                         wval - 0x0000002000000001LL, &wideCasTest) != 0);
        } else {
            incr();
            decr();
            add(addVal);

            int val;
            do {
                val = casTest;
            } while (compareAndSwap(val, val + 3, &casTest) != 0);
            do {
                val = casTest;
            } while (compareAndSwap(val, val - 1, &casTest) != 0);

            int64_t wval;
            do {
                wval = wideCasTest;
            } while (compareAndSwapWide(wval,
                                        wval + 0x0000002000000001LL, &wideCasTest) != 0);
            do {
                wval = wideCasTest;
            } while (compareAndSwapWide(wval,
                                        wval - 0x0000002000000001LL, &wideCasTest) != 0);
        }
    }
}
Esempio n. 3
0
/*
 * public native boolean compareAndSwapInt(Object obj, long offset,
 *         int expectedValue, int newValue);
 */
static void Dalvik_sun_misc_Unsafe_compareAndSwapInt(const u4 *args,
                                                     JValue *pResult) {
    // We ignore the this pointer in args[0].
    Object *obj = (Object *) args[1];
    s8 offset = GET_ARG_LONG(args, 2);
    s4 expectedValue = args[4];
    s4 newValue = args[5];
    volatile int32_t *address = (volatile int32_t *) (((u1 *) obj) + offset);

    // Note: android_atomic_release_cas() returns 0 on success, not failure.
    int result = android_atomic_release_cas(expectedValue, newValue, address);

    RETURN_BOOLEAN(result == 0);
}
Esempio n. 4
0
/*
 * public native boolean compareAndSwapObject(Object obj, long offset,
 *         Object expectedValue, Object newValue);
 */
static void Dalvik_sun_misc_Unsafe_compareAndSwapObject(const u4 *args,
                                                        JValue *pResult) {
    // We ignore the this pointer in args[0].
    Object *obj = (Object *) args[1];
    s8 offset = GET_ARG_LONG(args, 2);
    Object *expectedValue = (Object *) args[4];
    Object *newValue = (Object *) args[5];
    int32_t *address = (int32_t *) (((u1 *) obj) + offset);

    // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
    int result = android_atomic_release_cas((int32_t) expectedValue,
                                            (int32_t) newValue, address);
    dvmWriteBarrierField(obj, address);
    RETURN_BOOLEAN(result == 0);
}
Esempio n. 5
0
/*
 * Create and initialize a monitor.
 */
Monitor* dvmCreateMonitor(Object* obj)
{
    Monitor* mon;

    mon = (Monitor*) calloc(1, sizeof(Monitor));
    if (mon == NULL) {
        ALOGE("Unable to allocate monitor");
        dvmAbort();
    }
    mon->obj = obj;
    dvmInitMutex(&mon->lock);

    /* replace the head of the list with the new monitor */
    do {
        mon->next = gDvm.monitorList;
    } while (android_atomic_release_cas((int32_t)mon->next, (int32_t)mon,
            (int32_t*)(void*)&gDvm.monitorList) != 0);

    return mon;
}
Esempio n. 6
0
int android_atomic_cmpxchg(int32_t oldvalue, int32_t newvalue,
        volatile int32_t* addr) {
       return android_atomic_release_cas(oldvalue,newvalue,addr);
}
Esempio n. 7
0
/*
 * Start tests, show results.
 */
bool dvmTestAtomicSpeed() {
    pthread_t threads[THREAD_COUNT];
    void *(*startRoutine)(void *) = atomicTest;
    int64_t startWhen, endWhen;

#if defined(__ARM_ARCH__)
    dvmFprintf(stdout, "__ARM_ARCH__ is %d\n", __ARM_ARCH__);
#endif
#if defined(ANDROID_SMP)
    dvmFprintf(stdout, "ANDROID_SMP is %d\n", ANDROID_SMP);
#endif
    dvmFprintf(stdout, "Creating threads\n");

    int i;
    for (i = 0; i < THREAD_COUNT; i++) {
        void *arg = (void *) i;
        if (pthread_create(&threads[i], NULL, startRoutine, arg) != 0) {
            dvmFprintf(stderr, "thread create failed\n");
        }
    }

    /* wait for all the threads to reach the starting line */
    while (1) {
        pthread_mutex_lock(&waitLock);
        if (threadsStarted == THREAD_COUNT) {
            dvmFprintf(stdout, "Starting test\n");
            startWhen = getRelativeTimeNsec();
            pthread_cond_broadcast(&waitCond);
            pthread_mutex_unlock(&waitLock);
            break;
        }
        pthread_mutex_unlock(&waitLock);
        usleep(100000);
    }

    for (i = 0; i < THREAD_COUNT; i++) {
        void *retval;
        if (pthread_join(threads[i], &retval) != 0) {
            dvmFprintf(stderr, "thread join (%d) failed\n", i);
        }
    }

    endWhen = getRelativeTimeNsec();
    dvmFprintf(stdout, "All threads stopped, time is %.6fms\n",
               (endWhen - startWhen) / 1000000.0);

    /*
     * Show results; expecting:
     *
     * incTest = 5000000
     * decTest = -5000000
     * addTest = 7500000
     * casTest = 10000000
     * wideCasTest = 0x6600000077000000
     */
    dvmFprintf(stdout, "incTest = %d\n", incTest);
    dvmFprintf(stdout, "decTest = %d\n", decTest);
    dvmFprintf(stdout, "addTest = %d\n", addTest);
    dvmFprintf(stdout, "casTest = %d\n", casTest);
    dvmFprintf(stdout, "wideCasTest = 0x%llx\n", wideCasTest);

    /* do again, serially (SMP check) */
    startWhen = getRelativeTimeNsec();
    for (i = 0; i < THREAD_COUNT; i++) {
        doAtomicTest(i);
    }
    endWhen = getRelativeTimeNsec();
    dvmFprintf(stdout, "Same iterations done serially: time is %.6fms\n",
               (endWhen - startWhen) / 1000000.0);

    /*
     * Hard to do a meaningful thrash test on these, so just do a simple
     * function test.
     */
    andTest = 0xffd7fa96;
    orTest = 0x122221ff;
    android_atomic_and(0xfffdaf96, &andTest);
    android_atomic_or(0xdeaaeb00, &orTest);
    if (android_atomic_release_cas(failingCasTest + 1, failingCasTest - 1,
                                   &failingCasTest) == 0)
        dvmFprintf(stdout, "failing test did not fail!\n");

    dvmFprintf(stdout, "andTest = %#x\n", andTest);
    dvmFprintf(stdout, "orTest = %#x\n", orTest);
    dvmFprintf(stdout, "failingCasTest = %d\n", failingCasTest);

#ifdef TEST_BIONIC
    /*
     * Quick function test on the bionic ops.
     */
    int prev;
    int tester = 7;
    prev = __atomic_inc(&tester);
    __atomic_inc(&tester);
    __atomic_inc(&tester);
    dvmFprintf(stdout, "bionic 3 inc: %d -> %d\n", prev, tester);
    prev = __atomic_dec(&tester);
    __atomic_dec(&tester);
    __atomic_dec(&tester);
    dvmFprintf(stdout, "bionic 3 dec: %d -> %d\n", prev, tester);
    prev = __atomic_swap(27, &tester);
    dvmFprintf(stdout, "bionic swap: %d -> %d\n", prev, tester);
    int swapok = __atomic_cmpxchg(27, 72, &tester);
    dvmFprintf(stdout, "bionic cmpxchg: %d (%d)\n", tester, swapok);
#endif

    testAtomicSpeed();

    return 0;
}