From patchwork Tue Jun 17 19:17:59 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Bernie Ogden X-Patchwork-Id: 32104 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-yh0-f72.google.com (mail-yh0-f72.google.com [209.85.213.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 8F7C4206A0 for ; Tue, 17 Jun 2014 19:18:22 +0000 (UTC) Received: by mail-yh0-f72.google.com with SMTP id f10sf33635428yha.7 for ; Tue, 17 Jun 2014 12:18:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:mailing-list:precedence:list-id :list-unsubscribe:list-subscribe:list-archive:list-post:list-help :sender:delivered-to:mime-version:subject:from:in-reply-to:date:cc :message-id:references:to:x-original-sender :x-original-authentication-results:content-type :content-transfer-encoding; bh=Nwxi9AECz0/pTdGMQ+UY5foGKoO/4SpusBwgIVIf2IM=; b=H1Gvlbx0Vpsw4YrDkG6yGTQeeoUsGGnk2+qDovJ7XmX/wG1Dy0zqPpBKTvqzvYoVxB OaPkIn18HR+RP6h+SUUyerUn9SEhHEWL5oCrphNy1eCTiHDdp29KdqVZ/xVMxpzuNRSj cb45YW5AV0inhfvbi38hLRF7SX78Q/CmMJS3bgTngJjbmXVVgbCYv3qiWhwOb5YDI3r7 2HYjcwLYdYcuf3C+Uhi/0az5WBxdm6MZiXCBuwmXUKiA7DX6huyAj+KtURxpZ17yBiem jVKWxWmYZAAzVABeBIvcjbMKmt5EQODXhg03WSh3mrNWr0jJslXdMM45LVWm5mo0qD2J ax0A== X-Gm-Message-State: ALoCoQkIeNDean4DJbl0wmuSZwTD7FAtmV0YYva5iKRK2Kdy07qEMxBqajWdWV8XCqRwUkkBjfaG X-Received: by 10.224.43.202 with SMTP id x10mr1674804qae.0.1403032702384; Tue, 17 Jun 2014 12:18:22 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.90.48 with SMTP id w45ls4833971qgd.73.gmail; Tue, 17 Jun 2014 12:18:22 -0700 (PDT) X-Received: by 10.52.101.168 with SMTP id fh8mr8506085vdb.34.1403032702227; Tue, 17 Jun 2014 12:18:22 -0700 (PDT) Received: from mail-ve0-x231.google.com (mail-ve0-x231.google.com [2607:f8b0:400c:c01::231]) by mx.google.com with ESMTPS id a11si5861415vcf.3.2014.06.17.12.18.22 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 17 Jun 2014 12:18:22 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2607:f8b0:400c:c01::231 as permitted sender) client-ip=2607:f8b0:400c:c01::231; Received: by mail-ve0-f177.google.com with SMTP id i13so4366668veh.8 for ; Tue, 17 Jun 2014 12:18:22 -0700 (PDT) X-Received: by 10.58.30.1 with SMTP id o1mr3130176veh.37.1403032702010; Tue, 17 Jun 2014 12:18:22 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.54.6 with SMTP id vs6csp231714vcb; Tue, 17 Jun 2014 12:18:21 -0700 (PDT) X-Received: by 10.68.193.193 with SMTP id hq1mr34674028pbc.107.1403032701005; Tue, 17 Jun 2014 12:18:21 -0700 (PDT) Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id xp2si15470571pbc.57.2014.06.17.12.18.20 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Jun 2014 12:18:20 -0700 (PDT) Received-SPF: pass (google.com: domain of libc-alpha-return-50859-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Received: (qmail 28540 invoked by alias); 17 Jun 2014 19:18:09 -0000 Mailing-List: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org Precedence: list List-Id: List-Unsubscribe: , List-Subscribe: List-Archive: List-Post: , List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 28524 invoked by uid 89); 17 Jun 2014 19:18:08 -0000 X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-wi0-f171.google.com X-Received: by 10.180.20.141 with SMTP id n13mr39047481wie.6.1403032682898; Tue, 17 Jun 2014 12:18:02 -0700 (PDT) Mime-Version: 1.0 (Mac OS X Mail 7.3 \(1878.2\)) Subject: Re: [PATCH 1/9][v3][BZ 16892] Add linux-generic lowlevellock.h From: Bernard Ogden In-Reply-To: <87vbs38cl6.fsf@igel.home> Date: Tue, 17 Jun 2014 20:17:59 +0100 Cc: Richard Henderson , libc-alpha@sourceware.org Message-Id: <924152D3-F3DE-46DB-953E-64AB36FF96D3@linaro.org> References: <5398A441.9080603@twiddle.net> <43ED977F-8000-48AD-9E57-DD78E0ACB36A@linaro.org> <87vbs38cl6.fsf@igel.home> To: Andreas Schwab X-Original-Sender: bernie.ogden@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2607:f8b0:400c:c01::231 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org; dkim=pass header.i=@sourceware.org X-Google-Group-Id: 836684582541 Darn. Converted inline functions to macros. Added some more __glibc_unlikely while I was in there. Still builds on arm. I did try to cross-build for coldfire but I failed - would you have any pointers for that? Anyway, should be fixed. OK? 2014-06-09 Bernard Ogden [BZ #16892] * sysdeps/unix/sysv/linux/lowlevellock.h: New file. On 14 Jun 2014, at 21:23, Andreas Schwab wrote: > Bernard Ogden writes: > >> +static inline int __attribute__ ((always_inline)) >> +__lll_trylock (int *futex) >> +{ >> + return atomic_compare_and_exchange_bool_acq (futex, 1, 0); >> +} > > You cannot use inlines here, it breaks coldfire: > > In file included from ../sysdeps/unix/sysv/linux/m68k/coldfire/sysdep.h:21:0, > from x.c:1: > ../sysdeps/unix/sysv/linux/lowlevellock.h: In function ‘__lll_trylock’: > ../sysdeps/unix/sysdep.h:34:31: error: ‘SYS_atomic_cmpxchg_32’ undeclared (first use in this function) > #define SYS_ify(syscall_name) SYS_##syscall_name > ^ > ../sysdeps/unix/sysv/linux/m68k/coldfire/nptl/bits/atomic.h:74:29: note: in expansion of macro ‘SYS_ify’ > = (__typeof (oldval)) SYS_ify (atomic_cmpxchg_32); \ > ^ > ../include/atomic.h:138:6: note: in expansion of macro ‘atomic_compare_and_exchange_val_acq’ > atomic_compare_and_exchange_val_acq (mem, newval, __atg3_old) \ > ^ > ../sysdeps/unix/sysv/linux/lowlevellock.h:186:10: note: in expansion of macro ‘atomic_compare_and_exchange_bool_acq’ > return atomic_compare_and_exchange_bool_acq (futex, 1, 0); > ^ > ../sysdeps/unix/sysdep.h:34:31: note: each undeclared identifier is reported only once for each function it appears in > #define SYS_ify(syscall_name) SYS_##syscall_name > ^ > ../sysdeps/unix/sysv/linux/m68k/coldfire/nptl/bits/atomic.h:74:29: note: in expansion of macro ‘SYS_ify’ > = (__typeof (oldval)) SYS_ify (atomic_cmpxchg_32); \ > ^ > ../include/atomic.h:138:6: note: in expansion of macro ‘atomic_compare_and_exchange_val_acq’ > atomic_compare_and_exchange_val_acq (mem, newval, __atg3_old) \ > ^ > ../sysdeps/unix/sysv/linux/lowlevellock.h:186:10: note: in expansion of macro ‘atomic_compare_and_exchange_bool_acq’ > return atomic_compare_and_exchange_bool_acq (futex, 1, 0); > ^ > > Andreas. > > -- > Andreas Schwab, schwab@linux-m68k.org > GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 > "And now for something completely different." diff --git a/sysdeps/unix/sysv/linux/lowlevellock.h b/sysdeps/unix/sysv/linux/lowlevellock.h new file mode 100644 index 0000000..0cef90c --- /dev/null +++ b/sysdeps/unix/sysv/linux/lowlevellock.h @@ -0,0 +1,308 @@ +/* Copyright (C) 2011-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include +#include +#include +#include +#include +#include + + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_WAIT_REQUEUE_PI 11 +#define FUTEX_CMP_REQUEUE_PI 12 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + +#define INLINE_FUTEX_SYSCALL(nr, args...) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret = INTERNAL_SYSCALL (futex, __err, nr, args); \ + if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (__ret, __err))) \ + __ret = -INTERNAL_SYSCALL_ERRNO (__ret, __err); \ + __ret; \ + }) + +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait (futexp, val, NULL, private) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INLINE_FUTEX_SYSCALL (4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + }) + +#define lll_futex_timed_wait_bitset(futexp, val, timespec, clockbit, private) \ + ({ \ + int __op = FUTEX_WAIT_BITSET | clockbit; \ + INLINE_FUTEX_SYSCALL (6, (futexp), \ + __lll_private_flag (__op, private), \ + (val), (timespec), NULL /* Unused. */, \ + FUTEX_BITSET_MATCH_ANY); \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INLINE_FUTEX_SYSCALL (4, (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + }) + +#define lll_robust_dead(futexv, private) \ + do \ + { \ + int *__futexp = &(futexv); \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + lll_futex_wake (__futexp, 1, private); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INLINE_FUTEX_SYSCALL (6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private), \ + (nr_wake), (nr_move), (mutex), (val)); \ + }) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INLINE_FUTEX_SYSCALL (6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + }) + +/* Priority Inheritance support. */ +#define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \ + lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private) + +#define lll_futex_timed_wait_requeue_pi(futexp, val, timespec, clockbit, \ + mutex, private) \ + ({ \ + int __op = FUTEX_WAIT_REQUEUE_PI | clockbit; \ + INLINE_FUTEX_SYSCALL (5, (futexp), \ + __lll_private_flag (__op, private), \ + (val), (timespec), mutex); \ + }) + +#define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, val, priv) \ + ({ \ + INLINE_FUTEX_SYSCALL (6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE_PI, priv), \ + (nr_wake), (nr_move), (mutex), (val)); \ + }) + +#define __lll_trylock(lock) \ + atomic_compare_and_exchange_bool_acq (lock, 1, 0) + +#define lll_trylock(lock) __lll_trylock (&(lock)) + +#define __lll_cond_trylock(lock) \ + atomic_compare_and_exchange_bool_acq (lock, 2, 0) + +#define lll_cond_trylock(lock) __lll_cond_trylock (&(lock)) + +#define __lll_robust_trylock(lock, id) \ + atomic_compare_and_exchange_bool_acq (lock, id, 0) + +#define lll_robust_trylock(lock, id) \ + __lll_robust_trylock (&(lock), id) + +extern void __lll_lock_wait_private (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex, int private) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; + +#define __lll_lock(futex, private) \ + (void) ({ \ + int *__futex = (futex); \ + if (__glibc_unlikely (atomic_compare_and_exchange_bool_acq (__futex, \ + 1, 0) != 0)) \ + { \ + if (__builtin_constant_p (private) && private == LLL_PRIVATE) \ + __lll_lock_wait_private (__futex); \ + else \ + __lll_lock_wait (__futex, private); \ + } \ + }) +#define lll_lock(futex, private) __lll_lock (&(futex), private) + + +#define __lll_robust_lock(futex, id, private) \ + ({ \ + int *__futex = (futex); \ + int __val = 0; \ + if (__glibc_unlikely (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0) != 0)) \ + __val = __lll_robust_lock_wait (__futex, private); \ + __val; \ + }) +#define lll_robust_lock(futex, id, private) \ + __lll_robust_lock (&(futex), id, private) + + +#define __lll_cond_lock(futex, private) \ + (void) ({ \ + int *__futex = (futex); \ + if (__glibc_unlikely (atomic_compare_and_exchange_bool_acq (__futex, 2, \ + 0) != 0)) \ + __lll_lock_wait (__futex, private); \ + }) +#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) + + +#define lll_robust_cond_lock(futex, id, private) \ + __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; + +#define __lll_timedlock(futex, abstime, private) \ + ({ \ + int *__futex = (futex); \ + int __val = 0; \ + if (__glibc_unlikely (atomic_compare_and_exchange_bool_acq (__futex, 1, \ + 0) != 0)) \ + __val = __lll_timedlock_wait (__futex, abstime, private); \ + __val; \ + }) +#define lll_timedlock(futex, abstime, private) \ + __lll_timedlock (&(futex), abstime, private) + + +#define __lll_robust_timedlock(futex, abstime, id, private) \ + ({ \ + int *__futex = (futex); \ + int __val = 0; \ + if (__glibc_unlikely (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0) != 0)) \ + __val = __lll_robust_timedlock_wait (__futex, abstime, private); \ + __val; \ + }) +#define lll_robust_timedlock(futex, abstime, id, private) \ + __lll_robust_timedlock (&(futex), abstime, id, private) + + +#define __lll_unlock(futex, private) \ + (void) ({ \ + int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__glibc_unlikely (__oldval > 1)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_unlock(futex, private) __lll_unlock(&(futex), private) + + +#define __lll_robust_unlock(futex, private) \ + (void) ({ \ + int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__glibc_unlikely (__oldval & FUTEX_WAITERS)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_robust_unlock(futex, private) \ + __lll_robust_unlock(&(futex), private) + + +#define lll_islocked(futex) \ + (futex != 0) + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + +/* The states of a lock are: + 0 - untaken + 1 - taken by one user + >1 - taken by more users */ + +/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ +#define lll_wait_tid(tid) \ + do { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED); \ + } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __res = 0; \ + if ((tid) != 0) \ + __res = __lll_timedwait_tid (&(tid), (abstime)); \ + __res; \ + }) + +#endif /* lowlevellock.h */