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 int64_t wideCasTest = 0x6600000077000000LL; 6538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 6638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* 6738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Get a relative time value. 6838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 691e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic int64_t getRelativeTimeNsec() 7038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 7138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#define HAVE_POSIX_CLOCKS 7238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#ifdef HAVE_POSIX_CLOCKS 7338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden struct timespec now; 7438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden clock_gettime(CLOCK_MONOTONIC, &now); 7538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return (int64_t) now.tv_sec*1000000000LL + now.tv_nsec; 7638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#else 7738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden struct timeval now; 7838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden gettimeofday(&now, NULL); 7938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return (int64_t) now.tv_sec*1000000000LL + now.tv_usec * 1000LL; 8038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#endif 8138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 8238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 8338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 8438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* 8538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Non-atomic implementations, for comparison. 8638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * 8738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * If these get inlined the compiler may figure out what we're up to and 8838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * completely elide the operations. 8938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 901e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void incr() __attribute__((noinline)); 911e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void decr() __attribute__((noinline)); 9238a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic void add(int addVal) __attribute__((noinline)); 9338a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int compareAndSwap(int oldVal, int newVal, int* addr) __attribute__((noinline)); 9438a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int compareAndSwapWide(int64_t oldVal, int64_t newVal, int64_t* addr) __attribute__((noinline)); 9538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 961e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void incr() 9738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 9838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden incTest++; 9938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 1001e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void decr() 10138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 10238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden decTest--; 10338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 10438a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic void add(int32_t addVal) 10538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 10638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden addTest += addVal; 10738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 10838a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int compareAndSwap(int32_t oldVal, int32_t newVal, int32_t* addr) 10938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 11038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (*addr == oldVal) { 11138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden *addr = newVal; 11238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return 0; 11338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 11438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return 1; 11538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 11638a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int compareAndSwapWide(int64_t oldVal, int64_t newVal, int64_t* addr) 11738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 11838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (*addr == oldVal) { 11938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden *addr = newVal; 12038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return 0; 12138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 12238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return 1; 12338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 12438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 12538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* 12638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Exercise several of the atomic ops. 12738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 12838a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic void doAtomicTest(int num) 12938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 13038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int addVal = (num & 0x01) + 1; 13138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 13238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int i; 13338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = 0; i < ITERATION_COUNT; i++) { 13438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (USE_ATOMIC) { 13538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden android_atomic_inc(&incTest); 13638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden android_atomic_dec(&decTest); 13738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden android_atomic_add(addVal, &addTest); 13838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 13938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int val; 14038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 14138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden val = casTest; 14238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (android_atomic_release_cas(val, val+3, &casTest) != 0); 14338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 14438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden val = casTest; 14538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (android_atomic_acquire_cas(val, val-1, &casTest) != 0); 14638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 14738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int64_t wval; 14838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 14938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval = dvmQuasiAtomicRead64(&wideCasTest); 15038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (dvmQuasiAtomicCas64(wval, 15138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval + 0x0000002000000001LL, &wideCasTest) != 0); 15238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 15338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval = dvmQuasiAtomicRead64(&wideCasTest); 15438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (dvmQuasiAtomicCas64(wval, 15538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval - 0x0000002000000001LL, &wideCasTest) != 0); 15638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } else { 15738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden incr(); 15838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden decr(); 15938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden add(addVal); 16038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 16138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int val; 16238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 16338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden val = casTest; 16438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (compareAndSwap(val, val+3, &casTest) != 0); 16538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 16638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden val = casTest; 16738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (compareAndSwap(val, val-1, &casTest) != 0); 16838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 16938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int64_t wval; 17038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 17138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval = wideCasTest; 17238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (compareAndSwapWide(wval, 17338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval + 0x0000002000000001LL, &wideCasTest) != 0); 17438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden do { 17538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval = wideCasTest; 17638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } while (compareAndSwapWide(wval, 17738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden wval - 0x0000002000000001LL, &wideCasTest) != 0); 17838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 17938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 18038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 18138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 18238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* 18338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Entry point for multi-thread test. 18438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 18538a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic void* atomicTest(void* arg) 18638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 18738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_mutex_lock(&waitLock); 18838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden threadsStarted++; 18938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_cond_wait(&waitCond, &waitLock); 19038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_mutex_unlock(&waitLock); 19138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 19238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden doAtomicTest((int) arg); 19338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 19438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return NULL; 19538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 19638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 19738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* lifted from a VM test */ 19838a17866b31e0b6dee320f32a8644e358583ab23Andy McFaddenstatic int64_t testAtomicSpeedSub(int repeatCount) 19938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 20038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden static int value = 7; 20138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int* valuePtr = &value; 20238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int64_t start, end; 20338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int i; 20438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 20538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden start = getRelativeTimeNsec(); 20638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 20738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = repeatCount / 10; i != 0; i--) { 20838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (USE_ATOMIC) { 20938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden // succeed 10x 2101e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapiro android_atomic_release_cas(7, 7, valuePtr); 2111e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapiro android_atomic_release_cas(7, 7, valuePtr); 2121e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapiro android_atomic_release_cas(7, 7, valuePtr); 2131e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapiro android_atomic_release_cas(7, 7, valuePtr); 2141e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapiro android_atomic_release_cas(7, 7, valuePtr); 2151e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapiro android_atomic_release_cas(7, 7, valuePtr); 2161e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapiro android_atomic_release_cas(7, 7, valuePtr); 2171e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapiro android_atomic_release_cas(7, 7, valuePtr); 2181e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapiro android_atomic_release_cas(7, 7, valuePtr); 2191e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapiro android_atomic_release_cas(7, 7, valuePtr); 22038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } else { 22138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden // succeed 10x 22238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden compareAndSwap(7, 7, valuePtr); 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 } 23338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 23438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 23538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden end = getRelativeTimeNsec(); 23638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 23738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "."); 23838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden fflush(stdout); 23938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return end - start; 24038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 24138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 2421e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void testAtomicSpeed() 24338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 24438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden static const int kIterations = 10; 24538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden static const int kRepeatCount = 5 * 1000 * 1000; 24638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden static const int kDelay = 50 * 1000; 24738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int64_t results[kIterations]; 24838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int i; 24938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 25038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = 0; i < kIterations; i++) { 25138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden results[i] = testAtomicSpeedSub(kRepeatCount); 25238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden usleep(kDelay); 25338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 25438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 25538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "\n"); 25638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "%s speed test results (%d per iteration):\n", 25738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden USE_ATOMIC ? "Atomic" : "Non-atomic", kRepeatCount); 25838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = 0; i < kIterations; i++) { 25938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, 26038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden " %2d: %.3fns\n", i, (double) results[i] / kRepeatCount); 26138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 26238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 26338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 26438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden/* 26538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Start tests, show results. 26638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 2671e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmTestAtomicSpeed() 26838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden{ 26938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_t threads[THREAD_COUNT]; 27038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden void *(*startRoutine)(void*) = atomicTest; 27138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int64_t startWhen, endWhen; 27238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 27338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#if defined(__ARM_ARCH__) 27438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "__ARM_ARCH__ is %d\n", __ARM_ARCH__); 27538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#endif 27638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#if defined(ANDROID_SMP) 27738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "ANDROID_SMP is %d\n", ANDROID_SMP); 27838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#endif 27938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "Creating threads\n"); 28038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 28138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int i; 28238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = 0; i < THREAD_COUNT; i++) { 28338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden void* arg = (void*) i; 28438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (pthread_create(&threads[i], NULL, startRoutine, arg) != 0) { 28538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stderr, "thread create failed\n"); 28638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 28738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 28838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 28938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden /* wait for all the threads to reach the starting line */ 29038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden while (1) { 29138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_mutex_lock(&waitLock); 29238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (threadsStarted == THREAD_COUNT) { 29338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "Starting test\n"); 29438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden startWhen = getRelativeTimeNsec(); 29538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_cond_broadcast(&waitCond); 29638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_mutex_unlock(&waitLock); 29738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden break; 29838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 29938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden pthread_mutex_unlock(&waitLock); 30038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden usleep(100000); 30138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 30238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 30338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = 0; i < THREAD_COUNT; i++) { 30438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden void* retval; 30538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (pthread_join(threads[i], &retval) != 0) { 30638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stderr, "thread join (%d) failed\n", i); 30738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 30838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 30938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 31038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden endWhen = getRelativeTimeNsec(); 31138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "All threads stopped, time is %.6fms\n", 31238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (endWhen - startWhen) / 1000000.0); 31338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 31438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden /* 31538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Show results; expecting: 31638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * 31738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * incTest = 5000000 31838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * decTest = -5000000 31938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * addTest = 7500000 32038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * casTest = 10000000 32138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * wideCasTest = 0x6600000077000000 32238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 32338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "incTest = %d\n", incTest); 32438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "decTest = %d\n", decTest); 32538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "addTest = %d\n", addTest); 32638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "casTest = %d\n", casTest); 32738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "wideCasTest = 0x%llx\n", wideCasTest); 32838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 32938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden /* do again, serially (SMP check) */ 33038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden startWhen = getRelativeTimeNsec(); 33138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden for (i = 0; i < THREAD_COUNT; i++) { 33238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden doAtomicTest(i); 33338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden } 33438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden endWhen = getRelativeTimeNsec(); 33538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "Same iterations done serially: time is %.6fms\n", 33638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden (endWhen - startWhen) / 1000000.0); 33738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 33838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden /* 33938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Hard to do a meaningful thrash test on these, so just do a simple 34038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * function test. 34138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 34238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden andTest = 0xffd7fa96; 34338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden orTest = 0x122221ff; 34438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden android_atomic_and(0xfffdaf96, &andTest); 34538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden android_atomic_or(0xdeaaeb00, &orTest); 34638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden if (android_atomic_release_cas(failingCasTest+1, failingCasTest-1, 34738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden &failingCasTest) == 0) 34838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "failing test did not fail!\n"); 34938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 350291c84f60853d30e1c0d79dd08c5e5164f588e26Dan Bornstein dvmFprintf(stdout, "andTest = %#x\n", andTest); 351291c84f60853d30e1c0d79dd08c5e5164f588e26Dan Bornstein dvmFprintf(stdout, "orTest = %#x\n", orTest); 35238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "failingCasTest = %d\n", failingCasTest); 35338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 35438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#ifdef TEST_BIONIC 35538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden /* 35638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden * Quick function test on the bionic ops. 35738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden */ 35838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int prev; 35938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int tester = 7; 36038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden prev = __atomic_inc(&tester); 36138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden __atomic_inc(&tester); 36238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden __atomic_inc(&tester); 36338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "bionic 3 inc: %d -> %d\n", prev, tester); 36438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden prev = __atomic_dec(&tester); 36538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden __atomic_dec(&tester); 36638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden __atomic_dec(&tester); 36738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "bionic 3 dec: %d -> %d\n", prev, tester); 36838a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden prev = __atomic_swap(27, &tester); 36938a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "bionic swap: %d -> %d\n", prev, tester); 37038a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden int swapok = __atomic_cmpxchg(27, 72, &tester); 37138a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden dvmFprintf(stdout, "bionic cmpxchg: %d (%d)\n", tester, swapok); 37238a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden#endif 37338a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 37438a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden testAtomicSpeed(); 37538a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden 37638a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden return 0; 37738a17866b31e0b6dee320f32a8644e358583ab23Andy McFadden} 378