From: Vlastimil Babka <vbabka@suse.cz>
To: Suren Baghdasaryan <surenb@google.com>,
"Liam R. Howlett" <Liam.Howlett@oracle.com>,
Christoph Lameter <cl@linux.com>,
David Rientjes <rientjes@google.com>
Cc: Roman Gushchin <roman.gushchin@linux.dev>,
Harry Yoo <harry.yoo@oracle.com>,
Uladzislau Rezki <urezki@gmail.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
rcu@vger.kernel.org, maple-tree@lists.infradead.org,
vbabka@suse.cz
Subject: [PATCH RFC v3 5/8] slab: determine barn status racily outside of lock
Date: Mon, 17 Mar 2025 15:33:06 +0100 [thread overview]
Message-ID: <20250317-slub-percpu-caches-v3-5-9d9884d8b643@suse.cz> (raw)
In-Reply-To: <20250317-slub-percpu-caches-v3-0-9d9884d8b643@suse.cz>
The possibility of many barn operations is determined by the current
number of full or empty sheaves. Taking the barn->lock just to find out
that e.g. there are no empty sheaves results in unnecessary overhead and
lock contention. Thus perform these checks outside of the lock with a
data_race() annotated variable read and fail quickly without taking the
lock.
Checks for sheaf availability that racily succeed have to be obviously
repeated under the lock for correctness, but we can skip repeating
checks if there are too many sheaves on the given list as the limits
don't need to be strict.
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Reviewed-by: Suren Baghdasaryan <surenb@google.com>
Reviewed-by: Harry Yoo <harry.yoo@oracle.com>
---
mm/slub.c | 57 ++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 34 insertions(+), 23 deletions(-)
diff --git a/mm/slub.c b/mm/slub.c
index ab3532d5f41045d8268b12ad774541dcd066c4c4..2c7b2a85c628d01fa4811dd6cd3e4fd198d80381 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2698,9 +2698,12 @@ static struct slab_sheaf *barn_get_empty_sheaf(struct node_barn *barn)
struct slab_sheaf *empty = NULL;
unsigned long flags;
+ if (!data_race(barn->nr_empty))
+ return NULL;
+
spin_lock_irqsave(&barn->lock, flags);
- if (barn->nr_empty) {
+ if (likely(barn->nr_empty)) {
empty = list_first_entry(&barn->sheaves_empty,
struct slab_sheaf, barn_list);
list_del(&empty->barn_list);
@@ -2716,38 +2719,36 @@ static int barn_put_empty_sheaf(struct node_barn *barn,
struct slab_sheaf *sheaf, bool ignore_limit)
{
unsigned long flags;
- int ret = 0;
+
+ /* we don't repeat the check under barn->lock as it's not critical */
+ if (!ignore_limit && data_race(barn->nr_empty) >= MAX_EMPTY_SHEAVES)
+ return -E2BIG;
spin_lock_irqsave(&barn->lock, flags);
- if (!ignore_limit && barn->nr_empty >= MAX_EMPTY_SHEAVES) {
- ret = -E2BIG;
- } else {
- list_add(&sheaf->barn_list, &barn->sheaves_empty);
- barn->nr_empty++;
- }
+ list_add(&sheaf->barn_list, &barn->sheaves_empty);
+ barn->nr_empty++;
spin_unlock_irqrestore(&barn->lock, flags);
- return ret;
+ return 0;
}
static int barn_put_full_sheaf(struct node_barn *barn, struct slab_sheaf *sheaf,
bool ignore_limit)
{
unsigned long flags;
- int ret = 0;
+
+ /* we don't repeat the check under barn->lock as it's not critical */
+ if (!ignore_limit && data_race(barn->nr_full) >= MAX_FULL_SHEAVES)
+ return -E2BIG;
spin_lock_irqsave(&barn->lock, flags);
- if (!ignore_limit && barn->nr_full >= MAX_FULL_SHEAVES) {
- ret = -E2BIG;
- } else {
- list_add(&sheaf->barn_list, &barn->sheaves_full);
- barn->nr_full++;
- }
+ list_add(&sheaf->barn_list, &barn->sheaves_full);
+ barn->nr_full++;
spin_unlock_irqrestore(&barn->lock, flags);
- return ret;
+ return 0;
}
static struct slab_sheaf *barn_get_full_or_empty_sheaf(struct node_barn *barn)
@@ -2755,6 +2756,9 @@ static struct slab_sheaf *barn_get_full_or_empty_sheaf(struct node_barn *barn)
struct slab_sheaf *sheaf = NULL;
unsigned long flags;
+ if (!data_race(barn->nr_full) && !data_race(barn->nr_empty))
+ return NULL;
+
spin_lock_irqsave(&barn->lock, flags);
if (barn->nr_full) {
@@ -2785,9 +2789,12 @@ barn_replace_empty_sheaf(struct node_barn *barn, struct slab_sheaf *empty)
struct slab_sheaf *full = NULL;
unsigned long flags;
+ if (!data_race(barn->nr_full))
+ return NULL;
+
spin_lock_irqsave(&barn->lock, flags);
- if (barn->nr_full) {
+ if (likely(barn->nr_full)) {
full = list_first_entry(&barn->sheaves_full, struct slab_sheaf,
barn_list);
list_del(&full->barn_list);
@@ -2810,19 +2817,23 @@ barn_replace_full_sheaf(struct node_barn *barn, struct slab_sheaf *full)
struct slab_sheaf *empty;
unsigned long flags;
+ /* we don't repeat this check under barn->lock as it's not critical */
+ if (data_race(barn->nr_full) >= MAX_FULL_SHEAVES)
+ return ERR_PTR(-E2BIG);
+ if (!data_race(barn->nr_empty))
+ return ERR_PTR(-ENOMEM);
+
spin_lock_irqsave(&barn->lock, flags);
- if (barn->nr_full >= MAX_FULL_SHEAVES) {
- empty = ERR_PTR(-E2BIG);
- } else if (!barn->nr_empty) {
- empty = ERR_PTR(-ENOMEM);
- } else {
+ if (likely(barn->nr_empty)) {
empty = list_first_entry(&barn->sheaves_empty, struct slab_sheaf,
barn_list);
list_del(&empty->barn_list);
list_add(&full->barn_list, &barn->sheaves_full);
barn->nr_empty--;
barn->nr_full++;
+ } else {
+ empty = ERR_PTR(-ENOMEM);
}
spin_unlock_irqrestore(&barn->lock, flags);
--
2.48.1
next prev parent reply other threads:[~2025-03-17 14:33 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-17 14:33 [PATCH RFC v3 0/8] SLUB percpu sheaves Vlastimil Babka
2025-03-17 14:33 ` [PATCH RFC v3 1/8] locking/local_lock: Introduce localtry_lock_t Vlastimil Babka
2025-03-17 14:33 ` [PATCH RFC v3 2/8] slab: add opt-in caching layer of percpu sheaves Vlastimil Babka
2025-04-03 8:31 ` Harry Yoo
2025-04-03 14:11 ` Vlastimil Babka
2025-04-10 19:51 ` Suren Baghdasaryan
2025-04-22 15:02 ` Vlastimil Babka
2025-03-17 14:33 ` [PATCH RFC v3 3/8] slab: add sheaf support for batching kfree_rcu() operations Vlastimil Babka
2025-04-09 1:50 ` Harry Yoo
2025-04-09 15:09 ` Vlastimil Babka
2025-04-10 20:24 ` Suren Baghdasaryan
2025-04-22 15:18 ` Vlastimil Babka
2025-03-17 14:33 ` [PATCH RFC v3 4/8] slab: sheaf prefilling for guaranteed allocations Vlastimil Babka
2025-04-10 20:47 ` Suren Baghdasaryan
2025-04-23 13:06 ` Vlastimil Babka
2025-04-23 17:13 ` Suren Baghdasaryan
2025-03-17 14:33 ` Vlastimil Babka [this message]
2025-03-17 14:33 ` [PATCH RFC v3 6/8] tools: Add testing support for changes to rcu and slab for sheaves Vlastimil Babka
2025-03-17 14:33 ` [PATCH RFC v3 7/8] tools: Add sheafs support to testing infrastructure Vlastimil Babka
2025-03-17 14:33 ` [PATCH RFC v3 8/8] maple_tree: use percpu sheaves for maple_node_cache Vlastimil Babka
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250317-slub-percpu-caches-v3-5-9d9884d8b643@suse.cz \
--to=vbabka@suse.cz \
--cc=Liam.Howlett@oracle.com \
--cc=cl@linux.com \
--cc=harry.yoo@oracle.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=maple-tree@lists.infradead.org \
--cc=rcu@vger.kernel.org \
--cc=rientjes@google.com \
--cc=roman.gushchin@linux.dev \
--cc=surenb@google.com \
--cc=urezki@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox