← Documents Documentation/core-api/min_heap.rst GitHub 원문 ↗

Linux 6.18.37 · Core API

Min Heap API

Linux min-heap data structure와 callback, 초기화·조회·삽입·삭제·heapify macro 및 retpoline 비용을 줄이는 inline variant를 설명합니다.

Source pathDocumentation/core-api/min_heap.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

min_heap.rst:1-302

Min-heap은 root에 최솟값을 유지하는 binary tree입니다. Kernel API는 `DEFINE_MIN_HEAP` 또는 `MIN_HEAP_PREALLOCATED`로 storage를 정의하고 `struct min_heap_callbacks`의 `less`와 `swp`로 ordering과 교환 방식을 지정합니다.

`min_heap_peek()`은 `O(1)`, push·pop·sift·특정 index 삭제는 `O(log n)`, 전체 heapify는 `O(n)`입니다. Public macro wrapper를 사용해야 하며 `__min_heap_*()` internal function을 직접 호출하면 안 됩니다.

성능이 중요한 path에서는 `_inline` variant가 comparison과 swap callback을 직접 호출하여 indirect call 비용을 줄입니다. 이는 `CONFIG_MITIGATION_RETPOLINE`이 활성화된 환경에서 특히 유용합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

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

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Min Heap API 소개

1-32

SPDX license 식별자는 GPL-2.0입니다.

Min Heap API

저자: Kuan-Wei Chiu <[email protected]>

소개 (Introduction)

Min Heap API는 Linux kernel에서 min-heap을 관리하는 function과 macro 집합을 제공합니다. Min-heap은 각 node의 값이 child 값보다 작거나 같은 binary tree structure이므로 가장 작은 element가 항상 root에 있습니다.

이 문서는 min-heap을 정의하고 사용하는 방법을 자세히 설명합니다. 사용자는 `__min_heap_*()` prefix가 붙은 function을 직접 호출하지 말고 제공되는 macro wrapper를 사용해야 합니다.

표준 version 외에도 성능이 중요한 상황을 위한 inline version이 있습니다. Inline function은 non-inline function과 같은 이름에 `_inline` suffix를 붙입니다. 예를 들어 `__min_heap_init_inline`의 macro wrapper는 `min_heap_init_inline`입니다. Inline version은 custom comparison과 swap function을 indirect function call 대신 직접 호출하므로 overhead를 크게 줄일 수 있습니다. 특히 `CONFIG_MITIGATION_RETPOLINE`을 활성화하면 indirect function call 비용이 커지므로 효과가 큽니다. Non-inline version과 마찬가지로 function을 직접 호출하지 말고 macro wrapper를 사용해야 합니다.

Min-heap data structure 정의

33-62

Data Structures

Min-Heap Definition

Min-heap의 핵심 data structure는 `MIN_HEAP_PREALLOCATED`와 `DEFINE_MIN_HEAP` macro로 정의합니다. 이 macro를 사용하면 preallocated buffer 또는 동적으로 할당한 memory를 사용하는 min-heap을 정의할 수 있습니다.

예제는 다음과 같습니다.

#define MIN_HEAP_PREALLOCATED(_type, _name, _nr)
struct _name {
    size_t nr;         /* Number of elements in the heap */
    size_t size;       /* Maximum number of elements that can be held */
    _type *data;    /* Pointer to the heap data */
    _type preallocated[_nr];  /* Static preallocated array */
}

#define DEFINE_MIN_HEAP(_type, _name) MIN_HEAP_PREALLOCATED(_type, _name, 0)

일반적인 heap structure에는 element 수를 나타내는 `nr`, heap의 최대 capacity인 `size`, element array pointer인 `data`가 포함됩니다. `MIN_HEAP_PREALLOCATED`를 사용하면 preallocated heap storage를 위한 static array를 선택적으로 지정할 수 있습니다.

Min Heap callback

63-79

Min Heap Callbacks

`struct min_heap_callbacks`는 heap element ordering과 swap 동작을 custom하게 지정합니다. 두 function pointer를 포함합니다.

struct min_heap_callbacks {
    bool (*less)(const void *lhs, const void *rhs, void *args);
    void (*swp)(void *lhs, void *rhs, void *args);
};
  • `less`는 element 순서를 정하는 comparison function입니다.
  • `swp`는 heap의 element를 교환하는 function입니다. `swp`를 `NULL`로 설정하면 element size를 기준으로 교환하는 기본 swap function을 사용합니다.

