diff options
Diffstat (limited to 'include/linux/xarray.h')
-rw-r--r-- | include/linux/xarray.h | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/include/linux/xarray.h b/include/linux/xarray.h index 5c8acfc4ff55..4d1cd7a083e8 100644 --- a/include/linux/xarray.h +++ b/include/linux/xarray.h | |||
@@ -22,6 +22,12 @@ | |||
22 | * x1: Value entry or tagged pointer | 22 | * x1: Value entry or tagged pointer |
23 | * | 23 | * |
24 | * Attempting to store internal entries in the XArray is a bug. | 24 | * Attempting to store internal entries in the XArray is a bug. |
25 | * | ||
26 | * Most internal entries are pointers to the next node in the tree. | ||
27 | * The following internal entries have a special meaning: | ||
28 | * | ||
29 | * 0-62: Sibling entries | ||
30 | * 256: Retry entry | ||
25 | */ | 31 | */ |
26 | 32 | ||
27 | #define BITS_PER_XA_VALUE (BITS_PER_LONG - 1) | 33 | #define BITS_PER_XA_VALUE (BITS_PER_LONG - 1) |
@@ -111,6 +117,42 @@ static inline unsigned int xa_pointer_tag(void *entry) | |||
111 | return (unsigned long)entry & 3UL; | 117 | return (unsigned long)entry & 3UL; |
112 | } | 118 | } |
113 | 119 | ||
120 | /* | ||
121 | * xa_mk_internal() - Create an internal entry. | ||
122 | * @v: Value to turn into an internal entry. | ||
123 | * | ||
124 | * Context: Any context. | ||
125 | * Return: An XArray internal entry corresponding to this value. | ||
126 | */ | ||
127 | static inline void *xa_mk_internal(unsigned long v) | ||
128 | { | ||
129 | return (void *)((v << 2) | 2); | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | * xa_to_internal() - Extract the value from an internal entry. | ||
134 | * @entry: XArray entry. | ||
135 | * | ||
136 | * Context: Any context. | ||
137 | * Return: The value which was stored in the internal entry. | ||
138 | */ | ||
139 | static inline unsigned long xa_to_internal(const void *entry) | ||
140 | { | ||
141 | return (unsigned long)entry >> 2; | ||
142 | } | ||
143 | |||
144 | /* | ||
145 | * xa_is_internal() - Is the entry an internal entry? | ||
146 | * @entry: XArray entry. | ||
147 | * | ||
148 | * Context: Any context. | ||
149 | * Return: %true if the entry is an internal entry. | ||
150 | */ | ||
151 | static inline bool xa_is_internal(const void *entry) | ||
152 | { | ||
153 | return ((unsigned long)entry & 3) == 2; | ||
154 | } | ||
155 | |||
114 | #define xa_trylock(xa) spin_trylock(&(xa)->xa_lock) | 156 | #define xa_trylock(xa) spin_trylock(&(xa)->xa_lock) |
115 | #define xa_lock(xa) spin_lock(&(xa)->xa_lock) | 157 | #define xa_lock(xa) spin_lock(&(xa)->xa_lock) |
116 | #define xa_unlock(xa) spin_unlock(&(xa)->xa_lock) | 158 | #define xa_unlock(xa) spin_unlock(&(xa)->xa_lock) |
@@ -123,4 +165,54 @@ static inline unsigned int xa_pointer_tag(void *entry) | |||
123 | #define xa_unlock_irqrestore(xa, flags) \ | 165 | #define xa_unlock_irqrestore(xa, flags) \ |
124 | spin_unlock_irqrestore(&(xa)->xa_lock, flags) | 166 | spin_unlock_irqrestore(&(xa)->xa_lock, flags) |
125 | 167 | ||
168 | /* Everything below here is the Advanced API. Proceed with caution. */ | ||
169 | |||
170 | /* | ||
171 | * The xarray is constructed out of a set of 'chunks' of pointers. Choosing | ||
172 | * the best chunk size requires some tradeoffs. A power of two recommends | ||
173 | * itself so that we can walk the tree based purely on shifts and masks. | ||
174 | * Generally, the larger the better; as the number of slots per level of the | ||
175 | * tree increases, the less tall the tree needs to be. But that needs to be | ||
176 | * balanced against the memory consumption of each node. On a 64-bit system, | ||
177 | * xa_node is currently 576 bytes, and we get 7 of them per 4kB page. If we | ||
178 | * doubled the number of slots per node, we'd get only 3 nodes per 4kB page. | ||
179 | */ | ||
180 | #ifndef XA_CHUNK_SHIFT | ||
181 | #define XA_CHUNK_SHIFT (CONFIG_BASE_SMALL ? 4 : 6) | ||
182 | #endif | ||
183 | #define XA_CHUNK_SIZE (1UL << XA_CHUNK_SHIFT) | ||
184 | #define XA_CHUNK_MASK (XA_CHUNK_SIZE - 1) | ||
185 | |||
186 | /* Private */ | ||
187 | static inline bool xa_is_node(const void *entry) | ||
188 | { | ||
189 | return xa_is_internal(entry) && (unsigned long)entry > 4096; | ||
190 | } | ||
191 | |||
192 | /* Private */ | ||
193 | static inline void *xa_mk_sibling(unsigned int offset) | ||
194 | { | ||
195 | return xa_mk_internal(offset); | ||
196 | } | ||
197 | |||
198 | /* Private */ | ||
199 | static inline unsigned long xa_to_sibling(const void *entry) | ||
200 | { | ||
201 | return xa_to_internal(entry); | ||
202 | } | ||
203 | |||
204 | /** | ||
205 | * xa_is_sibling() - Is the entry a sibling entry? | ||
206 | * @entry: Entry retrieved from the XArray | ||
207 | * | ||
208 | * Return: %true if the entry is a sibling entry. | ||
209 | */ | ||
210 | static inline bool xa_is_sibling(const void *entry) | ||
211 | { | ||
212 | return IS_ENABLED(CONFIG_XARRAY_MULTI) && xa_is_internal(entry) && | ||
213 | (entry < xa_mk_sibling(XA_CHUNK_SIZE - 1)); | ||
214 | } | ||
215 | |||
216 | #define XA_RETRY_ENTRY xa_mk_internal(256) | ||
217 | |||
126 | #endif /* _LINUX_XARRAY_H */ | 218 | #endif /* _LINUX_XARRAY_H */ |