xref: /linux/Documentation/core-api/min_heap.rst (revision 9ad8d22f2f3fad7a366c9772362795ef6d6a2d51)
1.. SPDX-License-Identifier: GPL-2.0
2
3============
4Min Heap API
5============
6
7Introduction
8============
9
10The Min Heap API provides a set of functions and macros for managing min-heaps
11in the Linux kernel. A min-heap is a binary tree structure where the value of
12each node is less than or equal to the values of its children, ensuring that
13the smallest element is always at the root.
14
15This document provides a guide to the Min Heap API, detailing how to define and
16use min-heaps. Users should not directly call functions with **__min_heap_*()**
17prefixes, but should instead use the provided macro wrappers.
18
19In addition to the standard version of the functions, the API also includes a
20set of inline versions for performance-critical scenarios. These inline
21functions have the same names as their non-inline counterparts but include an
22**_inline** suffix. For example, **__min_heap_init_inline** and its
23corresponding macro wrapper **min_heap_init_inline**. The inline versions allow
24custom comparison and swap functions to be called directly, rather than through
25indirect function calls. This can significantly reduce overhead, especially
26when CONFIG_MITIGATION_RETPOLINE is enabled, as indirect function calls become
27more expensive. As with the non-inline versions, it is important to use the
28macro wrappers for inline functions instead of directly calling the functions
29themselves.
30
31Data Structures
32===============
33
34Min-Heap Definition
35-------------------
36
37The core data structure for representing a min-heap is defined using the
38**MIN_HEAP_PREALLOCATED** and **DEFINE_MIN_HEAP** macros. These macros allow
39you to define a min-heap with a preallocated buffer or dynamically allocated
40memory.
41
42Example:
43
44.. code-block:: c
45
46    #define MIN_HEAP_PREALLOCATED(_type, _name, _nr)
47    struct _name {
48        int nr;         /* Number of elements in the heap */
49        int size;       /* Maximum number of elements that can be held */
50        _type *data;    /* Pointer to the heap data */
51        _type preallocated[_nr];  /* Static preallocated array */
52    }
53
54    #define DEFINE_MIN_HEAP(_type, _name) MIN_HEAP_PREALLOCATED(_type, _name, 0)
55
56A typical heap structure will include a counter for the number of elements
57(`nr`), the maximum capacity of the heap (`size`), and a pointer to an array of
58elements (`data`). Optionally, you can specify a static array for preallocated
59heap storage using **MIN_HEAP_PREALLOCATED**.
60
61Min Heap Callbacks
62------------------
63
64The **struct min_heap_callbacks** provides customization options for ordering
65elements in the heap and swapping them. It contains two function pointers:
66
67.. code-block:: c
68
69    struct min_heap_callbacks {
70        bool (*less)(const void *lhs, const void *rhs, void *args);
71        void (*swp)(void *lhs, void *rhs, void *args);
72    };
73
74- **less** is the comparison function used to establish the order of elements.
75- **swp** is a function for swapping elements in the heap. If swp is set to
76  NULL, the default swap function will be used, which swaps the elements based on their size
77
78Macro Wrappers
79==============
80
81The following macro wrappers are provided for interacting with the heap in a
82user-friendly manner. Each macro corresponds to a function that operates on the
83heap, and they abstract away direct calls to internal functions.
84
85Each macro accepts various parameters that are detailed below.
86
87Heap Initialization
88--------------------
89
90.. code-block:: c
91
92    min_heap_init(heap, data, size);
93
94- **heap**: A pointer to the min-heap structure to be initialized.
95- **data**: A pointer to the buffer where the heap elements will be stored. If
96  `NULL`, the preallocated buffer within the heap structure will be used.
97- **size**: The maximum number of elements the heap can hold.
98
99This macro initializes the heap, setting its initial state. If `data` is
100`NULL`, the preallocated memory inside the heap structure will be used for
101storage. Otherwise, the user-provided buffer is used. The operation is **O(1)**.
102
103**Inline Version:** min_heap_init_inline(heap, data, size)
104
105Accessing the Top Element
106-------------------------
107
108.. code-block:: c
109
110    element = min_heap_peek(heap);
111
112- **heap**: A pointer to the min-heap from which to retrieve the smallest
113  element.
114
115This macro returns a pointer to the smallest element (the root) of the heap, or
116`NULL` if the heap is empty. The operation is **O(1)**.
117
118**Inline Version:** min_heap_peek_inline(heap)
119
120Heap Insertion
121--------------
122
123.. code-block:: c
124
125    success = min_heap_push(heap, element, callbacks, args);
126
127- **heap**: A pointer to the min-heap into which the element should be inserted.
128- **element**: A pointer to the element to be inserted into the heap.
129- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
130  `less` and `swp` functions.
131- **args**: Optional arguments passed to the `less` and `swp` functions.
132
133This macro inserts an element into the heap. It returns `true` if the insertion
134was successful and `false` if the heap is full. The operation is **O(log n)**.
135
136**Inline Version:** min_heap_push_inline(heap, element, callbacks, args)
137
138Heap Removal
139------------
140
141.. code-block:: c
142
143    success = min_heap_pop(heap, callbacks, args);
144
145- **heap**: A pointer to the min-heap from which to remove the smallest element.
146- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
147  `less` and `swp` functions.
148- **args**: Optional arguments passed to the `less` and `swp` functions.
149
150This macro removes the smallest element (the root) from the heap. It returns
151`true` if the element was successfully removed, or `false` if the heap is
152empty. The operation is **O(log n)**.
153
154**Inline Version:** min_heap_pop_inline(heap, callbacks, args)
155
156Heap Maintenance
157----------------
158
159You can use the following macros to maintain the heap's structure:
160
161.. code-block:: c
162
163    min_heap_sift_down(heap, pos, callbacks, args);
164
165- **heap**: A pointer to the min-heap.
166- **pos**: The index from which to start sifting down.
167- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
168  `less` and `swp` functions.
169- **args**: Optional arguments passed to the `less` and `swp` functions.
170
171This macro restores the heap property by moving the element at the specified
172index (`pos`) down the heap until it is in the correct position. The operation
173is **O(log n)**.
174
175**Inline Version:** min_heap_sift_down_inline(heap, pos, callbacks, args)
176
177.. code-block:: c
178
179    min_heap_sift_up(heap, idx, callbacks, args);
180
181- **heap**: A pointer to the min-heap.
182- **idx**: The index of the element to sift up.
183- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
184  `less` and `swp` functions.
185- **args**: Optional arguments passed to the `less` and `swp` functions.
186
187This macro restores the heap property by moving the element at the specified
188index (`idx`) up the heap. The operation is **O(log n)**.
189
190**Inline Version:** min_heap_sift_up_inline(heap, idx, callbacks, args)
191
192.. code-block:: c
193
194    min_heapify_all(heap, callbacks, args);
195
196- **heap**: A pointer to the min-heap.
197- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
198  `less` and `swp` functions.
199- **args**: Optional arguments passed to the `less` and `swp` functions.
200
201This macro ensures that the entire heap satisfies the heap property. It is
202called when the heap is built from scratch or after many modifications. The
203operation is **O(n)**.
204
205**Inline Version:** min_heapify_all_inline(heap, callbacks, args)
206
207Removing Specific Elements
208--------------------------
209
210.. code-block:: c
211
212    success = min_heap_del(heap, idx, callbacks, args);
213
214- **heap**: A pointer to the min-heap.
215- **idx**: The index of the element to delete.
216- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
217  `less` and `swp` functions.
218- **args**: Optional arguments passed to the `less` and `swp` functions.
219
220This macro removes an element at the specified index (`idx`) from the heap and
221restores the heap property. The operation is **O(log n)**.
222
223**Inline Version:** min_heap_del_inline(heap, idx, callbacks, args)
224
225Other Utilities
226===============
227
228- **min_heap_full(heap)**: Checks whether the heap is full.
229  Complexity: **O(1)**.
230
231.. code-block:: c
232
233    bool full = min_heap_full(heap);
234
235- `heap`: A pointer to the min-heap to check.
236
237This macro returns `true` if the heap is full, otherwise `false`.
238
239**Inline Version:** min_heap_full_inline(heap)
240
241- **min_heap_empty(heap)**: Checks whether the heap is empty.
242  Complexity: **O(1)**.
243
244.. code-block:: c
245
246    bool empty = min_heap_empty(heap);
247
248- `heap`: A pointer to the min-heap to check.
249
250This macro returns `true` if the heap is empty, otherwise `false`.
251
252**Inline Version:** min_heap_empty_inline(heap)
253
254Example Usage
255=============
256
257An example usage of the min-heap API would involve defining a heap structure,
258initializing it, and inserting and removing elements as needed.
259
260.. code-block:: c
261
262    #include <linux/min_heap.h>
263
264    int my_less_function(const void *lhs, const void *rhs, void *args) {
265        return (*(int *)lhs < *(int *)rhs);
266    }
267
268    struct min_heap_callbacks heap_cb = {
269        .less = my_less_function,    /* Comparison function for heap order */
270        .swp  = NULL,                /* Use default swap function */
271    };
272
273    void example_usage(void) {
274        /* Pre-populate the buffer with elements */
275        int buffer[5] = {5, 2, 8, 1, 3};
276        /* Declare a min-heap */
277        DEFINE_MIN_HEAP(int, my_heap);
278
279        /* Initialize the heap with preallocated buffer and size */
280        min_heap_init(&my_heap, buffer, 5);
281
282        /* Build the heap using min_heapify_all */
283        my_heap.nr = 5;  /* Set the number of elements in the heap */
284        min_heapify_all(&my_heap, &heap_cb, NULL);
285
286        /* Peek at the top element (should be 1 in this case) */
287        int *top = min_heap_peek(&my_heap);
288        pr_info("Top element: %d\n", *top);
289
290        /* Pop the top element (1) and get the new top (2) */
291        min_heap_pop(&my_heap, &heap_cb, NULL);
292        top = min_heap_peek(&my_heap);
293        pr_info("New top element: %d\n", *top);
294
295        /* Insert a new element (0) and recheck the top */
296        int new_element = 0;
297        min_heap_push(&my_heap, &new_element, &heap_cb, NULL);
298        top = min_heap_peek(&my_heap);
299        pr_info("Top element after insertion: %d\n", *top);
300    }
301