diff options
Diffstat (limited to 'lib/xarray.c')
-rw-r--r-- | lib/xarray.c | 71 |
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) | |||
976 | EXPORT_SYMBOL(__xa_store); | 976 | EXPORT_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 | */ | ||
993 | void *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 | } | ||
1012 | EXPORT_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 | */ | ||
1030 | void *__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 | } | ||
1047 | EXPORT_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. |