-
Notifications
You must be signed in to change notification settings - Fork 21
Improvements to memory allocator safety validation and optimizations #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
visitorckw
wants to merge
12
commits into
sysprog21:main
Choose a base branch
from
visitorckw:allocator-improvement
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+89
−31
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The coalesced variable in selective_coalesce() was declared but never used. Remove it to clean up the code and reduce unnecessary clutter.
The calloc() and realloc() implementations did not align the requested size before passing it to the allocator. This could result in returning non-aligned memory blocks, which may trigger unaligned memory access exceptions on RISC-V. Align the total size in calloc() and the input size in realloc() to ensure the allocator always returns properly aligned memory.
Currently, the memory allocator does not trigger a kernel panic on detected corruption or invalid operations. However, once the heap is corrupted, the kernel can no longer guarantee safe or correct behavior. Introduce ERR_HEAP_CORRUPT with a corresponding error message to prepare for future panic-on-error handling in the memory allocator.
The memory allocator previously attempted to continue execution even if validate_block() failed, which indicates unexpected heap corruption or invalid memory operations. Once the heap is corrupted, the kernel can no longer guarantee safe or correct behavior. Invoke panic(ERR_HEAP_CORRUPT) when validate_block() fails in malloc(), free(), or realloc(), ensuring the kernel halts immediately on fatal allocator errors.
The allocator previously only validated the size and bounds of a memory block. It did not check whether the block's successor was physically adjacent in memory. Extend validate_block() to verify that a block's next pointer matches the expected location based on its size. This ensures corruption in the linked list of blocks is detected early and consistently.
Inline adjacency checks were open-coded in free() and selective_coalesce(). If these checks failed, the allocator would silently skip the block and continue, masking heap corruption. Replace the open-coded adjacency logic with calls to validate_block() to avoid duplication and ensure consistent validation. If a block fails validation, invoke panic(ERR_HEAP_CORRUPT) instead of silently ignoring the error, since heap corruption is fatal to kernel safety.
In malloc(), free_blocks_count was decremented only if it was greater than zero. However, once a usable block has been found, free_blocks_count should never be zero. If this condition occurs, it indicates a fatal inconsistency in allocator state. Replace the conditional decrement with a check that panics with ERR_HEAP_CORRUPT when free_blocks_count <= 0, ensuring the kernel halts on heap accounting corruption.
Errors that trigger kernel panic in the memory allocator are expected to almost never occur during normal operation. Hint these branches with unlikely() so the compiler can better optimize the common fast path. This change wraps validation failures and other fatal checks with unlikely(), without altering runtime behavior.
Splitting a large memory block into two smaller blocks is a common operation in the allocator. Introduce a split_block() helper to centralize this functionality and avoid repeating the same code. The helper also panics if the split size is invalid, ensuring stronger consistency checks in the allocator.
malloc() previously contained open-coded logic for splitting a large block into two smaller ones. This is now replaced with a call to the split_block() helper introduced earlier. This removes duplicated code and ensures consistency by reusing the centralized split implementation, which also includes stronger validation and error handling.
When realloc() is called with a smaller size than the current block, we can avoid allocating a new block and copying data. Instead, split the existing block into two smaller blocks using the split_block() helper. This fast path improves performance for shrinking realloc() calls and triggers selective coalescing only when fragmentation exceeds the threshold.
When realloc() needs a larger size, we can check if the next block is free and adjacent. If the combined size of the current and next block is sufficient, merge them into a single block and split it to the desired size. This fast path avoids allocating a new block and copying data, and selective coalescing is triggered only when fragmentation exceeds the threshold, improving performance for growing realloc() calls.
Note that this PR may cause the timer test to encounter a kernel panic. From a quick inspection, the panic is triggered when the timer subsystem calls list_pop() and attempts to free a node from timer_node_pool, resulting in an invalid free. After merging this PR, I plan to create a separate issue to discuss this problem and work on a proper fix. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Improve the memory allocator by enhancing safety, correctness, and performance. Key changes include adding panic on heap corruption, consolidating block validation in validate_block(), fixing missing alignment in calloc() and realloc(), introducing a split_block() helper, and adding fast paths for shrinking and growing realloc(). These changes reduce code duplication, ensure consistent validation, and optimize common allocation operations.