Skip to content

Make all Level Zero calls GC-safe - #704

Merged
maleadt merged 1 commit into
mainfrom
tb/gcsafe-ccall
Oct 19, 2026
Merged

maleadt merged 1 commit into
mainfrom
tb/gcsafe-ccall

Conversation

@maleadt

@maleadt maleadt commented Oct 16, 2026

Copy link
Copy Markdown
Member

The generated Level Zero wrappers used a plain @ccall, so a thread blocked in the driver kept every other thread that needed a collection waiting. That hurts for zeModuleCreate (the IGC compile on a cold driver cache) and for wait on fences and events, which block for as long as the GPU work takes.

Like CUDA.jl, the generator now emits every Level Zero call as GPUToolbox's @gcsafe_ccall, enabled per library with gcsafe = true in the TOML (only ze.toml for now). The overhead is negligible: around 0–5 ns per call on 1.10 and 1.12. The hand-written GC-safe synchronization calls now go through the generated wrappers.

libze.jl was updated in place rather than regenerated, because regenerating would pull in newer headers. Apart from the macro, its AST is unchanged, and each rewritten function matches the generator's output for the 1.13 headers.

The new test blocks a worker thread in wait(event, timeout) while the main thread collects. Before this change GC.gc() stalled until the timeout (9.7 s) and the test failed; now it takes ~0.3 s (checked on 1.10 and 1.12).

Fixes #698

@codecov

codecov Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.48%. Comparing base (4ab2df8) to head (c8c290f).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #704      +/-   ##
==========================================
- Coverage   84.04%   83.48%   -0.56%     
==========================================
  Files          52       51       -1     
  Lines        4387     4263     -124     
==========================================
- Hits         3687     3559     -128     
- Misses        700      704       +4     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

The generated wrappers used a plain `@ccall`, keeping the calling thread
GC-unsafe while in the driver. Calls that block for a long time, such as
`zeModuleCreate` compiling a kernel or `wait` on a fence or event, then
stall every other thread that needs a collection until they return.

Like CUDA.jl, have the generator emit every Level Zero call as
`@gcsafe_ccall`, which is cheap enough for the non-blocking ones too. The
hand-written GC-safe synchronization calls now use the generated
wrappers. libze.jl was updated in place rather than regenerated, to avoid
picking up newer headers.

Fixes #698
maleadt added a commit that referenced this pull request Oct 19, 2026
The check was advisory, but clashed with the generated wrappers (formatted
with JuliaFormatter by res/wrap.jl): touching them made it suggest diffs so
large that posting the comment failed, as on #704. It also required running
a pull_request_target workflow on checked-out fork code.
@maleadt
maleadt merged commit e95e38f into main Oct 19, 2026
4 of 5 checks passed
@maleadt
maleadt deleted the tb/gcsafe-ccall branch October 19, 2026 05:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make blocking Level Zero calls GC-safe

1 participant