Skip to content

feat(libc): implement malloc_usable_size - #1656

Closed
NahuelGenchi wants to merge 1 commit into
boykopovar:mainfrom
NahuelGenchi:feat/libc-malloc-usable-size
Closed

NahuelGenchi wants to merge 1 commit into
boykopovar:mainfrom
NahuelGenchi:feat/libc-malloc-usable-size

Conversation

@NahuelGenchi

Copy link
Copy Markdown
Contributor

What

malloc_usable_size is imported from libSceLibcInternal by PPSA99005 and PPSA99001 (the ps5-opengl and ProsperoRadio homebrew in #1578) and wasn't exported. It returns the number of bytes a block can hold, which is at least what was requested. A null pointer gives 0, as on FreeBSD.

With the default heap it comes from the block header every allocation already carries: the space from the user pointer to the end of the raw block. That covers the extra room of the 16 byte header rounding and the padding added for aligned allocations, and the whole range is writable. A pointer the heap didn't hand out still fails the allocation lookup and throws, the same way free does.

When a title installs its own allocator, the call goes to its malloc_usable_size entry. The replacement table already carries it (slot 9 after malloc, free, calloc, realloc, memalign, reallocalign, posix_memalign, malloc_stats and malloc_stats_fast, in the order of MallocReplace in SceTypes.hpp). If a title leaves that entry empty the call throws like the other unregistered allocator entries, since there's no way to know the size without it.

The progress tool counts two functions here because it also counts the defaultUsableSize callback, like it counts the other default* callbacks in that file. The export itself is one.

PR #1611 also appends to the end of ApplicationHeap.cpp and its test, so those two will conflict as text. They add different functions, and whichever merges second needs a small rebase.

Tested

Ubuntu 26.04, GCC 15.2. application_heap_tests covers the title allocator path (the callback is called with the right pointer, null never reaches it), a table without the entry (throws, null still returns 0), and the default heap for 1, 37, 4096 and 100000 bytes plus aligned blocks: the result covers the request and every reported byte can be written. A stack address is rejected. The whole non-GPU suite passes (239 tests). Not run on Windows locally, so the Windows job is the first run there.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • AI-assisted: yes

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown

Progress report (4b005b2 → a1c86b1)

📈 System libraries: 84.77% (+0.01%, +2 implemented functions)

✅ 2 implemented
Library Name
libc defaultUsableSize
libc malloc_usable_size_nid_postfix

@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#1900 core/libs/prx/libc/src/ApplicationHeap.cpp L50-52, L54

@hikazey

hikazey commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Windows run, since the description says the Windows job would be the first run there: Windows 11 Pro (26200), MinGW-w64 GCC 15.2.0 (WinLibs r7, the CI build), Release, configured like CI, Ryzen 9 5900X. This commit merged onto main 6b56175a, which merges cleanly.

build application_heap_* (5 tests)
this PR 5/5 runs, all 5 tests pass
GuestHeapUsableSize_nid_postfix returning 0, tests kept application_heap_default fails in 5/5 runs
full suite with this PR 474/474 passed

The Windows guest heap commits through GuestArenaCommit rather than mmap, so I checked whether the reported size stays inside committed memory. application_heap_default writes every reported byte for 1, 37, 4096 and 100000 bytes and the aligned blocks, and it doesn't fault there.

AI-assisted: yes (Claude Code).

@popcoder565

Copy link
Copy Markdown
Contributor

First Windows run, since the description says it wasn't tested on Windows.

Setup: Windows 10 (19045), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release. Merged onto main b7218b3 together with nine other small libc/libkernel PRs: #1975, #1976, #1977, #1859, #1685, #1676, #1675, #1641, #1807.

  • application_heap_replacement passes.
  • Full ctest: 510/510 (one GPU test skipped for a device limit).

🤖 Addressed by Claude Code

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Closing: no title is shown stopping at malloc_usable_size on main. PPSA99005 and PPSA99001 import it but stop on other imports first; reopen with the title ID and the log line once one stops here.

@babyhuey

Copy link
Copy Markdown
Contributor

@NahuelGenchi OpenRCT2 Native Port (PPSA99728) now stops at malloc_usable_size on main f38a036 (catalog build, sce_module/libc.prx unwrapped, with #1529 in): app.elf: symbol lookup error: app.elf: undefined symbol: NDcSfcYZRC8. That's the reopen condition, and the intake check is at 10 merged PRs, so this can go up again as a new PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants