From 1d4a2bd678b13ff65b395386338642f5e577aefd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Mon, 11 Jun 2018 15:50:37 +0200 Subject: [PATCH] Add Task Sleeping --- libr/core/core.c | 2 +- libr/core/task.c | 42 +++++++++++++++++++++++++++++++----------- libr/include/r_core.h | 5 ++++- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/libr/core/core.c b/libr/core/core.c index ec23d71d63..25f2e4e316 100644 --- a/libr/core/core.c +++ b/libr/core/core.c @@ -1780,7 +1780,7 @@ static bool r_core_anal_read_at(struct r_anal_t *anal, ut64 addr, ut8 *buf, int static void r_core_break (RCore *core) { // if we are not in the main thread we hold in a lock RCoreTask *task = r_core_task_self (core); - r_core_task_schedule (task, false); + r_core_task_schedule (task, R_CORE_TASK_STATE_RUNNING); if (task && task->msg) { r_th_try_pause (task->msg->th); r_cons_singleton ()->breaked = false; diff --git a/libr/core/task.c b/libr/core/task.c index 24cad3bb1d..48991edcd5 100644 --- a/libr/core/task.c +++ b/libr/core/task.c @@ -85,21 +85,23 @@ hell: } } -R_API void r_core_task_schedule(RCoreTask *current, bool end) { +R_API void r_core_task_schedule(RCoreTask *current, RTaskState next_state) { RCore *core = current->core; + bool stop = next_state != R_CORE_TASK_STATE_RUNNING; core->current_task = NULL; r_th_lock_enter (core->tasks_lock); - if (end) { - current->state = R_CORE_TASK_STATE_DONE; + current->state = next_state; + + if (stop) { r_th_lock_leave (current->dispatch_lock); } RCoreTask *next = r_list_pop_head (core->tasks_queue); - if (next && !end) { + if (next && !stop) { r_list_append (core->tasks_queue, current); } @@ -110,29 +112,30 @@ R_API void r_core_task_schedule(RCoreTask *current, bool end) { r_th_lock_enter (next->dispatch_lock); r_th_cond_signal (next->dispatch_cond); r_th_lock_leave (next->dispatch_lock); - if (!end) { + if (!stop) { r_th_cond_wait (current->dispatch_cond, current->dispatch_lock); r_cons_load (current->cons); } - } else if (current != core->main_task && end) { + } else if (current != core->main_task && stop) { // all tasks done, reset to main cons current->cons = r_cons_dump (); r_cons_load (core->main_task->cons); core->main_task->cons = NULL; } - if (!end) { + if (!stop) { core->current_task = current; } } -static void task_begin(RCoreTask *current) { +static void task_wakeup(RCoreTask *current) { RCore *core = current->core; r_th_lock_enter (current->core->tasks_lock); current->state = R_CORE_TASK_STATE_RUNNING; + // check if there are other tasks running bool single = true; RCoreTask *task; RListIter *iter; @@ -145,6 +148,8 @@ static void task_begin(RCoreTask *current) { r_th_lock_enter (current->dispatch_lock); + // if we are not the only task, we must wait until another task signals us. + if (!single) { r_list_append (current->core->tasks_queue, current); } @@ -160,7 +165,9 @@ static void task_begin(RCoreTask *current) { // swap cons if (current->cons) { // we are the main task and some other task has already dumped the main cons for us + // or we were sleeping. r_cons_load (current->cons); + current->cons = NULL; } if (core->main_task != current) { // we are not the main task, so we need a new cons current->cons = r_cons_dump_new (); @@ -170,15 +177,16 @@ static void task_begin(RCoreTask *current) { core->main_task->cons = r_cons_dump (); } r_cons_load (current->cons); + current->cons = NULL; } } R_API void r_core_task_continue(RCoreTask *t) { - r_core_task_schedule (t, false); + r_core_task_schedule (t, R_CORE_TASK_STATE_RUNNING); } static void task_end(RCoreTask *t) { - r_core_task_schedule (t, true); + r_core_task_schedule (t, R_CORE_TASK_STATE_DONE); } @@ -190,7 +198,7 @@ static int task_finished(void *user, void *data) { static int task_run(RCoreTask *task) { RCore *core = task->core; - task_begin (task); + task_wakeup (task); // close (2); // no stderr char *res_str; @@ -243,10 +251,22 @@ R_API void r_core_task_sync_end(RCore *core) { task_end(core->main_task); } +/* To be called from within a task. + * Begin sleeping and schedule other tasks until r_core_task_sleep_end() is called. */ +R_API void r_core_task_sleep_begin(RCoreTask *task) { + r_core_task_schedule (task, R_CORE_TASK_STATE_SLEEPING); +} + +R_API void r_core_task_sleep_end(RCoreTask *task) { + task_wakeup (task); +} + R_API const char *r_core_task_status (RCoreTask *task) { switch (task->state) { case R_CORE_TASK_STATE_RUNNING: return "running"; + case R_CORE_TASK_STATE_SLEEPING: + return "sleeping"; case R_CORE_TASK_STATE_DONE: return "done"; case R_CORE_TASK_STATE_BEFORE_START: diff --git a/libr/include/r_core.h b/libr/include/r_core.h index d7075a880e..20ce70ad9d 100644 --- a/libr/include/r_core.h +++ b/libr/include/r_core.h @@ -681,6 +681,7 @@ typedef void (*RCoreTaskCallback)(void *user, char *out); typedef enum { R_CORE_TASK_STATE_BEFORE_START, R_CORE_TASK_STATE_RUNNING, + R_CORE_TASK_STATE_SLEEPING, R_CORE_TASK_STATE_DONE } RTaskState; @@ -706,6 +707,8 @@ R_API void r_core_task_enqueue(RCore *core, RCoreTask *task); R_API int r_core_task_run_sync(RCore *core, RCoreTask *task); R_API void r_core_task_sync_begin(RCore *core); R_API void r_core_task_sync_end(RCore *core); +R_API void r_core_task_sleep_begin(RCoreTask *task); +R_API void r_core_task_sleep_end(RCoreTask *task); R_API int r_core_task_del (RCore *core, int id); R_API RCoreTask *r_core_task_self (RCore *core); R_API void r_core_task_join (RCore *core, RCoreTask *task); @@ -714,7 +717,7 @@ typedef void (*inRangeCb) (RCore *core, ut64 from, ut64 to, int vsize, R_API int r_core_search_value_in_range (RCore *core, RInterval search_itv, ut64 vmin, ut64 vmax, int vsize, bool asterisk, inRangeCb cb); -R_API void r_core_task_schedule(RCoreTask *current, bool end); +R_API void r_core_task_schedule(RCoreTask *current, RTaskState next_state); /* PLUGINS */ extern RCorePlugin r_core_plugin_java;