15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Copyright (c) 2009, Google Inc. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * modification, are permitted provided that the following conditions are 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * met: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Redistributions in binary form must reproduce the above 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in the documentation and/or other materials provided with the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distribution. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * contributors may be used to endorse or promote products derived from 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this software without specific prior written permission. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * --- 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This file is a Linux-specific part of spinlock_internal.cc 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sched.h> 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h> 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits.h> 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/linux_syscall_support.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FUTEX_WAIT 0 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FUTEX_WAKE 1 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FUTEX_PRIVATE_FLAG 128 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool have_futex; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int futex_private_flag = FUTEX_PRIVATE_FLAG; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct InitModule { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitModule() { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = 0; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // futexes are ints, so we can use them only when 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that's the same size as the lockword_ in SpinLock. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __arm__ 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ARM linux doesn't support sys_futex1(void*, int, int, struct timespec*); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) have_futex = 0; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) have_futex = (sizeof (Atomic32) == sizeof (int) && 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_futex(&x, FUTEX_WAKE, 1, 0) >= 0); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (have_futex && 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_futex(&x, FUTEX_WAKE | futex_private_flag, 1, 0) < 0) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) futex_private_flag = 0; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} init_module; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // anonymous namespace 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (loop != 0) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int save_errno = errno; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct timespec tm; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tm.tv_sec = 0; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (have_futex) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tm.tv_nsec = base::internal::SuggestedDelayNS(loop); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tm.tv_nsec = 2000001; // above 2ms so linux 2.4 doesn't spin 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (have_futex) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tm.tv_nsec *= 16; // increase the delay; we expect explicit wakeups 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_futex(reinterpret_cast<int *>(const_cast<Atomic32 *>(w)), 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FUTEX_WAIT | futex_private_flag, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value, reinterpret_cast<struct kernel_timespec *>(&tm)); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nanosleep(&tm, NULL); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = save_errno; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpinLockWake(volatile Atomic32 *w, bool all) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (have_futex) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_futex(reinterpret_cast<int *>(const_cast<Atomic32 *>(w)), 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FUTEX_WAKE | futex_private_flag, all? INT_MAX : 1, 0); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace internal 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 104