[PATCH] Modified XArray entry bit flags as macro constants

From: Jung-JaeJoon
Date: Thu May 23 2024 - 22:50:24 EST


From: Jung-JaeJoon <rgbi3307@xxxxxxxxx>

It would be better to modify the operation on the last two bits of the entry
with a macro constant name rather than using a numeric constant.

#define XA_VALUE_ENTRY 1UL
#define XA_INTERNAL_ENTRY 2UL
#define XA_POINTER_ENTRY 3UL

In particular, in the xa_to_node() function, it is more consistent and efficient
to perform a logical AND operation as shown below than a subtraction operation.

- return (struct xa_node *)((unsigned long)entry - 2);
+ return (struct xa_node *)((unsigned long)entry & ~XA_INTERNAL_ENTRY);

Additionally, it is better to modify the if condition below
in the mas_store_root() function of lib/maple_tree.c to the xa_is_internal() inline function.

- else if (((unsigned long) (entry) & 3) == 2)
+ else if (xa_is_internal(entry))

And there is no reason to declare XA_CHECK_SCHED as an enum data type.
-enum {
- XA_CHECK_SCHED = 4096,
-};
+#define XA_CHECK_SCHED 4096

Signed-off-by: JaeJoon Jung <rgbi3307@xxxxxxxxx>

---
include/linux/xarray.h | 55 ++++++++++++++++++++++--------------------
lib/maple_tree.c | 2 +-
2 files changed, 30 insertions(+), 27 deletions(-)

diff --git a/include/linux/xarray.h b/include/linux/xarray.h
index cb571dfcf4b1..d73dfe35a005 100644
--- a/include/linux/xarray.h
+++ b/include/linux/xarray.h
@@ -42,6 +42,16 @@
* returned by the normal API.
*/

+#define XA_VALUE_ENTRY 1UL
+#define XA_INTERNAL_ENTRY 2UL
+#define XA_POINTER_ENTRY 3UL
+
+/*
+ * If iterating while holding a lock, drop the lock and reschedule
+ * every %XA_CHECK_SCHED loops.
+ */
+#define XA_CHECK_SCHED 4096
+
#define BITS_PER_XA_VALUE (BITS_PER_LONG - 1)

/**
@@ -54,7 +64,7 @@
static inline void *xa_mk_value(unsigned long v)
{
WARN_ON((long)v < 0);
- return (void *)((v << 1) | 1);
+ return (void *)((v << XA_VALUE_ENTRY) | XA_VALUE_ENTRY);
}

/**
@@ -66,7 +76,7 @@ static inline void *xa_mk_value(unsigned long v)
*/
static inline unsigned long xa_to_value(const void *entry)
{
- return (unsigned long)entry >> 1;
+ return (unsigned long)entry >> XA_VALUE_ENTRY;
}

/**
@@ -78,7 +88,7 @@ static inline unsigned long xa_to_value(const void *entry)
*/
static inline bool xa_is_value(const void *entry)
{
- return (unsigned long)entry & 1;
+ return (unsigned long)entry & XA_VALUE_ENTRY;
}

/**
@@ -111,7 +121,7 @@ static inline void *xa_tag_pointer(void *p, unsigned long tag)
*/
static inline void *xa_untag_pointer(void *entry)
{
- return (void *)((unsigned long)entry & ~3UL);
+ return (void *)((unsigned long)entry & ~XA_POINTER_ENTRY);
}

/**
@@ -126,7 +136,7 @@ static inline void *xa_untag_pointer(void *entry)
*/
static inline unsigned int xa_pointer_tag(void *entry)
{
- return (unsigned long)entry & 3UL;
+ return (unsigned long)entry & XA_POINTER_ENTRY;
}

/*
@@ -144,7 +154,7 @@ static inline unsigned int xa_pointer_tag(void *entry)
*/
static inline void *xa_mk_internal(unsigned long v)
{
- return (void *)((v << 2) | 2);
+ return (void *)((v << XA_INTERNAL_ENTRY) | XA_INTERNAL_ENTRY);
}

/*
@@ -156,7 +166,7 @@ static inline void *xa_mk_internal(unsigned long v)
*/
static inline unsigned long xa_to_internal(const void *entry)
{
- return (unsigned long)entry >> 2;
+ return (unsigned long)entry >> XA_INTERNAL_ENTRY;
}

