XArray: Unify xa_cmpxchg and __xa_cmpxchg
xa_cmpxchg() was one of the largest functions in the xarray implementation. By turning it into a wrapper and having the callers take the lock (like several other functions), we save 160 bytes on a tinyconfig build and reduce the duplication in xarray.c. Signed-off-by: Matthew Wilcox <willy@infradead.org>hifive-unleashed-5.1
parent
4c0608f4a0
commit
c5beb07e7a
|
@ -289,8 +289,6 @@ struct xarray {
|
||||||
void xa_init_flags(struct xarray *, gfp_t flags);
|
void xa_init_flags(struct xarray *, gfp_t flags);
|
||||||
void *xa_load(struct xarray *, unsigned long index);
|
void *xa_load(struct xarray *, unsigned long index);
|
||||||
void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
|
void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
|
||||||
void *xa_cmpxchg(struct xarray *, unsigned long index,
|
|
||||||
void *old, void *entry, gfp_t);
|
|
||||||
void *xa_store_range(struct xarray *, unsigned long first, unsigned long last,
|
void *xa_store_range(struct xarray *, unsigned long first, unsigned long last,
|
||||||
void *entry, gfp_t);
|
void *entry, gfp_t);
|
||||||
bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t);
|
bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t);
|
||||||
|
@ -359,48 +357,6 @@ static inline void *xa_erase(struct xarray *xa, unsigned long index)
|
||||||
return xa_store(xa, index, NULL, 0);
|
return xa_store(xa, index, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* xa_insert() - Store this entry in the XArray unless another entry is
|
|
||||||
* already present.
|
|
||||||
* @xa: XArray.
|
|
||||||
* @index: Index into array.
|
|
||||||
* @entry: New entry.
|
|
||||||
* @gfp: Memory allocation flags.
|
|
||||||
*
|
|
||||||
* If you would rather see the existing entry in the array, use xa_cmpxchg().
|
|
||||||
* This function is for users who don't care what the entry is, only that
|
|
||||||
* one is present.
|
|
||||||
*
|
|
||||||
* Context: Process context. Takes and releases the xa_lock.
|
|
||||||
* May sleep if the @gfp flags permit.
|
|
||||||
* Return: 0 if the store succeeded. -EEXIST if another entry was present.
|
|
||||||
* -ENOMEM if memory could not be allocated.
|
|
||||||
*/
|
|
||||||
static inline int xa_insert(struct xarray *xa, unsigned long index,
|
|
||||||
void *entry, gfp_t gfp)
|
|
||||||
{
|
|
||||||
void *curr = xa_cmpxchg(xa, index, NULL, entry, gfp);
|
|
||||||
if (!curr)
|
|
||||||
return 0;
|
|
||||||
if (xa_is_err(curr))
|
|
||||||
return xa_err(curr);
|
|
||||||
return -EEXIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* xa_release() - Release a reserved entry.
|
|
||||||
* @xa: XArray.
|
|
||||||
* @index: Index of entry.
|
|
||||||
*
|
|
||||||
* After calling xa_reserve(), you can call this function to release the
|
|
||||||
* reservation. If the entry at @index has been stored to, this function
|
|
||||||
* will do nothing.
|
|
||||||
*/
|
|
||||||
static inline void xa_release(struct xarray *xa, unsigned long index)
|
|
||||||
{
|
|
||||||
xa_cmpxchg(xa, index, NULL, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xa_for_each() - Iterate over a portion of an XArray.
|
* xa_for_each() - Iterate over a portion of an XArray.
|
||||||
* @xa: XArray.
|
* @xa: XArray.
|
||||||
|
@ -534,6 +490,61 @@ static inline void *xa_erase_irq(struct xarray *xa, unsigned long index)
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xa_cmpxchg() - Conditionally replace an entry in the XArray.
|
||||||
|
* @xa: XArray.
|
||||||
|
* @index: Index into array.
|
||||||
|
* @old: Old value to test against.
|
||||||
|
* @entry: New value to place in array.
|
||||||
|
* @gfp: Memory allocation flags.
|
||||||
|
*
|
||||||
|
* If the entry at @index is the same as @old, replace it with @entry.
|
||||||
|
* If the return value is equal to @old, then the exchange was successful.
|
||||||
|
*
|
||||||
|
* Context: Any context. Takes and releases the xa_lock. May sleep
|
||||||
|
* if the @gfp flags permit.
|
||||||
|
* Return: The old value at this index or xa_err() if an error happened.
|
||||||
|
*/
|
||||||
|
static inline void *xa_cmpxchg(struct xarray *xa, unsigned long index,
|
||||||
|
void *old, void *entry, gfp_t gfp)
|
||||||
|
{
|
||||||
|
void *curr;
|
||||||
|
|
||||||
|
xa_lock(xa);
|
||||||
|
curr = __xa_cmpxchg(xa, index, old, entry, gfp);
|
||||||
|
xa_unlock(xa);
|
||||||
|
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xa_insert() - Store this entry in the XArray unless another entry is
|
||||||
|
* already present.
|
||||||
|
* @xa: XArray.
|
||||||
|
* @index: Index into array.
|
||||||
|
* @entry: New entry.
|
||||||
|
* @gfp: Memory allocation flags.
|
||||||
|
*
|
||||||
|
* If you would rather see the existing entry in the array, use xa_cmpxchg().
|
||||||
|
* This function is for users who don't care what the entry is, only that
|
||||||
|
* one is present.
|
||||||
|
*
|
||||||
|
* Context: Process context. Takes and releases the xa_lock.
|
||||||
|
* May sleep if the @gfp flags permit.
|
||||||
|
* Return: 0 if the store succeeded. -EEXIST if another entry was present.
|
||||||
|
* -ENOMEM if memory could not be allocated.
|
||||||
|
*/
|
||||||
|
static inline int xa_insert(struct xarray *xa, unsigned long index,
|
||||||
|
void *entry, gfp_t gfp)
|
||||||
|
{
|
||||||
|
void *curr = xa_cmpxchg(xa, index, NULL, entry, gfp);
|
||||||
|
if (!curr)
|
||||||
|
return 0;
|
||||||
|
if (xa_is_err(curr))
|
||||||
|
return xa_err(curr);
|
||||||
|
return -EEXIST;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xa_alloc() - Find somewhere to store this entry in the XArray.
|
* xa_alloc() - Find somewhere to store this entry in the XArray.
|
||||||
* @xa: XArray.
|
* @xa: XArray.
|
||||||
|
@ -699,6 +710,20 @@ int xa_reserve_irq(struct xarray *xa, unsigned long index, gfp_t gfp)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xa_release() - Release a reserved entry.
|
||||||
|
* @xa: XArray.
|
||||||
|
* @index: Index of entry.
|
||||||
|
*
|
||||||
|
* After calling xa_reserve(), you can call this function to release the
|
||||||
|
* reservation. If the entry at @index has been stored to, this function
|
||||||
|
* will do nothing.
|
||||||
|
*/
|
||||||
|
static inline void xa_release(struct xarray *xa, unsigned long index)
|
||||||
|
{
|
||||||
|
xa_cmpxchg(xa, index, NULL, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Everything below here is the Advanced API. Proceed with caution. */
|
/* Everything below here is the Advanced API. Proceed with caution. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
41
lib/xarray.c
41
lib/xarray.c
|
@ -1406,47 +1406,6 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__xa_store);
|
EXPORT_SYMBOL(__xa_store);
|
||||||
|
|
||||||
/**
|
|
||||||
* xa_cmpxchg() - Conditionally replace an entry in the XArray.
|
|
||||||
* @xa: XArray.
|
|
||||||
* @index: Index into array.
|
|
||||||
* @old: Old value to test against.
|
|
||||||
* @entry: New value to place in array.
|
|
||||||
* @gfp: Memory allocation flags.
|
|
||||||
*
|
|
||||||
* If the entry at @index is the same as @old, replace it with @entry.
|
|
||||||
* If the return value is equal to @old, then the exchange was successful.
|
|
||||||
*
|
|
||||||
* Context: Process context. Takes and releases the xa_lock. May sleep
|
|
||||||
* if the @gfp flags permit.
|
|
||||||
* Return: The old value at this index or xa_err() if an error happened.
|
|
||||||
*/
|
|
||||||
void *xa_cmpxchg(struct xarray *xa, unsigned long index,
|
|
||||||
void *old, void *entry, gfp_t gfp)
|
|
||||||
{
|
|
||||||
XA_STATE(xas, xa, index);
|
|
||||||
void *curr;
|
|
||||||
|
|
||||||
if (WARN_ON_ONCE(xa_is_internal(entry)))
|
|
||||||
return XA_ERROR(-EINVAL);
|
|
||||||
|
|
||||||
do {
|
|
||||||
xas_lock(&xas);
|
|
||||||
curr = xas_load(&xas);
|
|
||||||
if (curr == XA_ZERO_ENTRY)
|
|
||||||
curr = NULL;
|
|
||||||
if (curr == old) {
|
|
||||||
xas_store(&xas, entry);
|
|
||||||
if (xa_track_free(xa) && entry)
|
|
||||||
xas_clear_mark(&xas, XA_FREE_MARK);
|
|
||||||
}
|
|
||||||
xas_unlock(&xas);
|
|
||||||
} while (xas_nomem(&xas, gfp));
|
|
||||||
|
|
||||||
return xas_result(&xas, curr);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(xa_cmpxchg);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __xa_cmpxchg() - Store this entry in the XArray.
|
* __xa_cmpxchg() - Store this entry in the XArray.
|
||||||
* @xa: XArray.
|
* @xa: XArray.
|
||||||
|
|
Loading…
Reference in New Issue