Skip to content

Commit 0829422

Browse files
committed
slab: determine barn status racily outside of lock
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. Reviewed-by: Suren Baghdasaryan <surenb@google.com> Reviewed-by: Harry Yoo <harry.yoo@oracle.com> Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
1 parent 3c1ea5c commit 0829422

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

mm/slub.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2801,9 +2801,12 @@ static struct slab_sheaf *barn_get_empty_sheaf(struct node_barn *barn)
28012801
struct slab_sheaf *empty = NULL;
28022802
unsigned long flags;
28032803

2804+
if (!data_race(barn->nr_empty))
2805+
return NULL;
2806+
28042807
spin_lock_irqsave(&barn->lock, flags);
28052808

2806-
if (barn->nr_empty) {
2809+
if (likely(barn->nr_empty)) {
28072810
empty = list_first_entry(&barn->sheaves_empty,
28082811
struct slab_sheaf, barn_list);
28092812
list_del(&empty->barn_list);
@@ -2850,6 +2853,9 @@ static struct slab_sheaf *barn_get_full_or_empty_sheaf(struct node_barn *barn)
28502853
struct slab_sheaf *sheaf = NULL;
28512854
unsigned long flags;
28522855

2856+
if (!data_race(barn->nr_full) && !data_race(barn->nr_empty))
2857+
return NULL;
2858+
28532859
spin_lock_irqsave(&barn->lock, flags);
28542860

28552861
if (barn->nr_full) {
@@ -2880,9 +2886,12 @@ barn_replace_empty_sheaf(struct node_barn *barn, struct slab_sheaf *empty)
28802886
struct slab_sheaf *full = NULL;
28812887
unsigned long flags;
28822888

2889+
if (!data_race(barn->nr_full))
2890+
return NULL;
2891+
28832892
spin_lock_irqsave(&barn->lock, flags);
28842893

2885-
if (barn->nr_full) {
2894+
if (likely(barn->nr_full)) {
28862895
full = list_first_entry(&barn->sheaves_full, struct slab_sheaf,
28872896
barn_list);
28882897
list_del(&full->barn_list);
@@ -2906,19 +2915,23 @@ barn_replace_full_sheaf(struct node_barn *barn, struct slab_sheaf *full)
29062915
struct slab_sheaf *empty;
29072916
unsigned long flags;
29082917

2918+
/* we don't repeat this check under barn->lock as it's not critical */
2919+
if (data_race(barn->nr_full) >= MAX_FULL_SHEAVES)
2920+
return ERR_PTR(-E2BIG);
2921+
if (!data_race(barn->nr_empty))
2922+
return ERR_PTR(-ENOMEM);
2923+
29092924
spin_lock_irqsave(&barn->lock, flags);
29102925

2911-
if (barn->nr_full >= MAX_FULL_SHEAVES) {
2912-
empty = ERR_PTR(-E2BIG);
2913-
} else if (!barn->nr_empty) {
2914-
empty = ERR_PTR(-ENOMEM);
2915-
} else {
2926+
if (likely(barn->nr_empty)) {
29162927
empty = list_first_entry(&barn->sheaves_empty, struct slab_sheaf,
29172928
barn_list);
29182929
list_del(&empty->barn_list);
29192930
list_add(&full->barn_list, &barn->sheaves_full);
29202931
barn->nr_empty--;
29212932
barn->nr_full++;
2933+
} else {
2934+
empty = ERR_PTR(-ENOMEM);
29222935
}
29232936

29242937
spin_unlock_irqrestore(&barn->lock, flags);

0 commit comments

Comments
 (0)