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