From patchwork Wed Oct 30 20:00:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 178130 Delivered-To: patch@linaro.org Received: by 2002:a92:409a:0:0:0:0:0 with SMTP id d26csp1756238ill; Wed, 30 Oct 2019 13:03:04 -0700 (PDT) X-Google-Smtp-Source: APXvYqx++KOGC2ihd6rf8jzI+a9+kYrmaZku4JZXOf74ooDKcjaO05gMqvBGGpWhPVvECUoI0yaW X-Received: by 2002:a17:906:2793:: with SMTP id j19mr11639ejc.55.1572465784323; Wed, 30 Oct 2019 13:03:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1572465784; cv=none; d=google.com; s=arc-20160816; b=arRm2W27R+l+Y2aiMa+1smg/9miFVQkQRslwbfqtEh8Vvhfg4jE1CUQsUSw0tkYIGz B7X0govKDJ1iuVkjwkj/peVwNromzIMyWD8H25UO4eiB9HEKAW2K2JwXZRR4LHO/x9BQ JBWTCOMXZaOrVlq0jninVeTi0ZIMmpbLCiY5WO2CW6MOHYC1DoFxK0iQsFFBt8Hi4vRf gRKMcEJAGnx0/qZImFoDX98wnwsfu23BpJkVDX7r0t+1iu6btl0WVDsa8fIRP5uGuAaU 7ADvDJzSoe6zAKTFj2gChkA2SkY+sLAzw5WTVNNO07ifPqCl84jiYnKjXmbpthiNlWNO XSUg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:delivered-to:sender:list-help:list-post:list-archive :list-subscribe:list-unsubscribe:list-id:precedence:mailing-list :dkim-signature:domainkey-signature; bh=ECsuoWy9mf5dueOC+3sp8CpJI/QDI1ASArqHFHCf0Z8=; b=KP32laLMTH96268AYquKcapz/VyfI9o28zW+BsPGo92XYfmGjAa8MxBel3FzkFTOKM baw6RnSixc3DElII1KS6FyeUAQHFllzsy6kOi19syTsh3NAaVR7kYGaC1AIiSutKw+wu mLnUkSFCaBxGMV1l8l4RW7y+MU81On/pTB5TOgAYC9kkF0FTem2EMmogm3Xjkx3IBGH8 rmToMSSR5FzFfReQOFSbSQgSePsYR0IupzhGV0xa/SSi/XflFld5NqG4BR+UrAp3sJQK n+8dNyYi6MkDoNCtgNdpIrdlxochSs54Q+wZPvtpLS8yI/1mam9zQqlSTFwDQ8eqdhqe r2+w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=yrEEDQE3; dkim=pass header.i=@linaro.org header.s=google header.b=yQ4b2X4l; spf=pass (google.com: domain of libc-alpha-return-106482-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="libc-alpha-return-106482-patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id k1si1971128eja.146.2019.10.30.13.03.03 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 30 Oct 2019 13:03:04 -0700 (PDT) Received-SPF: pass (google.com: domain of libc-alpha-return-106482-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=yrEEDQE3; dkim=pass header.i=@linaro.org header.s=google header.b=yQ4b2X4l; spf=pass (google.com: domain of libc-alpha-return-106482-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="libc-alpha-return-106482-patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references; q=dns; s=default; b=Ce+he1B4nHkOZHk9fb97jt0XeDjlTcJ BSvt3AjCzUPQ+YZ5FudlIy6TLlPOXTBEk1JxTWCrmsgTo7V9DTYfj93qP2WakDdE gplkU6XJ8ZBwBmCPbHF2WB32QeoWgb50ZuDzPJ7VNb/etyqcB7lvFy/sO781a0MX yyE5DpqmempM= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references; s=default; bh=40naVJiwa63BUd93CqDg/ViiM1o=; b=yrEED QE3r5QB7BPbvrZ+WzR7edgWhRj6uGG8zxAKz2lyq8i43mcaGW8QfUfHIAq1swqIQ nTQrybA/q8vsukAx3DJ2yb/H8uCaSUz032mWLZNWYRZQpyPEr87WyTiW93VovKL+ ESSmpnrLSnfN8Poy6HZlCq67SRoaG8B4Ws90P4= Received: (qmail 83600 invoked by alias); 30 Oct 2019 20:01:37 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk 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 78650 invoked by uid 89); 30 Oct 2019 20:01:17 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=lowlevel, tsp, low-level X-HELO: mail-qt1-f193.google.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ECsuoWy9mf5dueOC+3sp8CpJI/QDI1ASArqHFHCf0Z8=; b=yQ4b2X4luOi10TfZjpENzvQM1Z0MKreB8b15fJG79zHXNf29h8E8kjYTI+SJi4oZmB 7TnPoXwn5w2zEd1jRm2/HLG62Ne7rv/rKcwDWJWsgz0v8QVw5Vt/4p9eGTN9MB2Ljk+F 2TeL7GLX3VS9Ta7QfCWQXfO3tapBvRWb1GMrWOrxWo44ssh42dbJLGagxZnYjotSP6+a sbh7DdllC5dwe+ZN/474XMEt+pp1kTprfup97k4NFBlcTc3wfbdc1oQqRnP87YSfdzVV rwZ+uugqzAQkxZoRSeWz+5Q9q2rl63MovXzmbknLNHlRdnXpzb/hrUME7W5/Kkvn1uF1 J8dA== Return-Path: From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Alistair Francis Subject: [PATCH 3/5] nptl: Replace non cancellable pause/nanosleep with futex Date: Wed, 30 Oct 2019 17:00:50 -0300 Message-Id: <20191030200052.497-3-adhemerval.zanella@linaro.org> In-Reply-To: <20191030200052.497-1-adhemerval.zanella@linaro.org> References: <20191030200052.497-1-adhemerval.zanella@linaro.org> To help y2038 work avoid duplicate all the logic of nanosleep on non cancellable version, the patch replaces it with a new futex operation, lll_timedwait. The changes are: - Add a expected value for __lll_clocklock_wait, so it can be used to wait for generic values. - Remove its internal atomic operation and move the logic to __lll_clocklock. It makes __lll_clocklock_wait even more generic and __lll_clocklock slight faster on fast-path (since it won't require a function call anymore). - Add lll_timedwait, which uses __lll_clocklock_wait, to replace both __pause_nocancel and __nanosleep_nocancel. It also allows remove the sparc32 __lll_clocklock_wait implementation (since it is similar to the generic one). Checked on x86_64-linux-gnu, sparcv9-linux-gnu, and i686-linux-gnu. --- nptl/lll_timedlock_wait.c | 35 ++++++++-------- nptl/pthread_mutex_lock.c | 3 +- nptl/pthread_mutex_timedlock.c | 20 ++-------- sysdeps/nptl/lowlevellock.h | 15 ++++++- sysdeps/sparc/sparc32/lll_timedlock_wait.c | 1 - sysdeps/sparc/sparc32/lowlevellock.c | 42 -------------------- sysdeps/unix/sysv/linux/sparc/lowlevellock.h | 22 +++++++++- 7 files changed, 56 insertions(+), 82 deletions(-) delete mode 100644 sysdeps/sparc/sparc32/lll_timedlock_wait.c -- 2.17.1 Reviewed-by: Carlos O'Donell diff --git a/nptl/lll_timedlock_wait.c b/nptl/lll_timedlock_wait.c index cd3cc3d371..952b042555 100644 --- a/nptl/lll_timedlock_wait.c +++ b/nptl/lll_timedlock_wait.c @@ -25,39 +25,38 @@ int -__lll_clocklock_wait (int *futex, clockid_t clockid, +__lll_clocklock_wait (int *futex, int val, clockid_t clockid, const struct timespec *abstime, int private) { - /* Reject invalid timeouts. */ - if (! valid_nanoseconds (abstime->tv_nsec)) - return EINVAL; + struct timespec ts, *tsp = NULL; - /* Try locking. */ - while (atomic_exchange_acq (futex, 2) != 0) + if (abstime != NULL) { - struct timespec ts; + /* Reject invalid timeouts. */ + if (! valid_nanoseconds (abstime->tv_nsec)) + return EINVAL; - /* Get the current time. This can only fail if clockid is not - valid. */ + /* Get the current time. This can only fail if clockid is not valid. */ if (__glibc_unlikely (__clock_gettime (clockid, &ts) != 0)) return EINVAL; /* Compute relative timeout. */ - struct timespec rt; - rt.tv_sec = abstime->tv_sec - ts.tv_sec; - rt.tv_nsec = abstime->tv_nsec - ts.tv_nsec; - if (rt.tv_nsec < 0) + ts.tv_sec = abstime->tv_sec - ts.tv_sec; + ts.tv_nsec = abstime->tv_nsec - ts.tv_nsec; + if (ts.tv_nsec < 0) { - rt.tv_nsec += 1000000000; - --rt.tv_sec; + ts.tv_nsec += 1000000000; + --ts.tv_sec; } - if (rt.tv_sec < 0) + if (ts.tv_sec < 0) return ETIMEDOUT; - /* If *futex == 2, wait until woken or timeout. */ - lll_futex_timed_wait (futex, 2, &rt, private); + tsp = &ts; } + /* If *futex == val, wait until woken or timeout. */ + lll_futex_timed_wait (futex, val, tsp, private); + return 0; } diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c index 0ab890d815..ace436d5a6 100644 --- a/nptl/pthread_mutex_lock.c +++ b/nptl/pthread_mutex_lock.c @@ -434,7 +434,8 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) /* Delay the thread indefinitely. */ while (1) - __pause_nocancel (); + lll_timedwait (&(int){0}, 0, 0 /* ignored */, NULL, + private); } oldval = mutex->__data.__lock; diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c index c9bb3b9176..490064d8cf 100644 --- a/nptl/pthread_mutex_timedlock.c +++ b/nptl/pthread_mutex_timedlock.c @@ -401,22 +401,10 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex, /* Delay the thread until the timeout is reached. Then return ETIMEDOUT. */ - struct timespec reltime; - struct timespec now; - - INTERNAL_SYSCALL (clock_gettime, __err, 2, clockid, - &now); - reltime.tv_sec = abstime->tv_sec - now.tv_sec; - reltime.tv_nsec = abstime->tv_nsec - now.tv_nsec; - if (reltime.tv_nsec < 0) - { - reltime.tv_nsec += 1000000000; - --reltime.tv_sec; - } - if (reltime.tv_sec >= 0) - while (__nanosleep_nocancel (&reltime, &reltime) != 0) - continue; - + do + e = lll_timedwait (&(int){0}, 0, clockid, abstime, + private); + while (e != ETIMEDOUT); return ETIMEDOUT; } diff --git a/sysdeps/nptl/lowlevellock.h b/sysdeps/nptl/lowlevellock.h index e3f006537a..92298f3b7e 100644 --- a/sysdeps/nptl/lowlevellock.h +++ b/sysdeps/nptl/lowlevellock.h @@ -21,6 +21,7 @@ #include #include +#include /* Low-level locks use a combination of atomic operations (to acquire and release lock ownership) and futex operations (to block until the state @@ -121,10 +122,12 @@ extern void __lll_lock_wait (int *futex, int private) attribute_hidden; #define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) -extern int __lll_clocklock_wait (int *futex, clockid_t, +extern int __lll_clocklock_wait (int *futex, int val, clockid_t, const struct timespec *, int private) attribute_hidden; +#define lll_timedwait(futex, val, clockid, abstime, private) \ + __lll_clocklock_wait (futex, val, clockid, abstime, private) /* As __lll_lock, but with an absolute timeout measured against the clock specified in CLOCKID. If the timeout occurs then return ETIMEDOUT. If @@ -136,7 +139,15 @@ extern int __lll_clocklock_wait (int *futex, clockid_t, \ if (__glibc_unlikely \ (atomic_compare_and_exchange_bool_acq (__futex, 1, 0))) \ - __val = __lll_clocklock_wait (__futex, clockid, abstime, private); \ + { \ + while (atomic_exchange_acq (futex, 2) != 0) \ + { \ + __val = __lll_clocklock_wait (__futex, 2, clockid, \ + abstime, private); \ + if (__val == EINVAL || __val == ETIMEDOUT) \ + break; \ + } \ + } \ __val; \ }) #define lll_clocklock(futex, clockid, abstime, private) \ diff --git a/sysdeps/sparc/sparc32/lll_timedlock_wait.c b/sysdeps/sparc/sparc32/lll_timedlock_wait.c deleted file mode 100644 index bd639a7091..0000000000 --- a/sysdeps/sparc/sparc32/lll_timedlock_wait.c +++ /dev/null @@ -1 +0,0 @@ -/* __lll_clocklock_wait is in lowlevellock.c. */ diff --git a/sysdeps/sparc/sparc32/lowlevellock.c b/sysdeps/sparc/sparc32/lowlevellock.c index 074ecf0636..1a0ab4d9f2 100644 --- a/sysdeps/sparc/sparc32/lowlevellock.c +++ b/sysdeps/sparc/sparc32/lowlevellock.c @@ -50,46 +50,4 @@ __lll_lock_wait (int *futex, int private) } while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0); } - - -int -__lll_clocklock_wait (int *futex, clockid_t clockid, - const struct timespec *abstime, int private) -{ - /* Reject invalid timeouts. */ - if (! valid_nanoseconds (abstime->tv_nsec)) - return EINVAL; - - do - { - struct timespec ts; - struct timespec rt; - - /* Get the current time. This can only fail if clockid is not - valid. */ - if (__glibc_unlikely (__clock_gettime (clockid, &ts) != 0)) - return EINVAL; - - /* Compute relative timeout. */ - rt.tv_sec = abstime->tv_sec - ts.tv_sec; - rt.tv_nsec = abstime->tv_nsec - ts.tv_nsec; - if (rt.tv_nsec < 0) - { - rt.tv_nsec += 1000000000; - --rt.tv_sec; - } - - /* Already timed out? */ - if (rt.tv_sec < 0) - return ETIMEDOUT; - - /* Wait. */ - int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1); - if (oldval != 0) - lll_futex_timed_wait (futex, 2, &rt, private); - } - while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0); - - return 0; -} #endif diff --git a/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/sysdeps/unix/sysv/linux/sparc/lowlevellock.h index 34441f8ff5..6c005e8ffa 100644 --- a/sysdeps/unix/sysv/linux/sparc/lowlevellock.h +++ b/sysdeps/unix/sysv/linux/sparc/lowlevellock.h @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -75,9 +76,13 @@ __lll_cond_lock (int *futex, int private) #define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) -extern int __lll_clocklock_wait (int *futex, clockid_t, const struct timespec *, +extern int __lll_clocklock_wait (int *futex, clockid_t, int val, + const struct timespec *, int private) attribute_hidden; +#define lll_timedwait(futex, val, clockid, abstime, private) \ + __lll_clocklock_wait (futex, val, clockid, abstime, private) + static inline int __attribute__ ((always_inline)) __lll_clocklock (int *futex, clockid_t clockid, @@ -87,7 +92,20 @@ __lll_clocklock (int *futex, clockid_t clockid, int result = 0; if (__glibc_unlikely (val != 0)) - result = __lll_clocklock_wait (futex, clockid, abstime, private); + { + do + { + int oldval = atomic_compare_and_exchange_val_24_acq (futex, val, 1); + if (oldval != 0) + { + result = __lll_clocklock_wait (futex, 2, clockid, abstime, + private); + if (result == EINVAL || result == ETIMEDOUT) + break; + } + } + while (atomic_compare_and_exchange_val_24_acq (futex, val, 0) != 0); + } return result; } #define lll_clocklock(futex, clockid, abstime, private) \