Received: by 10.192.165.148 with SMTP id m20csp178537imm; Fri, 4 May 2018 08:32:51 -0700 (PDT) X-Google-Smtp-Source: AB8JxZptntirB4DiRVkhxNOLMke/jW2Mu7Yz/xXKpkaufSKHB7+8RUPA1h+F+WETcnfaKJl7NL1y X-Received: by 2002:a63:90c4:: with SMTP id a187-v6mr22603770pge.189.1525447971596; Fri, 04 May 2018 08:32:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525447971; cv=none; d=google.com; s=arc-20160816; b=gd21ryNmkkz8SW3aDz0XAc6bkqEzbpGOkvY4utPlkwBbUKGNN5f1Jvjx+sTriPyfVP xR2iVfVvGZP3BaYihd1xPJwMCjFxCfb7JXOlKpCYibVxMJDbRz2SI09K2LyJim1/V0Ao 90i8xox55rx43jhEPETFEJ/IqCvN1QWeJttFtk/3xKdFiR1MJKRNoqt9joJ7Q45Ucn+H JYChj3cj5AAtUtZsGdriuf2lqafdonBkD074YsqFkyu4v/4+FlPUcbLcsRYVu0qViz0n pG57RpkXqB08UbxgWtRf7Ebo0uq/OqEA6A4Tm6Q71Q9pjmYECZSngwWVmdhzWoEpzaFp v1/Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:arc-authentication-results; bh=w30Pu13Y2KEagrd4ZUGHctyM6JWI5bDMxK2vYaH66lk=; b=xkHdnu4ysFApys1JiPOAr+SAkYLNc6T2aBzWT253gEjV0pqlbB9H/7CCAo7U5X1G0e tFM5GK48zz+Tm+gplmTAK+BLSdrdZbsbBavx8PBOGxTMsrB+ZBxBxlMk5LpRD68tfArp CIaWiq3J0irGzVShi6lRe3QmWZIbwKl0b9+5W0jT7EBnn3sm5yAiBESu9ZgNp4+jKlKz onGTGXHcL0icpgK8O7BYJAZBgOZd+hlHu3MOkMVspCGd/QV5m4vZ+Xx89Hm9SCvsyq0R ejuzyZG/JNzrMrkwvIFHnQl6u2btcLD/fu5HTV1CZKU+3V4c4m94OJN+egpOKbPoOMYg ROXA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 31-v6si16031133plz.364.2018.05.04.08.32.36; Fri, 04 May 2018 08:32:51 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751341AbeEDPcZ (ORCPT + 99 others); Fri, 4 May 2018 11:32:25 -0400 Received: from Galois.linutronix.de ([146.0.238.70]:41213 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751196AbeEDPcX (ORCPT ); Fri, 4 May 2018 11:32:23 -0400 Received: from localhost ([127.0.0.1] helo=bazinga.breakpoint.cc) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1fEch3-0006aN-4z; Fri, 04 May 2018 17:32:21 +0200 From: Sebastian Andrzej Siewior To: linux-kernel@vger.kernel.org Cc: tglx@linutronix.de, Nicholas Bellinger , Andrew Morton , Sebastian Andrzej Siewior Subject: [PATCH] percpu_ida: Use _irqsave() instead of local_irq_save() + spin_lock Date: Fri, 4 May 2018 17:32:18 +0200 Message-Id: <20180504153218.7301-1-bigeasy@linutronix.de> X-Mailer: git-send-email 2.17.0 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org percpu_ida() decouples disabling interrupts from the locking operations. This breaks some assumptions if the locking operations are replaced like they are under -RT. The same locking can be achieved by avoiding local_irq_save() and using spin_lock_irqsave() instead. percpu_ida_alloc() gains one more preemption point because after unlocking the fastpath and before the pool lock is acquired, the interrupts are briefly enabled. Signed-off-by: Sebastian Andrzej Siewior --- lib/percpu_ida.c | 63 ++++++++++++++++-------------------------------- 1 file changed, 21 insertions(+), 42 deletions(-) diff --git a/lib/percpu_ida.c b/lib/percpu_ida.c index 6016f1deb1f5..9bbd9c5d375a 100644 --- a/lib/percpu_ida.c +++ b/lib/percpu_ida.c @@ -112,18 +112,6 @@ static inline void alloc_global_tags(struct percpu_ida= *pool, min(pool->nr_free, pool->percpu_batch_size)); } =20 -static inline unsigned alloc_local_tag(struct percpu_ida_cpu *tags) -{ - int tag =3D -ENOSPC; - - spin_lock(&tags->lock); - if (tags->nr_free) - tag =3D tags->freelist[--tags->nr_free]; - spin_unlock(&tags->lock); - - return tag; -} - /** * percpu_ida_alloc - allocate a tag * @pool: pool to allocate from @@ -147,20 +135,22 @@ int percpu_ida_alloc(struct percpu_ida *pool, int sta= te) DEFINE_WAIT(wait); struct percpu_ida_cpu *tags; unsigned long flags; - int tag; + int tag =3D -ENOSPC; =20 - local_irq_save(flags); - tags =3D this_cpu_ptr(pool->tag_cpu); + tags =3D raw_cpu_ptr(pool->tag_cpu); + spin_lock_irqsave(&tags->lock, flags); =20 /* Fastpath */ - tag =3D alloc_local_tag(tags); - if (likely(tag >=3D 0)) { - local_irq_restore(flags); + if (likely(tags->nr_free >=3D 0)) { + tag =3D tags->freelist[--tags->nr_free]; + spin_unlock_irqrestore(&tags->lock, flags); return tag; } + spin_unlock_irqrestore(&tags->lock, flags); =20 while (1) { - spin_lock(&pool->lock); + spin_lock_irqsave(&pool->lock, flags); + tags =3D this_cpu_ptr(pool->tag_cpu); =20 /* * prepare_to_wait() must come before steal_tags(), in case @@ -184,8 +174,7 @@ int percpu_ida_alloc(struct percpu_ida *pool, int state) &pool->cpus_have_tags); } =20 - spin_unlock(&pool->lock); - local_irq_restore(flags); + spin_unlock_irqrestore(&pool->lock, flags); =20 if (tag >=3D 0 || state =3D=3D TASK_RUNNING) break; @@ -196,9 +185,6 @@ int percpu_ida_alloc(struct percpu_ida *pool, int state) } =20 schedule(); - - local_irq_save(flags); - tags =3D this_cpu_ptr(pool->tag_cpu); } if (state !=3D TASK_RUNNING) finish_wait(&pool->wait, &wait); @@ -222,28 +208,24 @@ void percpu_ida_free(struct percpu_ida *pool, unsigne= d tag) =20 BUG_ON(tag >=3D pool->nr_tags); =20 - local_irq_save(flags); - tags =3D this_cpu_ptr(pool->tag_cpu); + tags =3D raw_cpu_ptr(pool->tag_cpu); =20 - spin_lock(&tags->lock); + spin_lock_irqsave(&tags->lock, flags); tags->freelist[tags->nr_free++] =3D tag; =20 nr_free =3D tags->nr_free; - spin_unlock(&tags->lock); =20 if (nr_free =3D=3D 1) { cpumask_set_cpu(smp_processor_id(), &pool->cpus_have_tags); wake_up(&pool->wait); } + spin_unlock_irqrestore(&tags->lock, flags); =20 if (nr_free =3D=3D pool->percpu_max_size) { - spin_lock(&pool->lock); + spin_lock_irqsave(&pool->lock, flags); + spin_lock(&tags->lock); =20 - /* - * Global lock held and irqs disabled, don't need percpu - * lock - */ if (tags->nr_free =3D=3D pool->percpu_max_size) { move_tags(pool->freelist, &pool->nr_free, tags->freelist, &tags->nr_free, @@ -251,10 +233,9 @@ void percpu_ida_free(struct percpu_ida *pool, unsigned= tag) =20 wake_up(&pool->wait); } - spin_unlock(&pool->lock); + spin_unlock(&tags->lock); + spin_unlock_irqrestore(&pool->lock, flags); } - - local_irq_restore(flags); } EXPORT_SYMBOL_GPL(percpu_ida_free); =20 @@ -346,29 +327,27 @@ int percpu_ida_for_each_free(struct percpu_ida *pool,= percpu_ida_cb fn, struct percpu_ida_cpu *remote; unsigned cpu, i, err =3D 0; =20 - local_irq_save(flags); for_each_possible_cpu(cpu) { remote =3D per_cpu_ptr(pool->tag_cpu, cpu); - spin_lock(&remote->lock); + spin_lock_irqsave(&remote->lock, flags); for (i =3D 0; i < remote->nr_free; i++) { err =3D fn(remote->freelist[i], data); if (err) break; } - spin_unlock(&remote->lock); + spin_unlock_irqrestore(&remote->lock, flags); if (err) goto out; } =20 - spin_lock(&pool->lock); + spin_lock_irqsave(&pool->lock, flags); for (i =3D 0; i < pool->nr_free; i++) { err =3D fn(pool->freelist[i], data); if (err) break; } - spin_unlock(&pool->lock); + spin_unlock_irqrestore(&pool->lock, flags); out: - local_irq_restore(flags); return err; } EXPORT_SYMBOL_GPL(percpu_ida_for_each_free); --=20 2.17.0