mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-16 07:46:51 +07:00
3159f943aa
Introduce xarray value entries and tagged pointers to replace radix tree exceptional entries. This is a slight change in encoding to allow the use of an extra bit (we can now store BITS_PER_LONG - 1 bits in a value entry). It is also a change in emphasis; exceptional entries are intimidating and different. As the comment explains, you can choose to store values or pointers in the xarray and they are both first-class citizens. Signed-off-by: Matthew Wilcox <willy@infradead.org> Reviewed-by: Josef Bacik <jbacik@fb.com>
127 lines
3.3 KiB
C
127 lines
3.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0+ */
|
|
#ifndef _LINUX_XARRAY_H
|
|
#define _LINUX_XARRAY_H
|
|
/*
|
|
* eXtensible Arrays
|
|
* Copyright (c) 2017 Microsoft Corporation
|
|
* Author: Matthew Wilcox <willy@infradead.org>
|
|
*
|
|
* See Documentation/core-api/xarray.rst for how to use the XArray.
|
|
*/
|
|
|
|
#include <linux/bug.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/types.h>
|
|
|
|
/*
|
|
* The bottom two bits of the entry determine how the XArray interprets
|
|
* the contents:
|
|
*
|
|
* 00: Pointer entry
|
|
* 10: Internal entry
|
|
* x1: Value entry or tagged pointer
|
|
*
|
|
* Attempting to store internal entries in the XArray is a bug.
|
|
*/
|
|
|
|
#define BITS_PER_XA_VALUE (BITS_PER_LONG - 1)
|
|
|
|
/**
|
|
* xa_mk_value() - Create an XArray entry from an integer.
|
|
* @v: Value to store in XArray.
|
|
*
|
|
* Context: Any context.
|
|
* Return: An entry suitable for storing in the XArray.
|
|
*/
|
|
static inline void *xa_mk_value(unsigned long v)
|
|
{
|
|
WARN_ON((long)v < 0);
|
|
return (void *)((v << 1) | 1);
|
|
}
|
|
|
|
/**
|
|
* xa_to_value() - Get value stored in an XArray entry.
|
|
* @entry: XArray entry.
|
|
*
|
|
* Context: Any context.
|
|
* Return: The value stored in the XArray entry.
|
|
*/
|
|
static inline unsigned long xa_to_value(const void *entry)
|
|
{
|
|
return (unsigned long)entry >> 1;
|
|
}
|
|
|
|
/**
|
|
* xa_is_value() - Determine if an entry is a value.
|
|
* @entry: XArray entry.
|
|
*
|
|
* Context: Any context.
|
|
* Return: True if the entry is a value, false if it is a pointer.
|
|
*/
|
|
static inline bool xa_is_value(const void *entry)
|
|
{
|
|
return (unsigned long)entry & 1;
|
|
}
|
|
|
|
/**
|
|
* xa_tag_pointer() - Create an XArray entry for a tagged pointer.
|
|
* @p: Plain pointer.
|
|
* @tag: Tag value (0, 1 or 3).
|
|
*
|
|
* If the user of the XArray prefers, they can tag their pointers instead
|
|
* of storing value entries. Three tags are available (0, 1 and 3).
|
|
* These are distinct from the xa_mark_t as they are not replicated up
|
|
* through the array and cannot be searched for.
|
|
*
|
|
* Context: Any context.
|
|
* Return: An XArray entry.
|
|
*/
|
|
static inline void *xa_tag_pointer(void *p, unsigned long tag)
|
|
{
|
|
return (void *)((unsigned long)p | tag);
|
|
}
|
|
|
|
/**
|
|
* xa_untag_pointer() - Turn an XArray entry into a plain pointer.
|
|
* @entry: XArray entry.
|
|
*
|
|
* If you have stored a tagged pointer in the XArray, call this function
|
|
* to get the untagged version of the pointer.
|
|
*
|
|
* Context: Any context.
|
|
* Return: A pointer.
|
|
*/
|
|
static inline void *xa_untag_pointer(void *entry)
|
|
{
|
|
return (void *)((unsigned long)entry & ~3UL);
|
|
}
|
|
|
|
/**
|
|
* xa_pointer_tag() - Get the tag stored in an XArray entry.
|
|
* @entry: XArray entry.
|
|
*
|
|
* If you have stored a tagged pointer in the XArray, call this function
|
|
* to get the tag of that pointer.
|
|
*
|
|
* Context: Any context.
|
|
* Return: A tag.
|
|
*/
|
|
static inline unsigned int xa_pointer_tag(void *entry)
|
|
{
|
|
return (unsigned long)entry & 3UL;
|
|
}
|
|
|
|
#define xa_trylock(xa) spin_trylock(&(xa)->xa_lock)
|
|
#define xa_lock(xa) spin_lock(&(xa)->xa_lock)
|
|
#define xa_unlock(xa) spin_unlock(&(xa)->xa_lock)
|
|
#define xa_lock_bh(xa) spin_lock_bh(&(xa)->xa_lock)
|
|
#define xa_unlock_bh(xa) spin_unlock_bh(&(xa)->xa_lock)
|
|
#define xa_lock_irq(xa) spin_lock_irq(&(xa)->xa_lock)
|
|
#define xa_unlock_irq(xa) spin_unlock_irq(&(xa)->xa_lock)
|
|
#define xa_lock_irqsave(xa, flags) \
|
|
spin_lock_irqsave(&(xa)->xa_lock, flags)
|
|
#define xa_unlock_irqrestore(xa, flags) \
|
|
spin_unlock_irqrestore(&(xa)->xa_lock, flags)
|
|
|
|
#endif /* _LINUX_XARRAY_H */
|