diff --git a/.github/workflows/ci-julia-nightly.yml b/.github/workflows/ci-julia-nightly.yml index 7aaccae..01f6516 100644 --- a/.github/workflows/ci-julia-nightly.yml +++ b/.github/workflows/ci-julia-nightly.yml @@ -15,6 +15,11 @@ on: - 'LICENSE.md' - 'README.md' - '.github/workflows/TagBot.yml' + # Julia nightly changes without any change here (e.g. new LLVM versions, see #66), + # so also test it regularly. + schedule: + - cron: '17 4 * * 1' # weekly, Monday 04:17 UTC + workflow_dispatch: jobs: test-julia-nightly: timeout-minutes: 30 diff --git a/src/threadtasks.jl b/src/threadtasks.jl index 1ec5f29..695281b 100644 --- a/src/threadtasks.jl +++ b/src/threadtasks.jl @@ -61,12 +61,18 @@ end @noinline function wake_thread!(_tid::T) where {T<:Integer} tid = _tid % Int tidp1 = tid + one(tid) + # `Base.Workqueues` holds one queue per thread; `tidp1` must be a valid thread id. + # On Julia 1.13+ `Base.Workqueues` is a `OncePerThread`, and `Base.Workqueues()` is + # the *current* thread's queue, so its `length` is the number of queued tasks, not + # the number of threads. Assuming that count is `> tid` is false in general and lets + # LLVM 22 (Julia 1.14) miscompile the `length` loop (segfault). @static if VERSION >= v"1.13-" - assume(unsigned(length(Base.Workqueues())) > unsigned(tid)) + assume(unsigned(Threads.maxthreadid()) > unsigned(tid)) else assume(unsigned(length(Base.Workqueues)) > unsigned(tid)) end - assume(unsigned(length(TASKS)) > unsigned(tidp1)) + # `TASKS[tid]` is accessed below; `tid` ranges over `1:length(TASKS)`. + assume(unsigned(length(TASKS)) >= unsigned(tid)) @inbounds push!(Base.Workqueues[tidp1], TASKS[tid]) ccall(:jl_wakeup_thread, Cvoid, (Int16,), tid % Int16) end