diff options
-rw-r--r-- | include/linux/xarray.h | 113 | ||||
-rw-r--r-- | lib/xarray.c | 41 |
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 { | |||
289 | void xa_init_flags(struct xarray *, gfp_t flags); | 289 | void xa_init_flags(struct xarray *, gfp_t flags); |
290 | void *xa_load(struct xarray *, unsigned long index); | 290 | void *xa_load(struct xarray *, unsigned long index); |
291 | void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t); | 291 | void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t); |
292 | void *xa_cmpxchg(struct xarray *, unsigned long index, | ||
293 | void *old, void *entry, gfp_t); | ||
294 | void *xa_store_range(struct xarray *, unsigned long first, unsigned long last, | 292 | void *xa_store_range(struct xarray *, unsigned long first, unsigned long last, |
295 | void *entry, gfp_t); | 293 | void *entry, gfp_t); |
296 | bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t); | 294 | bool 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 | */ | ||
379 | static 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 | */ | ||
399 | static 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 | */ | ||
508 | static 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 | */ | ||
537 | static 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 | */ | ||
722 | static 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) | |||
1407 | EXPORT_SYMBOL(__xa_store); | 1407 | EXPORT_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 | */ | ||
1424 | void *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 | } | ||
1448 | EXPORT_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. |