From patchwork Fri Mar 21 13:50:00 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: bniebuhr@efjohnson.com X-Patchwork-Id: 332656 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from whitealder.osuosl.org (whitealder.osuosl.org [140.211.166.138]) by ozlabs.org (Postfix) with ESMTP id BCD192C0082 for ; Sat, 22 Mar 2014 00:59:11 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 82EB78A8C0; Fri, 21 Mar 2014 13:59:08 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id CjjEbC3jPodw; Fri, 21 Mar 2014 13:59:06 +0000 (UTC) Received: from ash.osuosl.org (ash.osuosl.org [140.211.166.34]) by whitealder.osuosl.org (Postfix) with ESMTP id 0FE2F8AB06; Fri, 21 Mar 2014 13:59:06 +0000 (UTC) X-Original-To: uclibc@lists.busybox.net Delivered-To: uclibc@osuosl.org Received: from silver.osuosl.org (silver.osuosl.org [140.211.166.136]) by ash.osuosl.org (Postfix) with ESMTP id 2261A1BF9AF for ; Fri, 21 Mar 2014 13:59:05 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 1D294331F9 for ; Fri, 21 Mar 2014 13:59:05 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id X9RjYKOANvUY for ; Fri, 21 Mar 2014 13:59:04 +0000 (UTC) X-Greylist: delayed 00:06:47 by SQLgrey-1.7.6 Received: from devel-desktop (unknown [8.34.96.66]) by silver.osuosl.org (Postfix) with ESMTPS id 0913D32E96 for ; Fri, 21 Mar 2014 13:59:03 +0000 (UTC) Received: from devel-desktop (localhost [127.0.0.1]) by devel-desktop (8.14.4/8.14.4/Debian-2.1ubuntu4) with ESMTP id s2LDqA5K004499; Fri, 21 Mar 2014 08:52:10 -0500 Received: (from devel@localhost) by devel-desktop (8.14.4/8.14.4/Submit) id s2LDp2kF004493; Fri, 21 Mar 2014 08:51:02 -0500 X-Authentication-Warning: devel-desktop: devel set sender to bniebuhr@efjohnson.com using -f From: bniebuhr@efjohnson.com To: uclibc@uclibc.org Subject: [PATCH] Fix __lll_timedlock_wait busy-wait issue Date: Fri, 21 Mar 2014 08:50:00 -0500 Message-Id: <1395409800-4457-1-git-send-email-bniebuhr@efjohnson.com> X-Mailer: git-send-email 1.8.3.2 X-BeenThere: uclibc@uclibc.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Discussion and development of uClibc \(the embedded C library\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: uclibc-bounces@uclibc.org Sender: uclibc-bounces@uclibc.org From: Brian Niebuhr __lll_timedlock_wait has a bug that is exposed in these conditions: 1. Thread 1 acquires the lock 2. Thread 2 attempts to acquire the lock and waits via futex syscall 3. Thread 1 unlocks the lock and wakes the waiting thread 4. Thread 1 re-aquires the lock before thread 2 gets the CPU What happens in this case is that the futex value is set to '1' since Thread 1 reaquired the lock through the fast path (since it had just been released). The problem is that Thread 2 is in the loop in __lll_timedlock_wait and it expects the futex value to be '2'. atomic_compare_and_exchange_bool_acq only sets the futex value to '2' if it is already set to '0', and since Thread 1 reaquired the lock, the futex remains set to '1'. When Thread 2 attempts to wait on the futex, the operating system returns -EWOULDBLOCK since the futex value is not '2'. This causes a busy wait condition where Thread 2 continuously attempts to wait on the futex and the kernel immediately returns -EWOULDBLOCK. This continues until Thread 1 releases the lock. The fix is to use atomic_exchange_acq instead of atomic_compare_and_exchange_bool_acq which will force the futex value to '2' on each loop iteration. This change makes uClibc line up with glibc's implementation. Signed-off-by: Brian Niebuhr --- libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c index af864b3..4f7e890 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c @@ -60,10 +60,7 @@ __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) return EINVAL; /* Upgrade the lock. */ - if (atomic_exchange_acq (futex, 2) == 0) - return 0; - - do + while (atomic_exchange_acq (futex, 2) != 0) { struct timeval tv; @@ -86,7 +83,6 @@ __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) // XYZ: Lost the lock to check whether it was private. lll_futex_timed_wait (futex, 2, &rt, private); } - while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); return 0; }