History

xarray: Add XArray conditional store operations

Like cmpxchg(), xa_cmpxchg will only store to the index if the current entry matches the old entry. It returns the current entry, which is usually more useful than the errno returned by radix_tree_insert(). For the users who really only want the errno, the xa_insert() wrapper provides a more convenient calling convention.

Matthew Wilcox committed 9 years ago

Commit 41aec911 parent 58d6ea33 files · +151 −0Browse files

Showing the changes to lib/xarray.c (1 of 3 files). Show all

Unified · Split

lib/xarray.c+71−0
@@ -975,6 +975,77 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) · 974 unmodified lines
975975 }
976976 EXPORT_SYMBOL(__xa_store);
977977
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+
9781049 /**
9791050 * __xa_set_mark() - Set this mark on this entry while locked.
9801051 * @xa: XArray.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t