Macro wrapper와 heap 초기화

80-106

Macro Wrappers

Heap을 사용자 친화적으로 다루기 위해 다음 macro wrapper를 제공합니다. 각 macro는 heap을 조작하는 function에 대응하며 internal function의 직접 호출을 감춥니다. 각 macro의 parameter는 아래에서 설명합니다.

Heap Initialization

min_heap_init(heap, data, size);
  • `heap`: 초기화할 min-heap structure pointer입니다.
  • `data`: heap element를 저장할 buffer pointer입니다. `NULL`이면 heap structure 안의 preallocated buffer를 사용합니다.
  • `size`: heap이 담을 수 있는 최대 element 수입니다.

이 macro는 heap을 초기 상태로 설정합니다. `data`가 `NULL`이면 heap structure 내부의 preallocated memory를 사용하고, 그렇지 않으면 사용자가 제공한 buffer를 사용합니다. 시간 복잡도는 `O(1)`입니다.

Inline version은 `min_heap_init_inline(heap, data, size)`입니다.

최솟값 접근

107-121

Top element 접근 (Accessing the Top Element)

element = min_heap_peek(heap);
  • `heap`: 가장 작은 element를 가져올 min-heap pointer입니다.

이 macro는 heap의 가장 작은 element, 즉 root의 pointer를 반환합니다. Heap이 비어 있으면 `NULL`을 반환합니다. 시간 복잡도는 `O(1)`입니다.

Inline version은 `min_heap_peek_inline(heap)`입니다.

Heap insertion

122-139

Heap Insertion

success = min_heap_push(heap, element, callbacks, args);
  • `heap`: element를 insert할 min-heap pointer입니다.
  • `element`: heap에 insert할 element pointer입니다.
  • `callbacks`: `less`와 `swp` function을 제공하는 `struct min_heap_callbacks` pointer입니다.
  • `args`: `less`와 `swp` function에 전달할 optional argument입니다.

이 macro는 heap에 element를 insert합니다. 성공하면 `true`, heap이 가득 차 있으면 `false`를 반환합니다. 시간 복잡도는 `O(log n)`입니다.

Inline version은 `min_heap_push_inline(heap, element, callbacks, args)`입니다.

Heap removal

140-157

Heap Removal

success = min_heap_pop(heap, callbacks, args);
  • `heap`: 가장 작은 element를 제거할 min-heap pointer입니다.
  • `callbacks`: `less`와 `swp` function을 제공하는 `struct min_heap_callbacks` pointer입니다.
  • `args`: `less`와 `swp` function에 전달할 optional argument입니다.

이 macro는 heap의 가장 작은 element, 즉 root를 제거합니다. 성공하면 `true`, heap이 비어 있으면 `false`를 반환합니다. 시간 복잡도는 `O(log n)`입니다.

Inline version은 `min_heap_pop_inline(heap, callbacks, args)`입니다.

Heap property 유지

158-208

Heap Maintenance

다음 macro를 사용하여 heap structure를 유지할 수 있습니다.

min_heap_sift_down(heap, pos, callbacks, args);
  • `heap`: min-heap pointer입니다.
  • `pos`: sift down을 시작할 index입니다.
  • `callbacks`: `less`와 `swp` function을 제공하는 `struct min_heap_callbacks` pointer입니다.
  • `args`: `less`와 `swp` function에 전달할 optional argument입니다.

`min_heap_sift_down()`은 지정 index `pos`의 element를 올바른 위치에 도달할 때까지 heap 아래쪽으로 이동해 heap property를 복원합니다. 시간 복잡도는 `O(log n)`입니다. Inline version은 `min_heap_sift_down_inline(heap, pos, callbacks, args)`입니다.

min_heap_sift_up(heap, idx, callbacks, args);
  • `heap`: min-heap pointer입니다.
  • `idx`: 위쪽으로 sift할 element의 index입니다.
  • `callbacks`: `less`와 `swp` function을 제공하는 `struct min_heap_callbacks` pointer입니다.
  • `args`: `less`와 `swp` function에 전달할 optional argument입니다.

`min_heap_sift_up()`은 지정 index `idx`의 element를 heap 위쪽으로 이동해 heap property를 복원합니다. 시간 복잡도는 `O(log n)`입니다. Inline version은 `min_heap_sift_up_inline(heap, idx, callbacks, args)`입니다.

