1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <pthread.h> 30#include <linux/futex.h> 31 32#define SWAP_LOCK_COUNT 32U 33static pthread_mutex_t _swap_locks[SWAP_LOCK_COUNT]; 34 35#define SWAP_LOCK(addr) \ 36 &_swap_locks[((unsigned)(void *)(addr) >> 3U) % SWAP_LOCK_COUNT] 37 38#if 0 39/* 40 * Only this function is moved to atomic_cmpxchg.S, and 41 * implemented with gUSA framework. 42 */ 43int __atomic_cmpxchg(int old, int _new, volatile int *ptr) 44{ 45 int result; 46 pthread_mutex_t *lock = SWAP_LOCK(ptr); 47 48 pthread_mutex_lock(lock); 49 50 if (*ptr == old) { 51 *ptr = _new; 52 result = 0; 53 } else { 54 result = 1; 55 } 56 pthread_mutex_unlock(lock); 57 return result; 58} 59#else 60extern int __atomic_cmpxchg(int old, int _new, volatile int *ptr); 61#endif 62 63int __atomic_swap(int _new, volatile int *ptr) 64{ 65 int oldValue; 66 do { 67 oldValue = *ptr; 68 } while (__atomic_cmpxchg(oldValue, _new, ptr)); 69 return oldValue; 70} 71 72int __atomic_dec(volatile int *ptr) 73{ 74 int oldValue; 75 do { 76 oldValue = *ptr; 77 } while (__atomic_cmpxchg(oldValue, oldValue-1, ptr)); 78 return oldValue; 79} 80 81int __atomic_inc(volatile int *ptr) 82{ 83 int32_t oldValue; 84 do { 85 oldValue = *ptr; 86 } while (__atomic_cmpxchg(oldValue, oldValue+1, ptr)); 87 return oldValue; 88} 89 90extern int futex(volatile void *, int, int, void *, void *, int); 91 92int __futex_wait(volatile void *ftx, int val, const struct timespec *timeout) 93{ 94 return futex(ftx, FUTEX_WAIT, val, (void *)timeout, NULL, 0); 95} 96 97int __futex_wake(volatile void *ftx, int count) 98{ 99 return futex(ftx, FUTEX_WAKE, count, NULL, NULL, 0); 100} 101 102int __futex_syscall3(volatile void *ftx, int op, int val) 103{ 104 return futex(ftx, op, val, NULL, NULL, 0); 105} 106 107int __futex_syscall4(volative void *ftx, int op, int val, const struct timespec *timeout) 108{ 109 return futex(ftx, op, val, (void *)timeout, NULL, 0); 110} 111