Skip to content

Commit 3993ca9

Browse files
committed
slab: turn freelist_aba_t to a struct and fully define counters there
In struct slab we currently have freelist and counters pair, where counters itself is a union of unsigned long with a sub-struct of several smaller fields. Then for the usage with double cmpxchg we have freelist_aba_t that duplicates the definition of the freelist+counters with implicitly the same layout as the full definition in struct slab. Thanks to -fms-extension we can now move the full counters definition to freelist_aba_t (while changing it to struct freelist_counters as a typedef is unnecessary and discouraged) and replace the relevant part in struct slab to an unnamed reference to it. The immediate benefit is the removal of duplication and no longer relying on the same layout implicitly. It also allows further cleanups thanks to having the full definition of counters in struct freelist_counters. Reviewed-by: Harry Yoo <harry.yoo@oracle.com> Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
1 parent b244358 commit 3993ca9

2 files changed

Lines changed: 29 additions & 31 deletions

File tree

mm/slab.h

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,29 @@ typedef u64 freelist_full_t;
4040
* Freelist pointer and counter to cmpxchg together, avoids the typical ABA
4141
* problems with cmpxchg of just a pointer.
4242
*/
43-
typedef union {
44-
struct {
45-
void *freelist;
46-
unsigned long counter;
43+
struct freelist_counters {
44+
union {
45+
struct {
46+
void *freelist;
47+
union {
48+
unsigned long counters;
49+
struct {
50+
unsigned inuse:16;
51+
unsigned objects:15;
52+
/*
53+
* If slab debugging is enabled then the
54+
* frozen bit can be reused to indicate
55+
* that the slab was corrupted
56+
*/
57+
unsigned frozen:1;
58+
};
59+
};
60+
};
61+
#ifdef system_has_freelist_aba
62+
freelist_full_t freelist_counters;
63+
#endif
4764
};
48-
freelist_full_t full;
49-
} freelist_aba_t;
65+
};
5066

5167
/* Reuses the bits in struct page */
5268
struct slab {
@@ -69,27 +85,7 @@ struct slab {
6985
#endif
7086
};
7187
/* Double-word boundary */
72-
union {
73-
struct {
74-
void *freelist; /* first free object */
75-
union {
76-
unsigned long counters;
77-
struct {
78-
unsigned inuse:16;
79-
unsigned objects:15;
80-
/*
81-
* If slab debugging is enabled then the
82-
* frozen bit can be reused to indicate
83-
* that the slab was corrupted
84-
*/
85-
unsigned frozen:1;
86-
};
87-
};
88-
};
89-
#ifdef system_has_freelist_aba
90-
freelist_aba_t freelist_counter;
91-
#endif
92-
};
88+
struct freelist_counters;
9389
};
9490
struct rcu_head rcu_head;
9591
};
@@ -114,7 +110,7 @@ SLAB_MATCH(_unused_slab_obj_exts, obj_exts);
114110
#undef SLAB_MATCH
115111
static_assert(sizeof(struct slab) <= sizeof(struct page));
116112
#if defined(system_has_freelist_aba)
117-
static_assert(IS_ALIGNED(offsetof(struct slab, freelist), sizeof(freelist_aba_t)));
113+
static_assert(IS_ALIGNED(offsetof(struct slab, freelist), sizeof(struct freelist_counters)));
118114
#endif
119115

120116
/**

mm/slub.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -764,10 +764,12 @@ __update_freelist_fast(struct slab *slab,
764764
void *freelist_new, unsigned long counters_new)
765765
{
766766
#ifdef system_has_freelist_aba
767-
freelist_aba_t old = { .freelist = freelist_old, .counter = counters_old };
768-
freelist_aba_t new = { .freelist = freelist_new, .counter = counters_new };
767+
struct freelist_counters old = { .freelist = freelist_old, .counters = counters_old };
768+
struct freelist_counters new = { .freelist = freelist_new, .counters = counters_new };
769769

770-
return try_cmpxchg_freelist(&slab->freelist_counter.full, &old.full, new.full);
770+
return try_cmpxchg_freelist(&slab->freelist_counters,
771+
&old.freelist_counters,
772+
new.freelist_counters);
771773
#else
772774
return false;
773775
#endif

0 commit comments

Comments
 (0)