I would like to ensure that within a certain block of code no task switch can happen.
A bit like an “atomic block” for async tasks
I would like to ensure that within a certain block of code no task switch can happen.
A bit like an “atomic block” for async tasks
No. IIRC we don’t have a way of marking critical region
is there already an issue for this feature request?
I opened an issue Feature Request: Possibility to mark certain code block as "Prevent taskswitch" · Issue #52313 · JuliaLang/julia · GitHub
Whatever this may be, transforming code that has “yield to another task” steps at arbitrary nested calls into code that has none at all would need some internals magic for sure. The more language-level approach would be to not schedule a task to begin with or never use task-switching methods in a block. As you’re probably hinting, substituting non-switching versions so thoroughly would be a chore. For the issue’s example, there’s Base.Libc.systemsleep
.
Is this even possible in a non real-time OS?
Afaik task switches only occur at certain method calls, is it possible to ensure that a block of code doesn’t make any of these calls? Essentially, write a “kernel” which does the pure steps, and doesn’t make any extraneous method calls which might trigger a task switch like I/O (if that’s possible for your use case).
this is about the Julia Task
, nothing to do with OS. But I do question the actual safety constraint this function can provide is even useful
that’s not a semantic guarentee made by Julia, it can do task switch any time it wants to, in practice if you have a tight kernel task switching is unlikely to happen but that shouldn’t be the way to achive critical region. It’s not reliable anyway
Intuitively whatever triggers the task-switch, maybe simply sleep
, could have a switch to not do a taskswitch but use Base.Libc.systemsleep instead.
If it is really only about sleep, I could build a Cassette Meta transformer which replaces all invokations to sleep with invokations to Base.Libc.systemsleep. This has the disadvantage of possibly intense recompilation, but would work.
Don’t think we can do anything about the OS, but this is about Julia’s task scheduler
the case I have is that I run a couple of Base.run() and HTTP requests and was confused about which trigger taskswitches and which not.
A preven_taskswitch
function would be the simple solution
Isn’t julia’s task system cooperative, meaning that there are a lot of yield points all over the place? I think IO is a big one that yields
function foo()
for i = 1:10000
print("a")
end
end
function bar()
for i = 1:10000
print("b")
end
end
t1 = @async foo()
t2 = @async bar()
prints
abababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab...
indicating that the print
calls yield.
that sounds horrible. I always thought we only need Atomics for Threads (also the documentation suggests this).
What you are writing would destroy plenty of async based logics
have you not seen PSA: Thread-local state is no longer recommended ?
the link is not about async tasks, but about Threads
async has the exact same issue:
julia> f(i) = (sleep(0.01); return i)
f (generic function with 1 method)
julia> state = [0]
1-element Vector{Int64}:
0
julia> @sync for i ∈ 1:100
@async state[1] += f(i)
end
julia> state
1-element Vector{Int64}:
100
you are calling sleep
this seems to indicate that async task can indeed not be interrupted anywhere, but just at certain points like sleep
sleep()
can be anything! Julia does not have a list of “possibly yileding” function and guarentee everything else is non-yielding
edit:
oh yeah, of course anything print()
or any logging happens you’re out
impressive!!!
thank you for the example. That looks like it is almost impossible to prevent task switches.
So I am back to locking
please link to the documentation which says so
It is pretty unbelievable for me to take your saying literal.