Exemple #1
0
int __atomic_inc(volatile int *ptr)
{
    int32_t oldValue;
    do {
        oldValue = *ptr;
    } while (__atomic_cmpxchg(oldValue, oldValue+1, ptr));
    return oldValue;
}
Exemple #2
0
int __atomic_dec(volatile int *ptr)
{
    int oldValue;
    do {
        oldValue = *ptr;
    } while (__atomic_cmpxchg(oldValue, oldValue-1, ptr));
    return oldValue;
}
Exemple #3
0
int __atomic_swap(int _new, volatile int *ptr)
{
    int oldValue;
    do {
        oldValue = *ptr;
    } while (__atomic_cmpxchg(oldValue, _new, ptr));
    return oldValue;
}
extern "C" int __cxa_guard_acquire(_guard_t* gv)
{
    // 0 -> pending, return 1
    // pending -> waiting, wait and return 0
    // waiting: untouched, wait and return 0
    // ready: untouched, return 0

retry:
    if (__atomic_cmpxchg(0, pending, &gv->state) == 0) {
        ANDROID_MEMBAR_FULL();
        return 1;
    }
    __atomic_cmpxchg(pending, waiting, &gv->state); // Indicate there is a waiter
    __futex_wait(&gv->state, waiting, NULL);

    if (gv->state != ready) // __cxa_guard_abort was called, let every thread try since there is no return code for this condition
        goto retry;

    ANDROID_MEMBAR_FULL();
    return 0;
}
extern "C" void __cxa_guard_release(_guard_t* gv)
{
    // pending -> ready
    // waiting -> ready, and wake

    ANDROID_MEMBAR_FULL();
    if (__atomic_cmpxchg(pending, ready, &gv->state) == 0) {
        return;
    }

    gv->state = ready;
    __futex_wake(&gv->state, 0x7fffffff);
}
Exemple #6
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;
}