Skip to content

Commit 5993983

Browse files
committed
Use the root task as a scheduler task
1 parent 992c520 commit 5993983

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

base/task.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,12 @@ function wait()
12031203
return result
12041204
end
12051205

1206+
function wait_forever()
1207+
while true
1208+
wait()
1209+
end
1210+
end
1211+
12061212
if Sys.iswindows()
12071213
pause() = ccall(:Sleep, stdcall, Cvoid, (UInt32,), 0xffffffff)
12081214
else

src/scheduler.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,6 @@ void jl_init_threadinginfra(void)
9696
}
9797

9898

99-
void JL_NORETURN jl_finish_task(jl_task_t *ct);
100-
10199
// thread function: used by all mutator threads except the main thread
102100
void jl_threadfun(void *arg)
103101
{
@@ -118,8 +116,24 @@ void jl_threadfun(void *arg)
118116
// free the thread argument here
119117
free(targ);
120118

121-
(void)jl_gc_unsafe_enter(ptls);
122-
jl_finish_task(ct); // noreturn
119+
// advance the world age of the root task as needed
120+
ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
121+
jl_function_t *wait_forever = (jl_function_t *)jl_get_global(jl_base_module, jl_symbol("wait_forever"));
122+
if (wait_forever == NULL)
123+
jl_error("root task cannot find wait_forever");
124+
jl_value_t *args[1] = {wait_forever};
125+
126+
for (; ;) {
127+
ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
128+
JL_TRY {
129+
jl_apply(args, 1);
130+
}
131+
JL_CATCH {
132+
jl_no_exc_handler(jl_current_exception(ct), ct);
133+
}
134+
}
135+
jl_gc_debug_critical_error();
136+
abort();
123137
}
124138

125139

@@ -376,14 +390,26 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q,
376390
continue;
377391
}
378392

379-
jl_cpu_pause();
380393
jl_ptls_t ptls = ct->ptls;
381-
if (sleep_check_after_threshold(&start_cycles) || (ptls->tid == jl_atomic_load_relaxed(&io_loop_tid) && (!jl_atomic_load_relaxed(&_threadedregion) || wait_empty))) {
394+
if (sleep_check_after_threshold(&start_cycles) || (ptls->tid == jl_atomic_load_relaxed(&io_loop_tid) && (!jl_atomic_load_relaxed(&_threadedregion) || wait_empty)) || ct == ptls->root_task) {
395+
// The place seems empty and this thread is on its way to sleeping;
396+
// switch to the root task to do that. We don't do this on thread 0
397+
// because we didn't start it and don't own it or its root task.
398+
if (ptls->tid != 0 && ct != ptls->root_task) {
399+
jl_switchto(&ptls->root_task);
400+
401+
// If we return here, `ct` must be runnable and someone has asked
402+
// it to run, so we return it.
403+
assert(jl_atomic_load_relaxed(&ct->_state) == JL_TASK_STATE_RUNNABLE);
404+
return ct;
405+
}
406+
382407
// acquire sleep-check lock
383408
assert(jl_atomic_load_relaxed(&ptls->sleep_check_state) == not_sleeping);
384409
jl_atomic_store_relaxed(&ptls->sleep_check_state, sleeping);
385410
jl_fence(); // [^store_buffering_1]
386411
JL_PROBE_RT_SLEEP_CHECK_SLEEP(ptls);
412+
387413
if (!check_empty(checkempty)) { // uses relaxed loads
388414
if (set_not_sleeping(ptls)) {
389415
JL_PROBE_RT_SLEEP_CHECK_TASKQ_WAKE(ptls);

0 commit comments

Comments
 (0)