diff --git a/base/boot.jl b/base/boot.jl index 3dd891a22d5194..de72d9f7e8277b 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -114,7 +114,6 @@ # type Task # parent::Task -# last::Task # storage::Any # consumers # started::Bool diff --git a/base/docs/helpdb.jl b/base/docs/helpdb.jl index 25ed8c4e759060..130a72f5a3d07a 100644 --- a/base/docs/helpdb.jl +++ b/base/docs/helpdb.jl @@ -10883,13 +10883,6 @@ Returns `true` if the value of the sign of `x` is negative, otherwise `false`. """ signbit -doc""" - istaskstarted(task) -> Bool - -Tell whether a task has started executing. -""" -istaskstarted - doc""" clamp(x, lo, hi) diff --git a/base/exports.jl b/base/exports.jl index cfc1574f570464..b8022ea5975ccb 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1026,7 +1026,6 @@ export Condition, consume, current_task, - istaskstarted, istaskdone, lock, notify, diff --git a/base/serialize.jl b/base/serialize.jl index 5681286d1d6fb7..601fe6706c23b7 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -346,7 +346,7 @@ end function serialize(s::SerializationState, t::Task) serialize_cycle(s, t) && return - if istaskstarted(t) && !istaskdone(t) + if !istaskdone(t) error("cannot serialize a running Task") end writetag(s.io, TASK_TAG) diff --git a/base/task.jl b/base/task.jl index b360a3a119a20c..e8470c3a105acf 100644 --- a/base/task.jl +++ b/base/task.jl @@ -62,7 +62,6 @@ end current_task() = ccall(:jl_get_current_task, Any, ())::Task istaskdone(t::Task) = ((t.state == :done) | (t.state == :failed)) -istaskstarted(t::Task) = isdefined(t, :last) yieldto(t::Task, x::ANY = nothing) = ccall(:jl_switchto, Any, (Any, Any), t, x) @@ -115,60 +114,55 @@ suppress_excp_printing(t::Task) = isa(t.storage, ObjectIdDict) ? get(get_task_tl function task_done_hook(t::Task) err = (t.state == :failed) result = t.result - nexttask = t.last handled = true if err t.backtrace = catch_backtrace() end q = t.consumers + t.consumers = nothing + + if isa(t.donenotify, Condition) + handled |= !isempty(t.donenotify.waitq) + notify(t.donenotify, result, error=err) + end #### un-optimized version #isa(q,Condition) && notify(q, result, error=err) if isa(q,Task) nexttask = q nexttask.state = :runnable + if err + nexttask.exception = result + end + yieldto(nexttask, result) # this terminates the task elseif isa(q,Condition) && !isempty(q.waitq) notify(q, result, error=err) else handled = false end - t.consumers = nothing - - if isa(t.donenotify,Condition) - handled |= !isempty(t.donenotify.waitq) - notify(t.donenotify, result, error=err) - end - - if nexttask.state == :runnable - if err - nexttask.exception = result + if err && !handled + if isa(result,InterruptException) && isdefined(Base,:active_repl_backend) && + active_repl_backend.backend_task.state == :waiting && isempty(Workqueue) && + active_repl_backend.in_eval + throwto(active_repl_backend.backend_task, result) end - yieldto(nexttask, result) - else - if err && !handled - if isa(result,InterruptException) && isdefined(Base,:active_repl_backend) && - active_repl_backend.backend_task.state == :waiting && isempty(Workqueue) && - active_repl_backend.in_eval - throwto(active_repl_backend.backend_task, result) - end - if !suppress_excp_printing(t) - let bt = t.backtrace - # run a new task to print the error for us - @schedule with_output_color(:red, STDERR) do io - print(io, "ERROR (unhandled task failure): ") - showerror(io, result, bt) - println(io) - end + if !suppress_excp_printing(t) + let bt = t.backtrace + # run a new task to print the error for us + @schedule with_output_color(:red, STDERR) do io + print(io, "ERROR (unhandled task failure): ") + showerror(io, result, bt) + println(io) end end end - # if a finished task accidentally gets into the queue, wait() - # could return. in that case just take the next task off the queue. - while true - wait() - end + end + # if a finished task accidentally gets into the queue, wait() + # could return. in that case just take the next task off the queue. + while true + wait() end end diff --git a/src/gc.c b/src/gc.c index d1afbdfb46bfbf..9dfe343b330a48 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1577,7 +1577,6 @@ static void gc_mark_task_stack(jl_task_t *ta, int d) NOINLINE static void gc_mark_task(jl_task_t *ta, int d) { if (ta->parent) gc_push_root(ta->parent, d); - if (ta->last) gc_push_root(ta->last, d); gc_push_root(ta->tls, d); gc_push_root(ta->consumers, d); gc_push_root(ta->donenotify, d); diff --git a/src/julia.h b/src/julia.h index d72651dd78fc6c..32972252327375 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1374,7 +1374,6 @@ typedef struct _jl_handler_t { typedef struct _jl_task_t { JL_DATA_TYPE struct _jl_task_t *parent; - struct _jl_task_t *last; jl_value_t *tls; jl_sym_t *state; jl_value_t *consumers; diff --git a/src/task.c b/src/task.c index 82e378901af5b3..6da2eeb2364cad 100644 --- a/src/task.c +++ b/src/task.c @@ -254,7 +254,7 @@ static void NORETURN finish_task(jl_task_t *t, jl_value_t *resultval) // early free of stkbuf void *stkbuf = t->stkbuf; if (stkbuf != NULL) { - t->stkbuf = NULL; + t->stkbuf = (void*)(intptr_t)-1; free(stkbuf - sizeof(size_t)); } #endif @@ -344,8 +344,6 @@ static void ctx_switch(jl_task_t *t) jl_current_module = last->current_module; } - t->last = jl_current_task; - jl_gc_wb(t, t->last); jl_current_task = t; #if defined(_OS_WINDOWS_) && !defined(COPY_STACKS) @@ -424,9 +422,12 @@ JL_THREAD jl_value_t * volatile jl_task_arg_in_transit; extern int jl_in_gc; DLLEXPORT jl_value_t *jl_switchto(jl_task_t *t, jl_value_t *arg) { + if (t == jl_current_task) { + throw_if_exception_set(t); + return arg; + } if (t->state == done_sym || t->state == failed_sym || - // task started but stkbuf NULL'd => finish_task ran - (t->last != NULL && t->stkbuf == NULL && t != jl_current_task)) { + (t->stkbuf == (void*)(intptr_t)-1)) { if (t->exception != jl_nothing) jl_throw(t->exception); return t->result; @@ -824,7 +825,6 @@ DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, size_t ssize) t->ssize = ssize; t->current_module = NULL; t->parent = jl_current_task; - t->last = NULL; t->tls = jl_nothing; t->consumers = jl_nothing; t->state = runnable_sym; @@ -856,8 +856,8 @@ DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, size_t ssize) static void jl_unprotect_stack(jl_task_t *t) { void *stk = t->stkbuf; - if (stk) { - t->stkbuf = NULL; + if (stk && stk != (void*)(intptr_t)-1) { + t->stkbuf = (void*)(intptr_t)-1; #ifdef COPY_STACKS free(stk - sizeof(size_t)); #else @@ -882,9 +882,8 @@ void jl_init_tasks(void) jl_task_type = jl_new_datatype(jl_symbol("Task"), jl_any_type, jl_emptysvec, - jl_svec(10, + jl_svec(9, jl_symbol("parent"), - jl_symbol("last"), jl_symbol("storage"), jl_symbol("state"), jl_symbol("consumers"), @@ -893,13 +892,13 @@ void jl_init_tasks(void) jl_symbol("exception"), jl_symbol("backtrace"), jl_symbol("code")), - jl_svec(10, - jl_any_type, jl_any_type, + jl_svec(9, + jl_any_type, jl_any_type, jl_sym_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_function_type), - 0, 1, 0); + 0, 1, 8); jl_svecset(jl_task_type->types, 0, (jl_value_t*)jl_task_type); done_sym = jl_symbol("done"); @@ -975,8 +974,7 @@ void jl_init_root_task(void *stack, size_t ssize) jl_current_task->started = 1; jl_current_task->parent = jl_current_task; jl_current_task->current_module = jl_current_module; - jl_current_task->last = jl_current_task; - jl_current_task->tls = NULL; + jl_current_task->tls = jl_nothing; jl_current_task->consumers = jl_nothing; jl_current_task->state = runnable_sym; jl_current_task->start = NULL;