/*
@@ -168,7 +178,7 @@ static inline unsigned long xa_to_internal(const void *entry)
*/
static inline bool xa_is_internal(const void *entry)
{
- return ((unsigned long)entry & 3) == 2;
+ return ((unsigned long)entry & XA_POINTER_ENTRY) == XA_INTERNAL_ENTRY;
}

#define XA_ZERO_ENTRY xa_mk_internal(257)
@@ -220,7 +230,7 @@ static inline int xa_err(void *entry)
{
/* xa_to_internal() would not do sign extension. */
if (xa_is_err(entry))
- return (long)entry >> 2;
+ return (long)entry >> XA_INTERNAL_ENTRY;
return 0;
}

@@ -1245,19 +1255,19 @@ static inline struct xa_node *xa_parent_locked(const struct xarray *xa,
/* Private */
static inline void *xa_mk_node(const struct xa_node *node)
{
- return (void *)((unsigned long)node | 2);
+ return (void *)((unsigned long)node | XA_INTERNAL_ENTRY);
}

/* Private */
static inline struct xa_node *xa_to_node(const void *entry)
{
- return (struct xa_node *)((unsigned long)entry - 2);
+ return (struct xa_node *)((unsigned long)entry & ~XA_INTERNAL_ENTRY);
}

/* Private */
static inline bool xa_is_node(const void *entry)
{
- return xa_is_internal(entry) && (unsigned long)entry > 4096;
+ return xa_is_internal(entry) && (unsigned long)entry > XA_CHECK_SCHED;
}

/* Private */
@@ -1358,9 +1368,10 @@ struct xa_state {
* We encode errnos in the xas->xa_node. If an error has happened, we need to
* drop the lock to fix it, and once we've done so the xa_state is invalid.
*/
-#define XA_ERROR(errno) ((struct xa_node *)(((unsigned long)errno << 2) | 2UL))
-#define XAS_BOUNDS ((struct xa_node *)1UL)
-#define XAS_RESTART ((struct xa_node *)3UL)
+#define XA_ERROR(errno) ((struct xa_node *) \
+ (((unsigned long)errno << XA_INTERNAL_ENTRY) | XA_INTERNAL_ENTRY))
+#define XAS_BOUNDS ((struct xa_node *)XA_VALUE_ENTRY)
+#define XAS_RESTART ((struct xa_node *)XA_POINTER_ENTRY)

#define __XA_STATE(array, index, shift, sibs) { \
.xa = array, \
@@ -1449,7 +1460,7 @@ static inline void xas_set_err(struct xa_state *xas, long err)
*/
static inline bool xas_invalid(const struct xa_state *xas)
{
- return (unsigned long)xas->xa_node & 3;
+ return (unsigned long)xas->xa_node & XA_POINTER_ENTRY;
}

/**
@@ -1477,13 +1488,13 @@ static inline bool xas_is_node(const struct xa_state *xas)
/* True if the pointer is something other than a node */
static inline bool xas_not_node(struct xa_node *node)
{
- return ((unsigned long)node & 3) || !node;
+ return ((unsigned long)node & XA_POINTER_ENTRY) || !node;
}

/* True if the node represents RESTART or an error */
static inline bool xas_frozen(struct xa_node *node)
{
- return (unsigned long)node & 2;
+ return (unsigned long)node & XA_INTERNAL_ENTRY;
}

/* True if the node represents head-of-tree, RESTART or BOUNDS */
@@ -1764,14 +1775,6 @@ static inline void *xas_next_marked(struct xa_state *xas, unsigned long max,
return entry;
}

-/*
- * If iterating while holding a lock, drop the lock and reschedule
- * every %XA_CHECK_SCHED loops.
- */
-enum {
- XA_CHECK_SCHED = 4096,
-};
-
/**
* xas_for_each() - Iterate over a range of an XArray.
* @xas: XArray operation state.
diff --git a/lib/maple_tree.c b/lib/maple_tree.c
index 2d7d27e6ae3c..c08545f8b09b 100644
--- a/lib/maple_tree.c
+++ b/lib/maple_tree.c
@@ -3515,7 +3515,7 @@ static inline void mas_store_root(struct ma_state *mas, void *entry)
{
if (likely((mas->last != 0) || (mas->index != 0)))
mas_root_expand(mas, entry);
- else if (((unsigned long) (entry) & 3) == 2)
+ else if (xa_is_internal(entry))
mas_root_expand(mas, entry);
else {
rcu_assign_pointer(mas->tree->ma_root, entry);
--
2.17.1