1f6bb2a2cSMatthew Wilcox /* SPDX-License-Identifier: GPL-2.0+ */ 2f6bb2a2cSMatthew Wilcox #ifndef _LINUX_XARRAY_H 3f6bb2a2cSMatthew Wilcox #define _LINUX_XARRAY_H 4f6bb2a2cSMatthew Wilcox /* 5f6bb2a2cSMatthew Wilcox * eXtensible Arrays 6f6bb2a2cSMatthew Wilcox * Copyright (c) 2017 Microsoft Corporation 73d0186bbSMatthew Wilcox * Author: Matthew Wilcox <[email protected]> 83159f943SMatthew Wilcox * 93159f943SMatthew Wilcox * See Documentation/core-api/xarray.rst for how to use the XArray. 10f6bb2a2cSMatthew Wilcox */ 11f6bb2a2cSMatthew Wilcox 123159f943SMatthew Wilcox #include <linux/bug.h> 13f6bb2a2cSMatthew Wilcox #include <linux/spinlock.h> 143159f943SMatthew Wilcox #include <linux/types.h> 153159f943SMatthew Wilcox 163159f943SMatthew Wilcox /* 173159f943SMatthew Wilcox * The bottom two bits of the entry determine how the XArray interprets 183159f943SMatthew Wilcox * the contents: 193159f943SMatthew Wilcox * 203159f943SMatthew Wilcox * 00: Pointer entry 213159f943SMatthew Wilcox * 10: Internal entry 223159f943SMatthew Wilcox * x1: Value entry or tagged pointer 233159f943SMatthew Wilcox * 243159f943SMatthew Wilcox * Attempting to store internal entries in the XArray is a bug. 25*02c02bf1SMatthew Wilcox * 26*02c02bf1SMatthew Wilcox * Most internal entries are pointers to the next node in the tree. 27*02c02bf1SMatthew Wilcox * The following internal entries have a special meaning: 28*02c02bf1SMatthew Wilcox * 29*02c02bf1SMatthew Wilcox * 0-62: Sibling entries 30*02c02bf1SMatthew Wilcox * 256: Retry entry 313159f943SMatthew Wilcox */ 323159f943SMatthew Wilcox 333159f943SMatthew Wilcox #define BITS_PER_XA_VALUE (BITS_PER_LONG - 1) 343159f943SMatthew Wilcox 353159f943SMatthew Wilcox /** 363159f943SMatthew Wilcox * xa_mk_value() - Create an XArray entry from an integer. 373159f943SMatthew Wilcox * @v: Value to store in XArray. 383159f943SMatthew Wilcox * 393159f943SMatthew Wilcox * Context: Any context. 403159f943SMatthew Wilcox * Return: An entry suitable for storing in the XArray. 413159f943SMatthew Wilcox */ 423159f943SMatthew Wilcox static inline void *xa_mk_value(unsigned long v) 433159f943SMatthew Wilcox { 443159f943SMatthew Wilcox WARN_ON((long)v < 0); 453159f943SMatthew Wilcox return (void *)((v << 1) | 1); 463159f943SMatthew Wilcox } 473159f943SMatthew Wilcox 483159f943SMatthew Wilcox /** 493159f943SMatthew Wilcox * xa_to_value() - Get value stored in an XArray entry. 503159f943SMatthew Wilcox * @entry: XArray entry. 513159f943SMatthew Wilcox * 523159f943SMatthew Wilcox * Context: Any context. 533159f943SMatthew Wilcox * Return: The value stored in the XArray entry. 543159f943SMatthew Wilcox */ 553159f943SMatthew Wilcox static inline unsigned long xa_to_value(const void *entry) 563159f943SMatthew Wilcox { 573159f943SMatthew Wilcox return (unsigned long)entry >> 1; 583159f943SMatthew Wilcox } 593159f943SMatthew Wilcox 603159f943SMatthew Wilcox /** 613159f943SMatthew Wilcox * xa_is_value() - Determine if an entry is a value. 623159f943SMatthew Wilcox * @entry: XArray entry. 633159f943SMatthew Wilcox * 643159f943SMatthew Wilcox * Context: Any context. 653159f943SMatthew Wilcox * Return: True if the entry is a value, false if it is a pointer. 663159f943SMatthew Wilcox */ 673159f943SMatthew Wilcox static inline bool xa_is_value(const void *entry) 683159f943SMatthew Wilcox { 693159f943SMatthew Wilcox return (unsigned long)entry & 1; 703159f943SMatthew Wilcox } 713159f943SMatthew Wilcox 723159f943SMatthew Wilcox /** 733159f943SMatthew Wilcox * xa_tag_pointer() - Create an XArray entry for a tagged pointer. 743159f943SMatthew Wilcox * @p: Plain pointer. 753159f943SMatthew Wilcox * @tag: Tag value (0, 1 or 3). 763159f943SMatthew Wilcox * 773159f943SMatthew Wilcox * If the user of the XArray prefers, they can tag their pointers instead 783159f943SMatthew Wilcox * of storing value entries. Three tags are available (0, 1 and 3). 793159f943SMatthew Wilcox * These are distinct from the xa_mark_t as they are not replicated up 803159f943SMatthew Wilcox * through the array and cannot be searched for. 813159f943SMatthew Wilcox * 823159f943SMatthew Wilcox * Context: Any context. 833159f943SMatthew Wilcox * Return: An XArray entry. 843159f943SMatthew Wilcox */ 853159f943SMatthew Wilcox static inline void *xa_tag_pointer(void *p, unsigned long tag) 863159f943SMatthew Wilcox { 873159f943SMatthew Wilcox return (void *)((unsigned long)p | tag); 883159f943SMatthew Wilcox } 893159f943SMatthew Wilcox 903159f943SMatthew Wilcox /** 913159f943SMatthew Wilcox * xa_untag_pointer() - Turn an XArray entry into a plain pointer. 923159f943SMatthew Wilcox * @entry: XArray entry. 933159f943SMatthew Wilcox * 943159f943SMatthew Wilcox * If you have stored a tagged pointer in the XArray, call this function 953159f943SMatthew Wilcox * to get the untagged version of the pointer. 963159f943SMatthew Wilcox * 973159f943SMatthew Wilcox * Context: Any context. 983159f943SMatthew Wilcox * Return: A pointer. 993159f943SMatthew Wilcox */ 1003159f943SMatthew Wilcox static inline void *xa_untag_pointer(void *entry) 1013159f943SMatthew Wilcox { 1023159f943SMatthew Wilcox return (void *)((unsigned long)entry & ~3UL); 1033159f943SMatthew Wilcox } 1043159f943SMatthew Wilcox 1053159f943SMatthew Wilcox /** 1063159f943SMatthew Wilcox * xa_pointer_tag() - Get the tag stored in an XArray entry. 1073159f943SMatthew Wilcox * @entry: XArray entry. 1083159f943SMatthew Wilcox * 1093159f943SMatthew Wilcox * If you have stored a tagged pointer in the XArray, call this function 1103159f943SMatthew Wilcox * to get the tag of that pointer. 1113159f943SMatthew Wilcox * 1123159f943SMatthew Wilcox * Context: Any context. 1133159f943SMatthew Wilcox * Return: A tag. 1143159f943SMatthew Wilcox */ 1153159f943SMatthew Wilcox static inline unsigned int xa_pointer_tag(void *entry) 1163159f943SMatthew Wilcox { 1173159f943SMatthew Wilcox return (unsigned long)entry & 3UL; 1183159f943SMatthew Wilcox } 119f6bb2a2cSMatthew Wilcox 120*02c02bf1SMatthew Wilcox /* 121*02c02bf1SMatthew Wilcox * xa_mk_internal() - Create an internal entry. 122*02c02bf1SMatthew Wilcox * @v: Value to turn into an internal entry. 123*02c02bf1SMatthew Wilcox * 124*02c02bf1SMatthew Wilcox * Context: Any context. 125*02c02bf1SMatthew Wilcox * Return: An XArray internal entry corresponding to this value. 126*02c02bf1SMatthew Wilcox */ 127*02c02bf1SMatthew Wilcox static inline void *xa_mk_internal(unsigned long v) 128*02c02bf1SMatthew Wilcox { 129*02c02bf1SMatthew Wilcox return (void *)((v << 2) | 2); 130*02c02bf1SMatthew Wilcox } 131*02c02bf1SMatthew Wilcox 132*02c02bf1SMatthew Wilcox /* 133*02c02bf1SMatthew Wilcox * xa_to_internal() - Extract the value from an internal entry. 134*02c02bf1SMatthew Wilcox * @entry: XArray entry. 135*02c02bf1SMatthew Wilcox * 136*02c02bf1SMatthew Wilcox * Context: Any context. 137*02c02bf1SMatthew Wilcox * Return: The value which was stored in the internal entry. 138*02c02bf1SMatthew Wilcox */ 139*02c02bf1SMatthew Wilcox static inline unsigned long xa_to_internal(const void *entry) 140*02c02bf1SMatthew Wilcox { 141*02c02bf1SMatthew Wilcox return (unsigned long)entry >> 2; 142*02c02bf1SMatthew Wilcox } 143*02c02bf1SMatthew Wilcox 144*02c02bf1SMatthew Wilcox /* 145*02c02bf1SMatthew Wilcox * xa_is_internal() - Is the entry an internal entry? 146*02c02bf1SMatthew Wilcox * @entry: XArray entry. 147*02c02bf1SMatthew Wilcox * 148*02c02bf1SMatthew Wilcox * Context: Any context. 149*02c02bf1SMatthew Wilcox * Return: %true if the entry is an internal entry. 150*02c02bf1SMatthew Wilcox */ 151*02c02bf1SMatthew Wilcox static inline bool xa_is_internal(const void *entry) 152*02c02bf1SMatthew Wilcox { 153*02c02bf1SMatthew Wilcox return ((unsigned long)entry & 3) == 2; 154*02c02bf1SMatthew Wilcox } 155*02c02bf1SMatthew Wilcox 156f6bb2a2cSMatthew Wilcox #define xa_trylock(xa) spin_trylock(&(xa)->xa_lock) 157f6bb2a2cSMatthew Wilcox #define xa_lock(xa) spin_lock(&(xa)->xa_lock) 158f6bb2a2cSMatthew Wilcox #define xa_unlock(xa) spin_unlock(&(xa)->xa_lock) 159f6bb2a2cSMatthew Wilcox #define xa_lock_bh(xa) spin_lock_bh(&(xa)->xa_lock) 160f6bb2a2cSMatthew Wilcox #define xa_unlock_bh(xa) spin_unlock_bh(&(xa)->xa_lock) 161f6bb2a2cSMatthew Wilcox #define xa_lock_irq(xa) spin_lock_irq(&(xa)->xa_lock) 162f6bb2a2cSMatthew Wilcox #define xa_unlock_irq(xa) spin_unlock_irq(&(xa)->xa_lock) 163f6bb2a2cSMatthew Wilcox #define xa_lock_irqsave(xa, flags) \ 164f6bb2a2cSMatthew Wilcox spin_lock_irqsave(&(xa)->xa_lock, flags) 165f6bb2a2cSMatthew Wilcox #define xa_unlock_irqrestore(xa, flags) \ 166f6bb2a2cSMatthew Wilcox spin_unlock_irqrestore(&(xa)->xa_lock, flags) 167f6bb2a2cSMatthew Wilcox 168*02c02bf1SMatthew Wilcox /* Everything below here is the Advanced API. Proceed with caution. */ 169*02c02bf1SMatthew Wilcox 170*02c02bf1SMatthew Wilcox /* 171*02c02bf1SMatthew Wilcox * The xarray is constructed out of a set of 'chunks' of pointers. Choosing 172*02c02bf1SMatthew Wilcox * the best chunk size requires some tradeoffs. A power of two recommends 173*02c02bf1SMatthew Wilcox * itself so that we can walk the tree based purely on shifts and masks. 174*02c02bf1SMatthew Wilcox * Generally, the larger the better; as the number of slots per level of the 175*02c02bf1SMatthew Wilcox * tree increases, the less tall the tree needs to be. But that needs to be 176*02c02bf1SMatthew Wilcox * balanced against the memory consumption of each node. On a 64-bit system, 177*02c02bf1SMatthew Wilcox * xa_node is currently 576 bytes, and we get 7 of them per 4kB page. If we 178*02c02bf1SMatthew Wilcox * doubled the number of slots per node, we'd get only 3 nodes per 4kB page. 179*02c02bf1SMatthew Wilcox */ 180*02c02bf1SMatthew Wilcox #ifndef XA_CHUNK_SHIFT 181*02c02bf1SMatthew Wilcox #define XA_CHUNK_SHIFT (CONFIG_BASE_SMALL ? 4 : 6) 182*02c02bf1SMatthew Wilcox #endif 183*02c02bf1SMatthew Wilcox #define XA_CHUNK_SIZE (1UL << XA_CHUNK_SHIFT) 184*02c02bf1SMatthew Wilcox #define XA_CHUNK_MASK (XA_CHUNK_SIZE - 1) 185*02c02bf1SMatthew Wilcox 186*02c02bf1SMatthew Wilcox /* Private */ 187*02c02bf1SMatthew Wilcox static inline bool xa_is_node(const void *entry) 188*02c02bf1SMatthew Wilcox { 189*02c02bf1SMatthew Wilcox return xa_is_internal(entry) && (unsigned long)entry > 4096; 190*02c02bf1SMatthew Wilcox } 191*02c02bf1SMatthew Wilcox 192*02c02bf1SMatthew Wilcox /* Private */ 193*02c02bf1SMatthew Wilcox static inline void *xa_mk_sibling(unsigned int offset) 194*02c02bf1SMatthew Wilcox { 195*02c02bf1SMatthew Wilcox return xa_mk_internal(offset); 196*02c02bf1SMatthew Wilcox } 197*02c02bf1SMatthew Wilcox 198*02c02bf1SMatthew Wilcox /* Private */ 199*02c02bf1SMatthew Wilcox static inline unsigned long xa_to_sibling(const void *entry) 200*02c02bf1SMatthew Wilcox { 201*02c02bf1SMatthew Wilcox return xa_to_internal(entry); 202*02c02bf1SMatthew Wilcox } 203*02c02bf1SMatthew Wilcox 204*02c02bf1SMatthew Wilcox /** 205*02c02bf1SMatthew Wilcox * xa_is_sibling() - Is the entry a sibling entry? 206*02c02bf1SMatthew Wilcox * @entry: Entry retrieved from the XArray 207*02c02bf1SMatthew Wilcox * 208*02c02bf1SMatthew Wilcox * Return: %true if the entry is a sibling entry. 209*02c02bf1SMatthew Wilcox */ 210*02c02bf1SMatthew Wilcox static inline bool xa_is_sibling(const void *entry) 211*02c02bf1SMatthew Wilcox { 212*02c02bf1SMatthew Wilcox return IS_ENABLED(CONFIG_XARRAY_MULTI) && xa_is_internal(entry) && 213*02c02bf1SMatthew Wilcox (entry < xa_mk_sibling(XA_CHUNK_SIZE - 1)); 214*02c02bf1SMatthew Wilcox } 215*02c02bf1SMatthew Wilcox 216*02c02bf1SMatthew Wilcox #define XA_RETRY_ENTRY xa_mk_internal(256) 217*02c02bf1SMatthew Wilcox 218f6bb2a2cSMatthew Wilcox #endif /* _LINUX_XARRAY_H */ 219