요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
============
Min Heap API
============
:Author: Kuan-Wei Chiu <visitorckw@gmail.com>
Introduction
============
The Min Heap API provides a set of functions and macros for managing min-heaps
in the Linux kernel. A min-heap is a binary tree structure where the value of
each node is less than or equal to the values of its children, ensuring that
the smallest element is always at the root.
This document provides a guide to the Min Heap API, detailing how to define and
use min-heaps. Users should not directly call functions with **__min_heap_*()**
prefixes, but should instead use the provided macro wrappers.
In addition to the standard version of the functions, the API also includes a
set of inline versions for performance-critical scenarios. These inline
functions have the same names as their non-inline counterparts but include an
**_inline** suffix. For example, **__min_heap_init_inline** and its
corresponding macro wrapper **min_heap_init_inline**. The inline versions allow
custom comparison and swap functions to be called directly, rather than through
indirect function calls. This can significantly reduce overhead, especially
when CONFIG_MITIGATION_RETPOLINE is enabled, as indirect function calls become
more expensive. As with the non-inline versions, it is important to use the
macro wrappers for inline functions instead of directly calling the functions
themselves.
Data Structures
===============
Min-Heap Definition
-------------------
The core data structure for representing a min-heap is defined using the
**MIN_HEAP_PREALLOCATED** and **DEFINE_MIN_HEAP** macros. These macros allow
you to define a min-heap with a preallocated buffer or dynamically allocated
memory.
Example:
.. code-block:: c
#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)
A typical heap structure will include a counter for the number of elements
(`nr`), the maximum capacity of the heap (`size`), and a pointer to an array of
elements (`data`). Optionally, you can specify a static array for preallocated
heap storage using **MIN_HEAP_PREALLOCATED**.
Min Heap Callbacks
------------------
The **struct min_heap_callbacks** provides customization options for ordering
elements in the heap and swapping them. It contains two function pointers:
.. code-block:: c
struct min_heap_callbacks {
bool (*less)(const void *lhs, const void *rhs, void *args);
void (*swp)(void *lhs, void *rhs, void *args);
};
- **less** is the comparison function used to establish the order of elements.
- **swp** is a function for swapping elements in the heap. If swp is set to
NULL, the default swap function will be used, which swaps the elements based on their size
Macro Wrappers
==============
The following macro wrappers are provided for interacting with the heap in a
user-friendly manner. Each macro corresponds to a function that operates on the
heap, and they abstract away direct calls to internal functions.
Each macro accepts various parameters that are detailed below.
Heap Initialization
--------------------
.. code-block:: c
min_heap_init(heap, data, size);
- **heap**: A pointer to the min-heap structure to be initialized.
- **data**: A pointer to the buffer where the heap elements will be stored. If
`NULL`, the preallocated buffer within the heap structure will be used.
- **size**: The maximum number of elements the heap can hold.
This macro initializes the heap, setting its initial state. If `data` is
`NULL`, the preallocated memory inside the heap structure will be used for
storage. Otherwise, the user-provided buffer is used. The operation is **O(1)**.
**Inline Version:** min_heap_init_inline(heap, data, size)
Accessing the Top Element
-------------------------
.. code-block:: c
element = min_heap_peek(heap);
- **heap**: A pointer to the min-heap from which to retrieve the smallest
element.
This macro returns a pointer to the smallest element (the root) of the heap, or
`NULL` if the heap is empty. The operation is **O(1)**.
**Inline Version:** min_heap_peek_inline(heap)
Heap Insertion
--------------
.. code-block:: c
success = min_heap_push(heap, element, callbacks, args);
- **heap**: A pointer to the min-heap into which the element should be inserted.
- **element**: A pointer to the element to be inserted into the heap.
- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
`less` and `swp` functions.
- **args**: Optional arguments passed to the `less` and `swp` functions.
This macro inserts an element into the heap. It returns `true` if the insertion
was successful and `false` if the heap is full. The operation is **O(log n)**.
**Inline Version:** min_heap_push_inline(heap, element, callbacks, args)
Heap Removal
------------
.. code-block:: c
success = min_heap_pop(heap, callbacks, args);
- **heap**: A pointer to the min-heap from which to remove the smallest element.
- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
`less` and `swp` functions.
- **args**: Optional arguments passed to the `less` and `swp` functions.
This macro removes the smallest element (the root) from the heap. It returns
`true` if the element was successfully removed, or `false` if the heap is
empty. The operation is **O(log n)**.
**Inline Version:** min_heap_pop_inline(heap, callbacks, args)
Heap Maintenance
----------------
You can use the following macros to maintain the heap's structure:
.. code-block:: c
min_heap_sift_down(heap, pos, callbacks, args);
- **heap**: A pointer to the min-heap.
- **pos**: The index from which to start sifting down.
- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
`less` and `swp` functions.
- **args**: Optional arguments passed to the `less` and `swp` functions.
This macro restores the heap property by moving the element at the specified
index (`pos`) down the heap until it is in the correct position. The operation
is **O(log n)**.
**Inline Version:** min_heap_sift_down_inline(heap, pos, callbacks, args)
.. code-block:: c
min_heap_sift_up(heap, idx, callbacks, args);
- **heap**: A pointer to the min-heap.
- **idx**: The index of the element to sift up.
- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
`less` and `swp` functions.
- **args**: Optional arguments passed to the `less` and `swp` functions.
This macro restores the heap property by moving the element at the specified
index (`idx`) up the heap. The operation is **O(log n)**.
**Inline Version:** min_heap_sift_up_inline(heap, idx, callbacks, args)
.. code-block:: c
min_heapify_all(heap, callbacks, args);
- **heap**: A pointer to the min-heap.
- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
`less` and `swp` functions.
- **args**: Optional arguments passed to the `less` and `swp` functions.
This macro ensures that the entire heap satisfies the heap property. It is
called when the heap is built from scratch or after many modifications. The
operation is **O(n)**.
**Inline Version:** min_heapify_all_inline(heap, callbacks, args)
Removing Specific Elements
--------------------------
.. code-block:: c
success = min_heap_del(heap, idx, callbacks, args);
- **heap**: A pointer to the min-heap.
- **idx**: The index of the element to delete.
- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
`less` and `swp` functions.
- **args**: Optional arguments passed to the `less` and `swp` functions.
This macro removes an element at the specified index (`idx`) from the heap and
restores the heap property. The operation is **O(log n)**.
**Inline Version:** min_heap_del_inline(heap, idx, callbacks, args)
Other Utilities
===============
- **min_heap_full(heap)**: Checks whether the heap is full.
Complexity: **O(1)**.
.. code-block:: c
bool full = min_heap_full(heap);
- `heap`: A pointer to the min-heap to check.
This macro returns `true` if the heap is full, otherwise `false`.
**Inline Version:** min_heap_full_inline(heap)
- **min_heap_empty(heap)**: Checks whether the heap is empty.
Complexity: **O(1)**.
.. code-block:: c
bool empty = min_heap_empty(heap);
- `heap`: A pointer to the min-heap to check.
This macro returns `true` if the heap is empty, otherwise `false`.
**Inline Version:** min_heap_empty_inline(heap)
Example Usage
=============
An example usage of the min-heap API would involve defining a heap structure,
initializing it, and inserting and removing elements as needed.
.. code-block:: c
#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);
}
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Min Heap API 소개
1-32SPDX license 식별자는 GPL-2.0입니다.
Min Heap API
저자: Kuan-Wei Chiu <visitorckw@gmail.com>
소개 (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-62Data 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-79Min 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-106Macro 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-121Top 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-139Heap 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-157Heap 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-208Heap 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-226Removing 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-255Other 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-302Example 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이 됩니다.
요약과 해설
min_heap.rst:1-302Min-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`이 활성화된 환경에서 특히 유용합니다.