xarray.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /* SPDX-License-Identifier: GPL-2.0+ */
  2. #ifndef _LINUX_XARRAY_H
  3. #define _LINUX_XARRAY_H
  4. /*
  5. * eXtensible Arrays
  6. * Copyright (c) 2017 Microsoft Corporation
  7. * Author: Matthew Wilcox <willy@infradead.org>
  8. *
  9. * See Documentation/core-api/xarray.rst for how to use the XArray.
  10. */
  11. #include <linux/bug.h>
  12. #include <linux/spinlock.h>
  13. #include <linux/types.h>
  14. /*
  15. * The bottom two bits of the entry determine how the XArray interprets
  16. * the contents:
  17. *
  18. * 00: Pointer entry
  19. * 10: Internal entry
  20. * x1: Value entry or tagged pointer
  21. *
  22. * Attempting to store internal entries in the XArray is a bug.
  23. */
  24. #define BITS_PER_XA_VALUE (BITS_PER_LONG - 1)
  25. /**
  26. * xa_mk_value() - Create an XArray entry from an integer.
  27. * @v: Value to store in XArray.
  28. *
  29. * Context: Any context.
  30. * Return: An entry suitable for storing in the XArray.
  31. */
  32. static inline void *xa_mk_value(unsigned long v)
  33. {
  34. WARN_ON((long)v < 0);
  35. return (void *)((v << 1) | 1);
  36. }
  37. /**
  38. * xa_to_value() - Get value stored in an XArray entry.
  39. * @entry: XArray entry.
  40. *
  41. * Context: Any context.
  42. * Return: The value stored in the XArray entry.
  43. */
  44. static inline unsigned long xa_to_value(const void *entry)
  45. {
  46. return (unsigned long)entry >> 1;
  47. }
  48. /**
  49. * xa_is_value() - Determine if an entry is a value.
  50. * @entry: XArray entry.
  51. *
  52. * Context: Any context.
  53. * Return: True if the entry is a value, false if it is a pointer.
  54. */
  55. static inline bool xa_is_value(const void *entry)
  56. {
  57. return (unsigned long)entry & 1;
  58. }
  59. /**
  60. * xa_tag_pointer() - Create an XArray entry for a tagged pointer.
  61. * @p: Plain pointer.
  62. * @tag: Tag value (0, 1 or 3).
  63. *
  64. * If the user of the XArray prefers, they can tag their pointers instead
  65. * of storing value entries. Three tags are available (0, 1 and 3).
  66. * These are distinct from the xa_mark_t as they are not replicated up
  67. * through the array and cannot be searched for.
  68. *
  69. * Context: Any context.
  70. * Return: An XArray entry.
  71. */
  72. static inline void *xa_tag_pointer(void *p, unsigned long tag)
  73. {
  74. return (void *)((unsigned long)p | tag);
  75. }
  76. /**
  77. * xa_untag_pointer() - Turn an XArray entry into a plain pointer.
  78. * @entry: XArray entry.
  79. *
  80. * If you have stored a tagged pointer in the XArray, call this function
  81. * to get the untagged version of the pointer.
  82. *
  83. * Context: Any context.
  84. * Return: A pointer.
  85. */
  86. static inline void *xa_untag_pointer(void *entry)
  87. {
  88. return (void *)((unsigned long)entry & ~3UL);
  89. }
  90. /**
  91. * xa_pointer_tag() - Get the tag stored in an XArray entry.
  92. * @entry: XArray entry.
  93. *
  94. * If you have stored a tagged pointer in the XArray, call this function
  95. * to get the tag of that pointer.
  96. *
  97. * Context: Any context.
  98. * Return: A tag.
  99. */
  100. static inline unsigned int xa_pointer_tag(void *entry)
  101. {
  102. return (unsigned long)entry & 3UL;
  103. }
  104. #define xa_trylock(xa) spin_trylock(&(xa)->xa_lock)
  105. #define xa_lock(xa) spin_lock(&(xa)->xa_lock)
  106. #define xa_unlock(xa) spin_unlock(&(xa)->xa_lock)
  107. #define xa_lock_bh(xa) spin_lock_bh(&(xa)->xa_lock)
  108. #define xa_unlock_bh(xa) spin_unlock_bh(&(xa)->xa_lock)
  109. #define xa_lock_irq(xa) spin_lock_irq(&(xa)->xa_lock)
  110. #define xa_unlock_irq(xa) spin_unlock_irq(&(xa)->xa_lock)
  111. #define xa_lock_irqsave(xa, flags) \
  112. spin_lock_irqsave(&(xa)->xa_lock, flags)
  113. #define xa_unlock_irqrestore(xa, flags) \
  114. spin_unlock_irqrestore(&(xa)->xa_lock, flags)
  115. #endif /* _LINUX_XARRAY_H */