summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/xarray.h113
-rw-r--r--lib/xarray.c41
2 files changed, 69 insertions, 85 deletions
diff --git a/include/linux/xarray.h b/include/linux/xarray.h
index c2cb0426c60c..8e59d4fbd55e 100644
--- a/include/linux/xarray.h
+++ b/include/linux/xarray.h
@@ -289,8 +289,6 @@ struct xarray {
289void xa_init_flags(struct xarray *, gfp_t flags); 289void xa_init_flags(struct xarray *, gfp_t flags);
290void *xa_load(struct xarray *, unsigned long index); 290void *xa_load(struct xarray *, unsigned long index);
291void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t); 291void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
292void *xa_cmpxchg(struct xarray *, unsigned long index,
293 void *old, void *entry, gfp_t);
294void *xa_store_range(struct xarray *, unsigned long first, unsigned long last, 292void *xa_store_range(struct xarray *, unsigned long first, unsigned long last,
295 void *entry, gfp_t); 293 void *entry, gfp_t);
296bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t); 294bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t);
@@ -360,48 +358,6 @@ static inline void *xa_erase(struct xarray *xa, unsigned long index)
360} 358}
361 359
362/** 360/**
363 * xa_insert() - Store this entry in the XArray unless another entry is
364 * already present.
365 * @xa: XArray.
366 * @index: Index into array.
367 * @entry: New entry.
368 * @gfp: Memory allocation flags.
369 *
370 * If you would rather see the existing entry in the array, use xa_cmpxchg().
371 * This function is for users who don't care what the entry is, only that
372 * one is present.
373 *
374 * Context: Process context. Takes and releases the xa_lock.
375 * May sleep if the @gfp flags permit.
376 * Return: 0 if the store succeeded. -EEXIST if another entry was present.
377 * -ENOMEM if memory could not be allocated.
378 */
379static inline int xa_insert(struct xarray *xa, unsigned long index,
380 void *entry, gfp_t gfp)
381{
382 void *curr = xa_cmpxchg(xa, index, NULL, entry, gfp);
383 if (!curr)
384 return 0;
385 if (xa_is_err(curr))
386 return xa_err(curr);
387 return -EEXIST;
388}
389
390/**
391 * xa_release() - Release a reserved entry.
392 * @xa: XArray.
393 * @index: Index of entry.
394 *
395 * After calling xa_reserve(), you can call this function to release the
396 * reservation. If the entry at @index has been stored to, this function
397 * will do nothing.
398 */
399static inline void xa_release(struct xarray *xa, unsigned long index)
400{
401 xa_cmpxchg(xa, index, NULL, NULL, 0);
402}
403
404/**
405 * xa_for_each() - Iterate over a portion of an XArray. 361 * xa_for_each() - Iterate over a portion of an XArray.
406 * @xa: XArray. 362 * @xa: XArray.
407 * @entry: Entry retrieved from array. 363 * @entry: Entry retrieved from array.
@@ -535,6 +491,61 @@ static inline void *xa_erase_irq(struct xarray *xa, unsigned long index)
535} 491}
536 492
537/** 493/**
494 * xa_cmpxchg() - Conditionally replace an entry in the XArray.
495 * @xa: XArray.
496 * @index: Index into array.
497 * @old: Old value to test against.
498 * @entry: New value to place in array.
499 * @gfp: Memory allocation flags.
500 *
501 * If the entry at @index is the same as @old, replace it with @entry.
502 * If the return value is equal to @old, then the exchange was successful.
503 *
504 * Context: Any context. Takes and releases the xa_lock. May sleep
505 * if the @gfp flags permit.
506 * Return: The old value at this index or xa_err() if an error happened.
507 */
508static inline void *xa_cmpxchg(struct xarray *xa, unsigned long index,
509 void *old, void *entry, gfp_t gfp)
510{
511 void *curr;
512
513 xa_lock(xa);
514 curr = __xa_cmpxchg(xa, index, old, entry, gfp);
515 xa_unlock(xa);
516
517 return curr;
518}
519
520/**
521 * xa_insert() - Store this entry in the XArray unless another entry is
522 * already present.
523 * @xa: XArray.
524 * @index: Index into array.
525 * @entry: New entry.
526 * @gfp: Memory allocation flags.
527 *
528 * If you would rather see the existing entry in the array, use xa_cmpxchg().
529 * This function is for users who don't care what the entry is, only that
530 * one is present.
531 *
532 * Context: Process context. Takes and releases the xa_lock.
533 * May sleep if the @gfp flags permit.
534 * Return: 0 if the store succeeded. -EEXIST if another entry was present.
535 * -ENOMEM if memory could not be allocated.
536 */
537static inline int xa_insert(struct xarray *xa, unsigned long index,
538 void *entry, gfp_t gfp)
539{
540 void *curr = xa_cmpxchg(xa, index, NULL, entry, gfp);
541 if (!curr)
542 return 0;
543 if (xa_is_err(curr))
544 return xa_err(curr);
545 return -EEXIST;
546}
547
548/**
538 * xa_alloc() - Find somewhere to store this entry in the XArray. 549 * xa_alloc() - Find somewhere to store this entry in the XArray.
539 * @xa: XArray. 550 * @xa: XArray.
540 * @id: Pointer to ID. 551 * @id: Pointer to ID.
@@ -699,6 +710,20 @@ int xa_reserve_irq(struct xarray *xa, unsigned long index, gfp_t gfp)
699 return ret; 710 return ret;
700} 711}
701 712
713/**
714 * xa_release() - Release a reserved entry.
715 * @xa: XArray.
716 * @index: Index of entry.
717 *
718 * After calling xa_reserve(), you can call this function to release the
719 * reservation. If the entry at @index has been stored to, this function
720 * will do nothing.
721 */
722static inline void xa_release(struct xarray *xa, unsigned long index)
723{
724 xa_cmpxchg(xa, index, NULL, NULL, 0);
725}
726
702/* Everything below here is the Advanced API. Proceed with caution. */ 727/* Everything below here is the Advanced API. Proceed with caution. */
703 728
704/* 729/*
diff --git a/lib/xarray.c b/lib/xarray.c
index 9cab8cfef8a8..77671d4a7910 100644
--- a/lib/xarray.c
+++ b/lib/xarray.c
@@ -1407,47 +1407,6 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
1407EXPORT_SYMBOL(__xa_store); 1407EXPORT_SYMBOL(__xa_store);
1408 1408
1409/** 1409/**
1410 * xa_cmpxchg() - Conditionally replace an entry in the XArray.
1411 * @xa: XArray.
1412 * @index: Index into array.
1413 * @old: Old value to test against.
1414 * @entry: New value to place in array.
1415 * @gfp: Memory allocation flags.
1416 *
1417 * If the entry at @index is the same as @old, replace it with @entry.
1418 * If the return value is equal to @old, then the exchange was successful.
1419 *
1420 * Context: Process context. Takes and releases the xa_lock. May sleep
1421 * if the @gfp flags permit.
1422 * Return: The old value at this index or xa_err() if an error happened.
1423 */
1424void *xa_cmpxchg(struct xarray *xa, unsigned long index,
1425 void *old, void *entry, gfp_t gfp)
1426{
1427 XA_STATE(xas, xa, index);
1428 void *curr;
1429
1430 if (WARN_ON_ONCE(xa_is_internal(entry)))
1431 return XA_ERROR(-EINVAL);
1432
1433 do {
1434 xas_lock(&xas);
1435 curr = xas_load(&xas);
1436 if (curr == XA_ZERO_ENTRY)
1437 curr = NULL;
1438 if (curr == old) {
1439 xas_store(&xas, entry);
1440 if (xa_track_free(xa) && entry)
1441 xas_clear_mark(&xas, XA_FREE_MARK);
1442 }
1443 xas_unlock(&xas);
1444 } while (xas_nomem(&xas, gfp));
1445
1446 return xas_result(&xas, curr);
1447}
1448EXPORT_SYMBOL(xa_cmpxchg);
1449
1450/**
1451 * __xa_cmpxchg() - Store this entry in the XArray. 1410 * __xa_cmpxchg() - Store this entry in the XArray.
1452 * @xa: XArray. 1411 * @xa: XArray.
1453 * @index: Index into array. 1412 * @index: Index into array.