138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* 238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Copyright (C) 2010 The Android Open Source Project 338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * 438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Licensed under the Apache License, Version 2.0 (the "License"); 538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * you may not use this file except in compliance with the License. 638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * You may obtain a copy of the License at 738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * 838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * http://www.apache.org/licenses/LICENSE-2.0 938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * 1038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Unless required by applicable law or agreed to in writing, software 1138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * distributed under the License is distributed on an "AS IS" BASIS, 1238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * See the License for the specific language governing permissions and 1438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * limitations under the License. 1538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 1638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 1738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* 1838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * This provides a handful of correctness and speed tests on our atomic 1938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * operations. 2038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * 2138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * This doesn't really belong here, but we currently lack a better place 2238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * for it, so this will do for now. 2338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 2438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#include "Dalvik.h" 2538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 2638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#include <stdlib.h> 2738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#include <stdio.h> 2838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#include <pthread.h> 2938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#include <unistd.h> 3038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#include <cutils/atomic.h> 3138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#ifdef __arm__ 3238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden# include <machine/cpu-features.h> 3338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#endif 3438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 3538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#define USE_ATOMIC 1 3638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#define THREAD_COUNT 10 3738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#define ITERATION_COUNT 500000 3838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 3938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#ifdef HAVE_ANDROID_OS 4038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/*#define TEST_BIONIC 1*/ 4138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#endif 4238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 4338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 4438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#ifdef TEST_BIONIC 4538a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenextern int __atomic_cmpxchg(int old, int _new, volatile int *ptr); 4638a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenextern int __atomic_swap(int _new, volatile int *ptr); 4738a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenextern int __atomic_dec(volatile int *ptr); 4838a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenextern int __atomic_inc(volatile int *ptr); 4938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#endif 5038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 5138a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic pthread_mutex_t waitLock = PTHREAD_MUTEX_INITIALIZER; 5238a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic pthread_cond_t waitCond = PTHREAD_COND_INITIALIZER; 5338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 5438a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic volatile int threadsStarted = 0; 5538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 5638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* results */ 5738a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int incTest = 0; 5838a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int decTest = 0; 5938a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int addTest = 0; 6038a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int andTest = 0; 6138a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int orTest = 0; 6238a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int casTest = 0; 6338a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int failingCasTest = 0; 6438a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int swapTest = 0; 6538a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int64_t wideCasTest = 0x6600000077000000LL; 6638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 6738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* 6838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Get a relative time value. 6938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 7038a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int64_t getRelativeTimeNsec(void) 7138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 7238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#define HAVE_POSIX_CLOCKS 7338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#ifdef HAVE_POSIX_CLOCKS 7438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden struct timespec now; 7538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden clock_gettime(CLOCK_MONOTONIC, &now); 7638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return (int64_t) now.tv_sec*1000000000LL + now.tv_nsec; 7738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#else 7838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden struct timeval now; 7938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden gettimeofday(&now, NULL); 8038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return (int64_t) now.tv_sec*1000000000LL + now.tv_usec * 1000LL; 8138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#endif 8238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 8338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 8438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 8538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* 8638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Non-atomic implementations, for comparison. 8738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * 8838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * If these get inlined the compiler may figure out what we're up to and 8938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * completely elide the operations. 9038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 9138a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic void incr(void) __attribute__((noinline)); 9238a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic void decr(void) __attribute__((noinline)); 9338a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic void add(int addVal) __attribute__((noinline)); 9438a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int compareAndSwap(int oldVal, int newVal, int* addr) __attribute__((noinline)); 9538a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int compareAndSwapWide(int64_t oldVal, int64_t newVal, int64_t* addr) __attribute__((noinline)); 9638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 9738a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic void incr(void) 9838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 9938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden incTest++; 10038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 10138a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic void decr(void) 10238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 10338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden decTest--; 10438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 10538a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic void add(int32_t addVal) 10638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 10738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden addTest += addVal; 10838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 10938a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int compareAndSwap(int32_t oldVal, int32_t newVal, int32_t* addr) 11038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 11138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (*addr == oldVal) { 11238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden *addr = newVal; 11338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return 0; 11438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 11538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return 1; 11638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 11738a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int compareAndSwapWide(int64_t oldVal, int64_t newVal, int64_t* addr) 11838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 11938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (*addr == oldVal) { 12038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden *addr = newVal; 12138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return 0; 12238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 12338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return 1; 12438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 12538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 12638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* 12738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Exercise several of the atomic ops. 12838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 12938a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic void doAtomicTest(int num) 13038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 13138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int addVal = (num & 0x01) + 1; 13238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 13338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int i; 13438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = 0; i < ITERATION_COUNT; i++) { 13538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (USE_ATOMIC) { 13638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden android_atomic_inc(&incTest); 13738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden android_atomic_dec(&decTest); 13838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden android_atomic_add(addVal, &addTest); 13938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 14038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int val; 14138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 14238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden val = casTest; 14338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (android_atomic_release_cas(val, val+3, &casTest) != 0); 14438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 14538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden val = casTest; 14638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (android_atomic_acquire_cas(val, val-1, &casTest) != 0); 14738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 14838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int64_t wval; 14938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 15038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval = dvmQuasiAtomicRead64(&wideCasTest); 15138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (dvmQuasiAtomicCas64(wval, 15238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval + 0x0000002000000001LL, &wideCasTest) != 0); 15338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 15438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval = dvmQuasiAtomicRead64(&wideCasTest); 15538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (dvmQuasiAtomicCas64(wval, 15638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval - 0x0000002000000001LL, &wideCasTest) != 0); 15738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } else { 15838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden incr(); 15938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden decr(); 16038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden add(addVal); 16138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 16238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int val; 16338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 16438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden val = casTest; 16538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (compareAndSwap(val, val+3, &casTest) != 0); 16638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 16738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden val = casTest; 16838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (compareAndSwap(val, val-1, &casTest) != 0); 16938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 17038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int64_t wval; 17138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 17238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval = wideCasTest; 17338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (compareAndSwapWide(wval, 17438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval + 0x0000002000000001LL, &wideCasTest) != 0); 17538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 17638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval = wideCasTest; 17738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (compareAndSwapWide(wval, 17838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval - 0x0000002000000001LL, &wideCasTest) != 0); 17938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 18038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 18138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 18238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 18338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* 18438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Entry point for multi-thread test. 18538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 18638a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic void* atomicTest(void* arg) 18738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 18838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_mutex_lock(&waitLock); 18938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden threadsStarted++; 19038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_cond_wait(&waitCond, &waitLock); 19138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_mutex_unlock(&waitLock); 19238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 19338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden doAtomicTest((int) arg); 19438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 19538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return NULL; 19638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 19738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 19838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* lifted from a VM test */ 19938a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int64_t testAtomicSpeedSub(int repeatCount) 20038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 20138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden static int value = 7; 20238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int* valuePtr = &value; 20338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int64_t start, end; 20438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int i; 20538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 20638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden start = getRelativeTimeNsec(); 20738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 20838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = repeatCount / 10; i != 0; i--) { 20938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (USE_ATOMIC) { 21038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden // succeed 10x 21138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (void) android_atomic_release_cas(7, 7, valuePtr); 21238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (void) android_atomic_release_cas(7, 7, valuePtr); 21338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (void) android_atomic_release_cas(7, 7, valuePtr); 21438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (void) android_atomic_release_cas(7, 7, valuePtr); 21538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (void) android_atomic_release_cas(7, 7, valuePtr); 21638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (void) android_atomic_release_cas(7, 7, valuePtr); 21738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (void) android_atomic_release_cas(7, 7, valuePtr); 21838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (void) android_atomic_release_cas(7, 7, valuePtr); 21938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (void) android_atomic_release_cas(7, 7, valuePtr); 22038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (void) android_atomic_release_cas(7, 7, valuePtr); 22138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } else { 22238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden // succeed 10x 22338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden compareAndSwap(7, 7, valuePtr); 22438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden compareAndSwap(7, 7, valuePtr); 22538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden compareAndSwap(7, 7, valuePtr); 22638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden compareAndSwap(7, 7, valuePtr); 22738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden compareAndSwap(7, 7, valuePtr); 22838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden compareAndSwap(7, 7, valuePtr); 22938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden compareAndSwap(7, 7, valuePtr); 23038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden compareAndSwap(7, 7, valuePtr); 23138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden compareAndSwap(7, 7, valuePtr); 23238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden compareAndSwap(7, 7, valuePtr); 23338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 23438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 23538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 23638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden end = getRelativeTimeNsec(); 23738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 23838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "."); 23938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden fflush(stdout); 24038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return end - start; 24138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 24238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 24338a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic void testAtomicSpeed(void) 24438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 24538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden static const int kIterations = 10; 24638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden static const int kRepeatCount = 5 * 1000 * 1000; 24738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden static const int kDelay = 50 * 1000; 24838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int64_t results[kIterations]; 24938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int i; 25038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 25138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = 0; i < kIterations; i++) { 25238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden results[i] = testAtomicSpeedSub(kRepeatCount); 25338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden usleep(kDelay); 25438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 25538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 25638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "\n"); 25738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "%s speed test results (%d per iteration):\n", 25838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden USE_ATOMIC ? "Atomic" : "Non-atomic", kRepeatCount); 25938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = 0; i < kIterations; i++) { 26038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, 26138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden " %2d: %.3fns\n", i, (double) results[i] / kRepeatCount); 26238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 26338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 26438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 26538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* 26638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Start tests, show results. 26738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 26838a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenbool dvmTestAtomicSpeed(void) 26938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 27038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_t threads[THREAD_COUNT]; 27138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden void *(*startRoutine)(void*) = atomicTest; 27238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int64_t startWhen, endWhen; 27338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 27438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#if defined(__ARM_ARCH__) 27538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "__ARM_ARCH__ is %d\n", __ARM_ARCH__); 27638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#endif 27738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#if defined(ANDROID_SMP) 27838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "ANDROID_SMP is %d\n", ANDROID_SMP); 27938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#endif 28038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "Creating threads\n"); 28138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 28238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int i; 28338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = 0; i < THREAD_COUNT; i++) { 28438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden void* arg = (void*) i; 28538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (pthread_create(&threads[i], NULL, startRoutine, arg) != 0) { 28638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stderr, "thread create failed\n"); 28738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 28838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 28938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 29038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden /* wait for all the threads to reach the starting line */ 29138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden while (1) { 29238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_mutex_lock(&waitLock); 29338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (threadsStarted == THREAD_COUNT) { 29438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "Starting test\n"); 29538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden startWhen = getRelativeTimeNsec(); 29638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_cond_broadcast(&waitCond); 29738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_mutex_unlock(&waitLock); 29838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden break; 29938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 30038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_mutex_unlock(&waitLock); 30138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden usleep(100000); 30238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 30338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 30438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = 0; i < THREAD_COUNT; i++) { 30538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden void* retval; 30638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (pthread_join(threads[i], &retval) != 0) { 30738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stderr, "thread join (%d) failed\n", i); 30838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 30938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 31038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 31138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden endWhen = getRelativeTimeNsec(); 31238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "All threads stopped, time is %.6fms\n", 31338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (endWhen - startWhen) / 1000000.0); 31438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 31538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden /* 31638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Show results; expecting: 31738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * 31838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * incTest = 5000000 31938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * decTest = -5000000 32038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * addTest = 7500000 32138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * casTest = 10000000 32238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * wideCasTest = 0x6600000077000000 32338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 32438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "incTest = %d\n", incTest); 32538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "decTest = %d\n", decTest); 32638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "addTest = %d\n", addTest); 32738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "casTest = %d\n", casTest); 32838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "wideCasTest = 0x%llx\n", wideCasTest); 32938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 33038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden /* do again, serially (SMP check) */ 33138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden startWhen = getRelativeTimeNsec(); 33238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = 0; i < THREAD_COUNT; i++) { 33338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden doAtomicTest(i); 33438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 33538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden endWhen = getRelativeTimeNsec(); 33638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "Same iterations done serially: time is %.6fms\n", 33738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (endWhen - startWhen) / 1000000.0); 33838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 33938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden /* 34038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Hard to do a meaningful thrash test on these, so just do a simple 34138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * function test. 34238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 34338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden andTest = 0xffd7fa96; 34438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden orTest = 0x122221ff; 34538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden swapTest = 0x11111111; 34638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden android_atomic_and(0xfffdaf96, &andTest); 34738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden android_atomic_or(0xdeaaeb00, &orTest); 34863e53deb445448f0131a73f64313c7d965c8487eCarl Shapiro int oldSwap = android_atomic_swap(0x22222222, &swapTest); 34963e53deb445448f0131a73f64313c7d965c8487eCarl Shapiro int oldSwap2 = android_atomic_swap(0x33333333, &swapTest); 35038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (android_atomic_release_cas(failingCasTest+1, failingCasTest-1, 35138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden &failingCasTest) == 0) 35238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "failing test did not fail!\n"); 35338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 35438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "andTest = 0x%x\n", andTest); 35538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "orTest = 0x%x\n", orTest); 356453e05f3847e8c7170291df04225d41abbecd4f9Carl Shapiro dvmFprintf(stdout, "swapTest = 0x%x -> 0x%x\n", oldSwap, oldSwap2); 357453e05f3847e8c7170291df04225d41abbecd4f9Carl Shapiro dvmFprintf(stdout, "swapTest = 0x%x -> 0x%x\n", oldSwap2, swapTest); 35838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "failingCasTest = %d\n", failingCasTest); 35938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 36038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#ifdef TEST_BIONIC 36138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden /* 36238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Quick function test on the bionic ops. 36338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 36438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int prev; 36538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int tester = 7; 36638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden prev = __atomic_inc(&tester); 36738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden __atomic_inc(&tester); 36838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden __atomic_inc(&tester); 36938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "bionic 3 inc: %d -> %d\n", prev, tester); 37038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden prev = __atomic_dec(&tester); 37138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden __atomic_dec(&tester); 37238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden __atomic_dec(&tester); 37338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "bionic 3 dec: %d -> %d\n", prev, tester); 37438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden prev = __atomic_swap(27, &tester); 37538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "bionic swap: %d -> %d\n", prev, tester); 37638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int swapok = __atomic_cmpxchg(27, 72, &tester); 37738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "bionic cmpxchg: %d (%d)\n", tester, swapok); 37838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#endif 37938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 38038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden testAtomicSpeed(); 38138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 38238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return 0; 38338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 384