min_heapify_all(heap, callbacks, args);
  • `heap`: min-heap pointer입니다.
  • `callbacks`: `less`와 `swp` function을 제공하는 `struct min_heap_callbacks` pointer입니다.
  • `args`: `less`와 `swp` function에 전달할 optional argument입니다.

`min_heapify_all()`은 heap 전체가 heap property를 만족하도록 합니다. Heap을 처음부터 만들거나 많은 수정 뒤에 호출합니다. 시간 복잡도는 `O(n)`입니다. Inline version은 `min_heapify_all_inline(heap, callbacks, args)`입니다.

특정 element 제거

209-226

Removing Specific Elements

success = min_heap_del(heap, idx, callbacks, args);
  • `heap`: min-heap pointer입니다.
  • `idx`: 삭제할 element의 index입니다.
  • `callbacks`: `less`와 `swp` function을 제공하는 `struct min_heap_callbacks` pointer입니다.
  • `args`: `less`와 `swp` function에 전달할 optional argument입니다.

`min_heap_del()`은 지정 index `idx`의 element를 제거하고 heap property를 복원합니다. 시간 복잡도는 `O(log n)`입니다.

Inline version은 `min_heap_del_inline(heap, idx, callbacks, args)`입니다.

Heap 상태 utility

227-255

Other Utilities

  • `min_heap_full(heap)`은 heap이 가득 찼는지 검사합니다. 시간 복잡도는 `O(1)`입니다.
  • `min_heap_empty(heap)`는 heap이 비어 있는지 검사합니다. 시간 복잡도는 `O(1)`입니다.
bool full = min_heap_full(heap);

`heap`은 검사할 min-heap pointer입니다. `min_heap_full()`은 heap이 가득 찼으면 `true`, 아니면 `false`를 반환합니다. Inline version은 `min_heap_full_inline(heap)`입니다.

bool empty = min_heap_empty(heap);

`heap`은 검사할 min-heap pointer입니다. `min_heap_empty()`는 heap이 비어 있으면 `true`, 아니면 `false`를 반환합니다. Inline version은 `min_heap_empty_inline(heap)`입니다.

Min Heap API 사용 예제

256-302

Example Usage

Min-heap API의 일반적인 사용은 heap structure를 정의하고 초기화한 뒤 필요에 따라 element를 insert하거나 제거하는 과정으로 구성됩니다.

#include <linux/min_heap.h>

int my_less_function(const void *lhs, const void *rhs, void *args) {
    return (*(int *)lhs < *(int *)rhs);
}

struct min_heap_callbacks heap_cb = {
    .less = my_less_function,    /* Comparison function for heap order */
    .swp  = NULL,                /* Use default swap function */
};

void example_usage(void) {
    /* Pre-populate the buffer with elements */
    int buffer[5] = {5, 2, 8, 1, 3};
    /* Declare a min-heap */
    DEFINE_MIN_HEAP(int, my_heap);

    /* Initialize the heap with preallocated buffer and size */
    min_heap_init(&my_heap, buffer, 5);

    /* Build the heap using min_heapify_all */
    my_heap.nr = 5;  /* Set the number of elements in the heap */
    min_heapify_all(&my_heap, &heap_cb, NULL);

    /* Peek at the top element (should be 1 in this case) */
    int *top = min_heap_peek(&my_heap);
    pr_info("Top element: %d\n", *top);

    /* Pop the top element (1) and get the new top (2) */
    min_heap_pop(&my_heap, &heap_cb, NULL);
    top = min_heap_peek(&my_heap);
    pr_info("New top element: %d\n", *top);

    /* Insert a new element (0) and recheck the top */
    int new_element = 0;
    min_heap_push(&my_heap, &new_element, &heap_cb, NULL);
    top = min_heap_peek(&my_heap);
    pr_info("Top element after insertion: %d\n", *top);
}

예제는 `<linux/min_heap.h>`를 include하고 integer 비교 function `my_less_function()`과 기본 swap을 사용하는 `heap_cb`를 정의합니다. `DEFINE_MIN_HEAP(int, my_heap)`으로 heap을 선언하고 다섯 element가 든 buffer로 초기화합니다.

`my_heap.nr`을 5로 설정한 뒤 `min_heapify_all()`로 heap property를 구성합니다. `min_heap_peek()`은 1을 반환하고, `min_heap_pop()`으로 1을 제거한 다음에는 2가 top이 됩니다. 마지막으로 0을 `min_heap_push()`하면 새 top은 0이 됩니다.