aboutsummaryrefslogtreecommitdiffstats
path: root/lib/xarray.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/xarray.c')
-rw-r--r--lib/xarray.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/lib/xarray.c b/lib/xarray.c
index 4596a95ed9cd..2ba5a98ec618 100644
--- a/lib/xarray.c
+++ b/lib/xarray.c
@@ -976,6 +976,77 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
976EXPORT_SYMBOL(__xa_store); 976EXPORT_SYMBOL(__xa_store);
977 977
978/** 978/**
979 * xa_cmpxchg() - Conditionally replace an entry in the XArray.
980 * @xa: XArray.
981 * @index: Index into array.
982 * @old: Old value to test against.
983 * @entry: New value to place in array.
984 * @gfp: Memory allocation flags.
985 *
986 * If the entry at @index is the same as @old, replace it with @entry.
987 * If the return value is equal to @old, then the exchange was successful.
988 *
989 * Context: Process context. Takes and releases the xa_lock. May sleep
990 * if the @gfp flags permit.
991 * Return: The old value at this index or xa_err() if an error happened.
992 */
993void *xa_cmpxchg(struct xarray *xa, unsigned long index,
994 void *old, void *entry, gfp_t gfp)
995{
996 XA_STATE(xas, xa, index);
997 void *curr;
998
999 if (WARN_ON_ONCE(xa_is_internal(entry)))
1000 return XA_ERROR(-EINVAL);
1001
1002 do {
1003 xas_lock(&xas);
1004 curr = xas_load(&xas);
1005 if (curr == old)
1006 xas_store(&xas, entry);
1007 xas_unlock(&xas);
1008 } while (xas_nomem(&xas, gfp));
1009
1010 return xas_result(&xas, curr);
1011}
1012EXPORT_SYMBOL(xa_cmpxchg);
1013
1014/**
1015 * __xa_cmpxchg() - Store this entry in the XArray.
1016 * @xa: XArray.
1017 * @index: Index into array.
1018 * @old: Old value to test against.
1019 * @entry: New entry.
1020 * @gfp: Memory allocation flags.
1021 *
1022 * You must already be holding the xa_lock when calling this function.
1023 * It will drop the lock if needed to allocate memory, and then reacquire
1024 * it afterwards.
1025 *
1026 * Context: Any context. Expects xa_lock to be held on entry. May
1027 * release and reacquire xa_lock if @gfp flags permit.
1028 * Return: The old entry at this index or xa_err() if an error happened.
1029 */
1030void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
1031 void *old, void *entry, gfp_t gfp)
1032{
1033 XA_STATE(xas, xa, index);
1034 void *curr;
1035
1036 if (WARN_ON_ONCE(xa_is_internal(entry)))
1037 return XA_ERROR(-EINVAL);
1038
1039 do {
1040 curr = xas_load(&xas);
1041 if (curr == old)
1042 xas_store(&xas, entry);
1043 } while (__xas_nomem(&xas, gfp));
1044
1045 return xas_result(&xas, curr);
1046}
1047EXPORT_SYMBOL(__xa_cmpxchg);
1048
1049/**
979 * __xa_set_mark() - Set this mark on this entry while locked. 1050 * __xa_set_mark() - Set this mark on this entry while locked.
980 * @xa: XArray. 1051 * @xa: XArray.
981 * @index: Index of entry. 1052 * @index: Index of entry.