diff --git a/base/exports.jl b/base/exports.jl index 91a1c28807c11..92de059e5e76f 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1011,6 +1011,7 @@ export consume, current_task, istaskdone, + istaskstarted, lock, notify, produce, diff --git a/base/serialize.jl b/base/serialize.jl index d5647a678991d..d381cbf91f633 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -348,15 +348,18 @@ end function serialize(s::SerializationState, t::Task) serialize_cycle(s, t) && return - if !istaskdone(t) + if istaskstarted(t) && !istaskdone(t) error("cannot serialize a running Task") end + state = [t.code, + t.storage, + t.state == :queued || t.state == :runnable ? (:runnable) : t.state, + t.result, + t.exception] writetag(s.io, TASK_TAG) - serialize(s, t.code) - serialize(s, t.storage) - serialize(s, t.state == :queued || t.state == :runnable ? (:runnable) : t.state) - serialize(s, t.result) - serialize(s, t.exception) + for fld in state + serialize(s, fld) + end end function serialize_type_data(s, t) diff --git a/base/task.jl b/base/task.jl index 7b087ef2cadbc..15c99fea25bfe 100644 --- a/base/task.jl +++ b/base/task.jl @@ -66,6 +66,7 @@ end current_task() = ccall(:jl_get_current_task, Any, ())::Task istaskdone(t::Task) = ((t.state == :done) | (t.state == :failed)) +istaskstarted(t::Task) = ccall(:jl_is_task_started, Cint, (Any,), t) != 0 yieldto(t::Task, x::ANY = nothing) = ccall(:jl_switchto, Any, (Any, Any), t, x) diff --git a/src/julia.h b/src/julia.h index 931f7eb10c457..d096218c9964c 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1465,7 +1465,8 @@ typedef struct _jl_task_t { jl_jmp_buf ctx; size_t bufsz; void *stkbuf; - size_t ssize; + size_t ssize:31; + size_t started:1; // current exception handler jl_handler_t *eh; diff --git a/src/task.c b/src/task.c index a1387e894d128..8e40fcd8d2a03 100644 --- a/src/task.c +++ b/src/task.c @@ -240,6 +240,7 @@ static void NOINLINE NORETURN start_task(void) // this runs the first time we switch to a task jl_task_t *t = jl_current_task; jl_value_t *res; + t->started = 1; if (t->exception != NULL && t->exception != jl_nothing) { record_backtrace(); res = t->exception; @@ -863,6 +864,7 @@ DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, size_t ssize) t->gcstack = NULL; t->stkbuf = NULL; t->tid = 0; + t->started = 0; #ifdef COPY_STACKS t->bufsz = 0; @@ -952,6 +954,7 @@ void jl_init_root_task(void *stack, size_t ssize) jl_current_task->ssize = ssize; jl_current_task->stkbuf = stack; #endif + jl_current_task->started = 1; jl_current_task->parent = jl_current_task; jl_current_task->current_module = jl_current_module; jl_current_task->tls = jl_nothing; @@ -972,6 +975,11 @@ void jl_init_root_task(void *stack, size_t ssize) jl_task_arg_in_transit = (jl_value_t*)jl_nothing; } +DLLEXPORT int jl_is_task_started(jl_task_t *t) +{ + return t->started; +} + #ifdef __cplusplus } #endif