Rizin
unix-like reverse engineering framework and cli tools
task.c File Reference
#include <rz_core.h>

Go to the source code of this file.

Classes

struct  oneshot_t
 
struct  core_task_ctx_t
 
struct  cmd_task_ctx_t
 
struct  function_task_ctx_t
 

Macros

#define TASK_SIGSET_T   void *
 

Typedefs

typedef struct oneshot_t OneShot
 
typedef struct core_task_ctx_t CoreTaskCtx
 
typedef struct cmd_task_ctx_t CmdTaskCtx
 
typedef struct function_task_ctx_t FunctionTaskCtx
 

Functions

RZ_API void rz_core_task_scheduler_init (RzCoreTaskScheduler *sched, RzCoreTaskContextSwitch ctx_switch, void *ctx_switch_user, RzCoreTaskBreak break_cb, void *break_cb_user)
 
RZ_API void rz_core_task_scheduler_fini (RzCoreTaskScheduler *tasks)
 
static void tasks_lock_block_signals (TASK_SIGSET_T *old_sigset)
 
static void tasks_lock_block_signals_reset (TASK_SIGSET_T *old_sigset)
 
static void tasks_lock_enter (RzCoreTaskScheduler *scheduler, TASK_SIGSET_T *old_sigset)
 
static void tasks_lock_leave (RzCoreTaskScheduler *scheduler, TASK_SIGSET_T *old_sigset)
 
RZ_API int rz_core_task_running_tasks_count (RzCoreTaskScheduler *scheduler)
 
static void task_join (RzCoreTask *task)
 
RZ_API void rz_core_task_join (RzCoreTaskScheduler *scheduler, RzCoreTask *current, int id)
 
static void task_free (RzCoreTask *task)
 
RZ_API RzCoreTaskrz_core_task_new (RzCoreTaskScheduler *sched, RzCoreTaskRunner runner, RzCoreTaskRunnerFree runner_free, void *runner_user)
 
RZ_API void rz_core_task_incref (RzCoreTask *task)
 
RZ_API void rz_core_task_decref (RzCoreTask *task)
 
static void cleanup_transient (RzCoreTaskScheduler *sched, RzCoreTask *exclude)
 
RZ_API void rz_core_task_schedule (RzCoreTask *current, RzTaskState next_state)
 
static void task_wakeup (RzCoreTask *current)
 
RZ_API void rz_core_task_yield (RzCoreTaskScheduler *scheduler)
 
static void task_end (RzCoreTask *t)
 
static void * task_run_thread (RzCoreTask *task)
 
RZ_API void rz_core_task_enqueue (RzCoreTaskScheduler *scheduler, RzCoreTask *task)
 
RZ_API void rz_core_task_enqueue_oneshot (RzCoreTaskScheduler *scheduler, RzCoreTaskOneShot func, void *user)
 
RZ_API int rz_core_task_run_sync (RzCoreTaskScheduler *scheduler, RzCoreTask *task)
 
RZ_API void rz_core_task_sync_begin (RzCoreTaskScheduler *scheduler)
 
RZ_API void rz_core_task_sync_end (RzCoreTaskScheduler *scheduler)
 
RZ_API void rz_core_task_sleep_begin (RzCoreTask *task)
 
RZ_API void rz_core_task_sleep_end (RzCoreTask *task)
 
RZ_API RzCoreTaskrz_core_task_self (RzCoreTaskScheduler *scheduler)
 
static RzCoreTasktask_get (RzCoreTaskScheduler *scheduler, int id)
 
RZ_API RzCoreTaskrz_core_task_get_incref (RzCoreTaskScheduler *scheduler, int id)
 
static void task_break (RzCoreTask *task)
 
RZ_API void rz_core_task_break (RzCoreTaskScheduler *scheduler, int id)
 
RZ_API void rz_core_task_break_all (RzCoreTaskScheduler *scheduler)
 
RZ_API int rz_core_task_del (RzCoreTaskScheduler *scheduler, int id)
 
static bool core_task_ctx_init (CoreTaskCtx *ctx, RzCore *core)
 
static void core_task_ctx_fini (CoreTaskCtx *ctx)
 
static CmdTaskCtxcmd_task_ctx_new (RzCore *core, const char *cmd, RzCoreCmdTaskFinished finished_cb, void *finished_cb_user)
 
static void cmd_task_runner (RzCoreTaskScheduler *sched, void *user)
 
static void cmd_task_free (CmdTaskCtx *ctx)
 
RZ_API RzCoreTaskrz_core_cmd_task_new (RzCore *core, const char *cmd, RzCoreCmdTaskFinished finished_cb, void *finished_cb_user)
 
RZ_API const char * rz_core_cmd_task_get_result (RzCoreTask *task)
 
static FunctionTaskCtxfunction_task_ctx_new (RzCore *core, RzCoreTaskFunction fcn, void *fcn_user)
 
static void function_task_runner (RzCoreTaskScheduler *sched, void *user)
 
static void function_task_free (FunctionTaskCtx *ctx)
 
RZ_API RzCoreTaskrz_core_function_task_new (RzCore *core, RzCoreTaskFunction fcn, void *fcn_user)
 
RZ_API void * rz_core_function_task_get_result (RzCoreTask *task)
 
RZ_IPI void rz_core_task_ctx_switch (RzCoreTask *next, void *user)
 
RZ_IPI void rz_core_task_break_cb (RzCoreTask *task, void *user)
 
RZ_API const char * rz_core_task_status (RzCoreTask *task)
 
RZ_API void rz_core_task_print (RzCore *core, RzCoreTask *task, int mode, PJ *j)
 
RZ_API void rz_core_task_list (RzCore *core, int mode)
 
RZ_API bool rz_core_task_is_cmd (RzCore *core, int id)
 
RZ_API void rz_core_task_del_all_done (RzCore *core)
 

Macro Definition Documentation

◆ TASK_SIGSET_T

#define TASK_SIGSET_T   void *

Definition at line 47 of file task.c.

Typedef Documentation

◆ CmdTaskCtx

typedef struct cmd_task_ctx_t CmdTaskCtx

Context for (user-visible) command tasks

◆ CoreTaskCtx

typedef struct core_task_ctx_t CoreTaskCtx

Common base for all contexts of tasks in core. Must be the first member of every task context!

◆ FunctionTaskCtx

Context for (user-invisible) function tasks

◆ OneShot

typedef struct oneshot_t OneShot

Function Documentation

◆ cleanup_transient()

static void cleanup_transient ( RzCoreTaskScheduler sched,
RzCoreTask exclude 
)
static

Delete all done, transient, non-current jobs that have not been deleted yet.

Definition at line 217 of file task.c.

217  {
218  RzCoreTask *ltask;
219  RzListIter *iter;
220  RzListIter *iter_tmp;
221  rz_list_foreach_safe (sched->tasks, iter, iter_tmp, ltask) {
222  if (ltask == exclude) {
223  continue;
224  }
225  if (ltask->transient && ltask->state == RZ_CORE_TASK_STATE_DONE) {
226  rz_list_delete(sched->tasks, iter);
227  }
228  }
229 }
RZ_API void rz_list_delete(RZ_NONNULL RzList *list, RZ_NONNULL RzListIter *iter)
Removes an entry in the list by using the RzListIter pointer.
Definition: list.c:162
struct rz_core_task_t RzCoreTask
Definition: rz_core.h:254
RzList * tasks
Definition: rz_core.h:272

References rz_list_delete(), and rz_core_tasks_t::tasks.

Referenced by rz_core_task_schedule().

◆ cmd_task_ctx_new()

static CmdTaskCtx* cmd_task_ctx_new ( RzCore core,
const char *  cmd,
RzCoreCmdTaskFinished  finished_cb,
void *  finished_cb_user 
)
static

Definition at line 575 of file task.c.

575  {
578  if (!ctx) {
579  return NULL;
580  }
581  if (!core_task_ctx_init(&ctx->core_ctx, core)) {
582  free(ctx);
583  return NULL;
584  }
585  ctx->cmd = strdup(cmd);
586  ctx->cmd_log = false;
587  ctx->res = NULL;
588  ctx->finished_cb = finished_cb;
589  ctx->finished_cb_user = finished_cb_user;
590  return ctx;
591 }
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
Definition: sflib.h:79
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define RZ_NEW(x)
Definition: rz_types.h:285
static bool core_task_ctx_init(CoreTaskCtx *ctx, RzCore *core)
Definition: task.c:545

References cmd, core_task_ctx_init(), free(), NULL, RZ_NEW, rz_return_val_if_fail, and strdup().

Referenced by rz_core_cmd_task_new().

◆ cmd_task_free()

static void cmd_task_free ( CmdTaskCtx ctx)
static

Definition at line 615 of file task.c.

615  {
616  if (!ctx) {
617  return;
618  }
619  free(ctx->cmd);
620  free(ctx->res);
621  core_task_ctx_fini(&ctx->core_ctx);
622  free(ctx);
623 }
static void core_task_ctx_fini(CoreTaskCtx *ctx)
Definition: task.c:556

References core_task_ctx_fini(), and free().

Referenced by rz_core_cmd_task_new().

◆ cmd_task_runner()

static void cmd_task_runner ( RzCoreTaskScheduler sched,
void *  user 
)
static

Definition at line 593 of file task.c.

593  {
594  CmdTaskCtx *ctx = user;
595  RzCore *core = ctx->core_ctx.core;
596  RzCoreTask *task = rz_core_task_self(sched);
597  char *res_str;
598  if (task == sched->main_task) {
599  rz_core_cmd(core, ctx->cmd, ctx->cmd_log);
600  res_str = NULL;
601  } else {
602  res_str = rz_core_cmd_str(core, ctx->cmd);
603  }
604  ctx->res = res_str;
605 
606  if (ctx->finished_cb) {
607  ctx->finished_cb(res_str, ctx->finished_cb_user);
608  }
609 
610  if (task != sched->main_task && rz_cons_default_context_is_interactive()) {
611  eprintf("\nTask %d finished\n", task->id);
612  }
613 }
RZ_API int rz_core_cmd(RzCore *core, const char *cstr, int log)
Definition: cmd.c:5328
RZ_API char * rz_core_cmd_str(RzCore *core, const char *cmd)
Executes a rizin command and returns the stdout as a string.
Definition: cmd.c:5513
RZ_API bool rz_cons_default_context_is_interactive(void)
Definition: cons.c:369
#define eprintf(x, y...)
Definition: rlcc.c:7
struct rz_core_task_t * main_task
Definition: rz_core.h:277
RZ_API RzCoreTask * rz_core_task_self(RzCoreTaskScheduler *scheduler)
Definition: task.c:446

References eprintf, rz_core_tasks_t::main_task, NULL, rz_cons_default_context_is_interactive(), rz_core_cmd(), rz_core_cmd_str(), and rz_core_task_self().

Referenced by rz_core_cmd_task_get_result(), rz_core_cmd_task_new(), rz_core_task_del_all_done(), rz_core_task_is_cmd(), and rz_core_task_print().

◆ core_task_ctx_fini()

static void core_task_ctx_fini ( CoreTaskCtx ctx)
static

Definition at line 556 of file task.c.

556  {
557  if (ctx->cons_context && ctx->cons_context->break_stack) {
558  rz_cons_context_break_pop(ctx->cons_context, false);
559  }
560  rz_cons_context_free(ctx->cons_context);
561 }
RZ_API void rz_cons_context_free(RzConsContext *context)
Definition: cons.c:897
RZ_API void rz_cons_context_break_pop(RzConsContext *context, bool sig)
Definition: cons.c:335

References rz_cons_context_break_pop(), and rz_cons_context_free().

Referenced by cmd_task_free(), and function_task_free().

◆ core_task_ctx_init()

static bool core_task_ctx_init ( CoreTaskCtx ctx,
RzCore core 
)
static

Definition at line 545 of file task.c.

545  {
546  ctx->core = core;
547  ctx->cons_context = rz_cons_context_new(rz_cons_singleton()->context);
548  if (!ctx->cons_context) {
549  return false;
550  }
551  ctx->cons_context->cmd_depth = core->max_cmd_depth;
552  rz_cons_context_break_push(ctx->cons_context, NULL, NULL, false);
553  return true;
554 }
RZ_API RzConsContext * rz_cons_context_new(RZ_NULLABLE RzConsContext *parent)
Definition: cons.c:888
RZ_API RzCons * rz_cons_singleton(void)
Definition: cons.c:300
RZ_API void rz_cons_context_break_push(RzConsContext *context, RzConsBreak cb, void *user, bool sig)
Definition: cons.c:308
int max_cmd_depth
Definition: rz_core.h:363

References rz_core_t::max_cmd_depth, NULL, rz_cons_context_break_push(), rz_cons_context_new(), and rz_cons_singleton().

Referenced by cmd_task_ctx_new(), and function_task_ctx_new().

◆ function_task_ctx_new()

static FunctionTaskCtx* function_task_ctx_new ( RzCore core,
RzCoreTaskFunction  fcn,
void *  fcn_user 
)
static

Definition at line 665 of file task.c.

665  {
667  if (!ctx) {
668  return NULL;
669  }
670  if (!core_task_ctx_init(&ctx->core_ctx, core)) {
671  free(ctx);
672  return NULL;
673  }
674  ctx->fcn = fcn;
675  ctx->fcn_user = fcn_user;
676  ctx->res = NULL;
677  return ctx;
678 }

References core_task_ctx_init(), free(), NULL, and RZ_NEW.

Referenced by rz_core_function_task_new().

◆ function_task_free()

static void function_task_free ( FunctionTaskCtx ctx)
static

Definition at line 688 of file task.c.

688  {
689  if (!ctx) {
690  return;
691  }
692  core_task_ctx_fini(&ctx->core_ctx);
693  free(ctx);
694 }

References core_task_ctx_fini(), and free().

Referenced by rz_core_function_task_new().

◆ function_task_runner()

static void function_task_runner ( RzCoreTaskScheduler sched,
void *  user 
)
static

Definition at line 680 of file task.c.

680  {
681  FunctionTaskCtx *ctx = user;
682  RzCore *core = ctx->core_ctx.core;
683  rz_cons_push();
684  ctx->res = ctx->fcn(core, ctx->fcn_user);
685  rz_cons_pop();
686 }
RZ_API void rz_cons_pop(void)
Definition: cons.c:876
RZ_API void rz_cons_push(void)
Definition: cons.c:860

References rz_cons_pop(), and rz_cons_push().

Referenced by rz_core_function_task_get_result(), and rz_core_function_task_new().

◆ rz_core_cmd_task_get_result()

RZ_API const char* rz_core_cmd_task_get_result ( RzCoreTask task)

Get the result of the command that was run in a task created with rz_core_cmd_task_new. If the task is not a command task, returns NULL.

Definition at line 646 of file task.c.

646  {
647  // Check if this is really a command task
648  if (!task->runner_user || task->runner != cmd_task_runner) {
649  return NULL;
650  }
651  CmdTaskCtx *ctx = task->runner_user;
652  return ctx->res;
653 }
static void cmd_task_runner(RzCoreTaskScheduler *sched, void *user)
Definition: task.c:593

References cmd_task_runner(), and NULL.

Referenced by task_output().

◆ rz_core_cmd_task_new()

RZ_API RzCoreTask* rz_core_cmd_task_new ( RzCore core,
const char *  cmd,
RzCoreCmdTaskFinished  finished_cb,
void *  finished_cb_user 
)

Create a new task that runs a command and saves its result. These tasks are user-visible under the & command family.

Definition at line 629 of file task.c.

629  {
630  CmdTaskCtx *ctx = cmd_task_ctx_new(core, cmd, finished_cb, finished_cb_user);
631  if (!ctx) {
632  return NULL;
633  }
634  RzCoreTask *task = rz_core_task_new(&core->tasks, cmd_task_runner, (RzCoreTaskRunnerFree)cmd_task_free, ctx);
635  if (!task) {
637  return NULL;
638  }
639  return task;
640 }
RzCoreTaskScheduler tasks
Definition: rz_core.h:362
RZ_API RzCoreTask * rz_core_task_new(RzCoreTaskScheduler *sched, RzCoreTaskRunner runner, RzCoreTaskRunnerFree runner_free, void *runner_user)
Definition: task.c:161
static void cmd_task_free(CmdTaskCtx *ctx)
Definition: task.c:615
static CmdTaskCtx * cmd_task_ctx_new(RzCore *core, const char *cmd, RzCoreCmdTaskFinished finished_cb, void *finished_cb_user)
Definition: task.c:575

References cmd, cmd_task_ctx_new(), cmd_task_free(), cmd_task_runner(), NULL, rz_core_task_new(), and rz_core_t::tasks.

Referenced by task_enqueue().

◆ rz_core_function_task_get_result()

RZ_API void* rz_core_function_task_get_result ( RzCoreTask task)

Get the return value of the function that was run in a task created with rz_core_function_task_new. If the task is not a function task, returns NULL.

Definition at line 718 of file task.c.

718  {
719  // Check if this is really a command task
720  if (!task->runner_user || task->runner != function_task_runner) {
721  return NULL;
722  }
723  FunctionTaskCtx *ctx = task->runner_user;
724  return ctx->res;
725 }
static void function_task_runner(RzCoreTaskScheduler *sched, void *user)
Definition: task.c:680

References function_task_runner(), and NULL.

◆ rz_core_function_task_new()

RZ_API RzCoreTask* rz_core_function_task_new ( RzCore core,
RzCoreTaskFunction  fcn,
void *  fcn_user 
)

Create a new task that runs a custom function and saves its result. These tasks are not user-visible.

Definition at line 700 of file task.c.

700  {
701  FunctionTaskCtx *ctx = function_task_ctx_new(core, fcn, fcn_user);
702  if (!ctx) {
703  return NULL;
704  }
706  (RzCoreTaskRunnerFree)function_task_free, ctx);
707  if (!task) {
709  return NULL;
710  }
711  return task;
712 }
static void function_task_free(FunctionTaskCtx *ctx)
Definition: task.c:688
static FunctionTaskCtx * function_task_ctx_new(RzCore *core, RzCoreTaskFunction fcn, void *fcn_user)
Definition: task.c:665

References function_task_ctx_new(), function_task_free(), function_task_runner(), NULL, rz_core_task_new(), and rz_core_t::tasks.

◆ rz_core_task_break()

RZ_API void rz_core_task_break ( RzCoreTaskScheduler scheduler,
int  id 
)

Definition at line 483 of file task.c.

483  {
484  TASK_SIGSET_T old_sigset;
485  tasks_lock_enter(scheduler, &old_sigset);
486  RzCoreTask *task = task_get(scheduler, id);
487  if (!task || task->state == RZ_CORE_TASK_STATE_DONE) {
488  tasks_lock_leave(scheduler, &old_sigset);
489  return;
490  }
491  task_break(task);
492  tasks_lock_leave(scheduler, &old_sigset);
493 }
static void tasks_lock_enter(RzCoreTaskScheduler *scheduler, TASK_SIGSET_T *old_sigset)
Definition: task.c:56
static void tasks_lock_leave(RzCoreTaskScheduler *scheduler, TASK_SIGSET_T *old_sigset)
Definition: task.c:61
#define TASK_SIGSET_T
Definition: task.c:47
static RzCoreTask * task_get(RzCoreTaskScheduler *scheduler, int id)
Definition: task.c:450
static void task_break(RzCoreTask *task)
Definition: task.c:475

References task_break(), task_get(), TASK_SIGSET_T, tasks_lock_enter(), and tasks_lock_leave().

Referenced by task_break().

◆ rz_core_task_break_all()

RZ_API void rz_core_task_break_all ( RzCoreTaskScheduler scheduler)

Definition at line 495 of file task.c.

495  {
496  TASK_SIGSET_T old_sigset;
497  tasks_lock_enter(scheduler, &old_sigset);
498  RzCoreTask *task;
499  RzListIter *iter;
500  rz_list_foreach (scheduler->tasks, iter, task) {
501  if (task->state != RZ_CORE_TASK_STATE_DONE) {
502  task_break(task);
503  }
504  }
505  tasks_lock_leave(scheduler, &old_sigset);
506 }

References task_break(), TASK_SIGSET_T, rz_core_tasks_t::tasks, tasks_lock_enter(), and tasks_lock_leave().

Referenced by rz_core_fini(), and rz_main_rizin().

◆ rz_core_task_break_cb()

RZ_IPI void rz_core_task_break_cb ( RzCoreTask task,
void *  user 
)

Definition at line 738 of file task.c.

738  {
739  CoreTaskCtx *ctx = task->runner_user;
740  rz_cons_context_break(ctx ? ctx->cons_context : NULL);
741 }
RZ_API void rz_cons_context_break(RzConsContext *context)
Definition: cons.c:917

References NULL, and rz_cons_context_break().

Referenced by rz_core_init().

◆ rz_core_task_ctx_switch()

RZ_IPI void rz_core_task_ctx_switch ( RzCoreTask next,
void *  user 
)

Definition at line 727 of file task.c.

727  {
728  if (next->runner_user) {
729  CoreTaskCtx *ctx = next->runner_user;
730  if (ctx->cons_context) {
731  rz_cons_context_load(ctx->cons_context);
732  return;
733  }
734  }
736 }
RZ_API void rz_cons_context_reset(void)
Definition: cons.c:909
RZ_API void rz_cons_context_load(RzConsContext *context)
Definition: cons.c:905

References rz_cons_context_load(), and rz_cons_context_reset().

Referenced by rz_core_init().

◆ rz_core_task_decref()

RZ_API void rz_core_task_decref ( RzCoreTask task)

Definition at line 200 of file task.c.

200  {
201  if (!task) {
202  return;
203  }
204  TASK_SIGSET_T old_sigset;
205  RzCoreTaskScheduler *sched = task->sched;
206  tasks_lock_enter(sched, &old_sigset);
207  task->refcount--;
208  if (task->refcount <= 0) {
209  task_free(task);
210  }
211  tasks_lock_leave(sched, &old_sigset);
212 }
static void task_free(RzCoreTask *task)
Definition: task.c:144

References task_free(), TASK_SIGSET_T, tasks_lock_enter(), and tasks_lock_leave().

Referenced by rz_core_task_is_cmd(), rz_core_task_join(), rz_core_task_scheduler_init(), and task_output().

◆ rz_core_task_del()

RZ_API int rz_core_task_del ( RzCoreTaskScheduler scheduler,
int  id 
)

Definition at line 508 of file task.c.

508  {
509  RzCoreTask *task;
510  RzListIter *iter;
511  bool ret = false;
512  TASK_SIGSET_T old_sigset;
513  tasks_lock_enter(scheduler, &old_sigset);
514  rz_list_foreach (scheduler->tasks, iter, task) {
515  if (task->id == id) {
516  if (task == scheduler->main_task) {
517  break;
518  }
519  if (task->state == RZ_CORE_TASK_STATE_DONE) {
520  rz_list_delete(scheduler->tasks, iter);
521  } else {
522  task->transient = true;
523  }
524  ret = true;
525  break;
526  }
527  }
528  tasks_lock_leave(scheduler, &old_sigset);
529  return ret;
530 }

References rz_core_tasks_t::main_task, rz_list_delete(), TASK_SIGSET_T, rz_core_tasks_t::tasks, tasks_lock_enter(), and tasks_lock_leave().

Referenced by rz_tasks_delete_handler().

◆ rz_core_task_del_all_done()

RZ_API void rz_core_task_del_all_done ( RzCore core)

Definition at line 844 of file task.c.

844  {
845  TASK_SIGSET_T old_sigset;
846  tasks_lock_enter(&core->tasks, &old_sigset);
847  RzCoreTaskScheduler *sched = &core->tasks;
848  RzCoreTask *task;
849  RzListIter *iter, *iter2;
850  rz_list_foreach_safe (sched->tasks, iter, iter2, task) {
851  if (task != sched->main_task && task->state == RZ_CORE_TASK_STATE_DONE && task->runner == cmd_task_runner) {
852  rz_list_delete(sched->tasks, iter);
853  }
854  }
855  tasks_lock_leave(&core->tasks, &old_sigset);
856 }

References cmd_task_runner(), rz_core_tasks_t::main_task, rz_list_delete(), TASK_SIGSET_T, rz_core_tasks_t::tasks, rz_core_t::tasks, tasks_lock_enter(), and tasks_lock_leave().

Referenced by rz_tasks_delete_all_handler().

◆ rz_core_task_enqueue()

RZ_API void rz_core_task_enqueue ( RzCoreTaskScheduler scheduler,
RzCoreTask task 
)

Definition at line 374 of file task.c.

374  {
375  if (!scheduler || !task) {
376  return;
377  }
378  TASK_SIGSET_T old_sigset;
379  tasks_lock_enter(scheduler, &old_sigset);
380  if (!task->running_sem) {
381  task->running_sem = rz_th_sem_new(1);
382  }
383  if (task->running_sem) {
384  rz_th_sem_wait(task->running_sem);
385  }
386  rz_list_append(scheduler->tasks, task);
387  task->thread = rz_th_new((RzThreadFunction)task_run_thread, task);
388  tasks_lock_leave(scheduler, &old_sigset);
389 }
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API RZ_OWN RzThread * rz_th_new(RZ_NONNULL RzThreadFunction function, RZ_NULLABLE void *user)
Creates and starts a new thread.
Definition: thread.c:198
void *(* RzThreadFunction)(void *user)
Definition: rz_th.h:28
static void * task_run_thread(RzCoreTask *task)
Definition: task.c:348
RZ_API RZ_OWN RzThreadSemaphore * rz_th_sem_new(unsigned int initial)
Allocates and initialize a RzThreadSemaphore structure.
Definition: thread_sem.c:26
RZ_API void rz_th_sem_wait(RZ_NONNULL RzThreadSemaphore *sem)
Decrements (acquires) the semaphore (waits indefinetely)
Definition: thread_sem.c:111

References rz_list_append(), rz_th_new(), rz_th_sem_new(), rz_th_sem_wait(), task_run_thread(), TASK_SIGSET_T, rz_core_tasks_t::tasks, tasks_lock_enter(), and tasks_lock_leave().

Referenced by task_enqueue().

◆ rz_core_task_enqueue_oneshot()

RZ_API void rz_core_task_enqueue_oneshot ( RzCoreTaskScheduler scheduler,
RzCoreTaskOneShot  func,
void *  user 
)

Definition at line 391 of file task.c.

391  {
392  if (!scheduler || !func) {
393  return;
394  }
395  TASK_SIGSET_T old_sigset;
396  tasks_lock_enter(scheduler, &old_sigset);
397  if (scheduler->tasks_running == 0) {
398  // nothing is running right now and no other task can be scheduled
399  // while core->tasks_lock is locked => just run it
400  scheduler->oneshot_running = true;
401  func(user);
402  scheduler->oneshot_running = false;
403  } else {
405  if (oneshot) {
406  oneshot->func = func;
407  oneshot->user = user;
408  rz_list_append(scheduler->oneshot_queue, oneshot);
409  scheduler->oneshots_enqueued++;
410  }
411  }
412  tasks_lock_leave(scheduler, &old_sigset);
413 }
static RzBinXtrData * oneshot(RzBin *bin, const ut8 *buf, ut64 size, int subbin_type)
Definition: task.c:66
int oneshots_enqueued
Definition: rz_core.h:275
int tasks_running
Definition: rz_core.h:279
bool oneshot_running
Definition: rz_core.h:280
RzList * oneshot_queue
Definition: rz_core.h:274

References oneshot(), rz_core_tasks_t::oneshot_queue, rz_core_tasks_t::oneshot_running, rz_core_tasks_t::oneshots_enqueued, rz_list_append(), RZ_NEW, TASK_SIGSET_T, tasks_lock_enter(), tasks_lock_leave(), and rz_core_tasks_t::tasks_running.

Referenced by __do_panels_refreshOneShot(), agraph_refresh_oneshot(), rz_core_bind_cons(), rz_core_visual_analysis_refresh_oneshot(), and visual_refresh_oneshot().

◆ rz_core_task_get_incref()

RZ_API RzCoreTask* rz_core_task_get_incref ( RzCoreTaskScheduler scheduler,
int  id 
)

Definition at line 461 of file task.c.

461  {
462  TASK_SIGSET_T old_sigset;
463  tasks_lock_enter(scheduler, &old_sigset);
464  RzCoreTask *task = task_get(scheduler, id);
465  if (task) {
466  rz_core_task_incref(task);
467  }
468  tasks_lock_leave(scheduler, &old_sigset);
469  return task;
470 }
RZ_API void rz_core_task_incref(RzCoreTask *task)
Definition: task.c:190

References rz_core_task_incref(), task_get(), TASK_SIGSET_T, tasks_lock_enter(), and tasks_lock_leave().

Referenced by rz_core_task_is_cmd(), rz_core_task_join(), and task_output().

◆ rz_core_task_incref()

RZ_API void rz_core_task_incref ( RzCoreTask task)

Definition at line 190 of file task.c.

190  {
191  if (!task) {
192  return;
193  }
194  TASK_SIGSET_T old_sigset;
195  tasks_lock_enter(task->sched, &old_sigset);
196  task->refcount++;
197  tasks_lock_leave(task->sched, &old_sigset);
198 }

References TASK_SIGSET_T, tasks_lock_enter(), and tasks_lock_leave().

Referenced by rz_core_task_get_incref(), and rz_core_task_join().

◆ rz_core_task_is_cmd()

RZ_API bool rz_core_task_is_cmd ( RzCore core,
int  id 
)

Definition at line 834 of file task.c.

834  {
835  RzCoreTask *task = rz_core_task_get_incref(&core->tasks, id);
836  if (!task) {
837  return false;
838  }
839  bool r = task->runner == cmd_task_runner;
840  rz_core_task_decref(task);
841  return r;
842 }
#define r
Definition: crypto_rc6.c:12
RZ_API void rz_core_task_decref(RzCoreTask *task)
Definition: task.c:200
RZ_API RzCoreTask * rz_core_task_get_incref(RzCoreTaskScheduler *scheduler, int id)
Definition: task.c:461

References cmd_task_runner(), r, rz_core_task_decref(), rz_core_task_get_incref(), and rz_core_t::tasks.

Referenced by rz_tasks_delete_handler(), rz_tasks_wait_handler(), and task_break().

◆ rz_core_task_join()

RZ_API void rz_core_task_join ( RzCoreTaskScheduler scheduler,
RzCoreTask current,
int  id 
)

Definition at line 96 of file task.c.

96  {
97  if (current && id == current->id) {
98  return;
99  }
100  if (id >= 0) {
101  RzCoreTask *task = rz_core_task_get_incref(scheduler, id);
102  if (!task) {
103  return;
104  }
105  if (current) {
106  rz_core_task_sleep_begin(current);
107  }
108  task_join(task);
109  if (current) {
110  rz_core_task_sleep_end(current);
111  }
112  rz_core_task_decref(task);
113  } else {
114  TASK_SIGSET_T old_sigset;
115  tasks_lock_enter(scheduler, &old_sigset);
116  RzList *tasks = rz_list_clone(scheduler->tasks);
117  RzListIter *iter;
118  RzCoreTask *task;
119  rz_list_foreach (tasks, iter, task) {
120  if (current == task) {
121  continue;
122  }
123  rz_core_task_incref(task);
124  }
125  tasks_lock_leave(scheduler, &old_sigset);
126 
127  rz_list_foreach (tasks, iter, task) {
128  if (current == task) {
129  continue;
130  }
131  if (current) {
132  rz_core_task_sleep_begin(current);
133  }
134  task_join(task);
135  if (current) {
136  rz_core_task_sleep_end(current);
137  }
138  rz_core_task_decref(task);
139  }
140  rz_list_free(tasks);
141  }
142 }
RZ_API RZ_OWN RzList * rz_list_clone(RZ_NONNULL const RzList *list)
Shallow copies of the list (but doesn't free its elements)
Definition: list.c:496
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
RZ_API void rz_core_task_sleep_end(RzCoreTask *task)
Definition: task.c:442
static void task_join(RzCoreTask *task)
Definition: task.c:86
RZ_API void rz_core_task_sleep_begin(RzCoreTask *task)
Definition: task.c:438

References rz_core_task_decref(), rz_core_task_get_incref(), rz_core_task_incref(), rz_core_task_sleep_begin(), rz_core_task_sleep_end(), rz_list_clone(), rz_list_free(), task_join(), TASK_SIGSET_T, rz_core_tasks_t::tasks, tasks_lock_enter(), and tasks_lock_leave().

Referenced by rz_core_fini(), rz_main_rizin(), and rz_tasks_wait_handler().

◆ rz_core_task_list()

RZ_API void rz_core_task_list ( RzCore core,
int  mode 
)

Definition at line 811 of file task.c.

811  {
812  RzListIter *iter;
813  RzCoreTask *task;
814  PJ *j = NULL;
815  if (mode == 'j') {
816  j = pj_new();
817  pj_a(j);
818  }
819  TASK_SIGSET_T old_sigset;
820  tasks_lock_enter(&core->tasks, &old_sigset);
821  rz_list_foreach (core->tasks.tasks, iter, task) {
822  rz_core_task_print(core, task, mode, j);
823  }
824  if (j) {
825  pj_end(j);
827  pj_free(j);
828  } else {
829  rz_cons_printf("--\ntotal running: %d\n", core->tasks.tasks_running);
830  }
831  tasks_lock_leave(&core->tasks, &old_sigset);
832 }
RZ_API int rz_cons_printf(const char *format,...)
Definition: cons.c:1202
RZ_API void rz_cons_println(const char *str)
Definition: cons.c:233
const char int mode
Definition: ioapi.h:137
RZ_API PJ * pj_new(void)
Definition: pj.c:25
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API const char * pj_string(PJ *pj)
Definition: pj.c:57
RZ_API void pj_free(PJ *j)
Definition: pj.c:34
RZ_API PJ * pj_a(PJ *j)
Definition: pj.c:81
Definition: rz_pj.h:12
RZ_API void rz_core_task_print(RzCore *core, RzCoreTask *task, int mode, PJ *j)
Definition: task.c:758

References NULL, pj_a(), pj_end(), pj_free(), pj_new(), pj_string(), rz_cons_printf(), rz_cons_println(), rz_core_task_print(), TASK_SIGSET_T, rz_core_tasks_t::tasks, rz_core_t::tasks, tasks_lock_enter(), tasks_lock_leave(), and rz_core_tasks_t::tasks_running.

Referenced by rz_tasks_handler().

◆ rz_core_task_new()

RZ_API RzCoreTask* rz_core_task_new ( RzCoreTaskScheduler sched,
RzCoreTaskRunner  runner,
RzCoreTaskRunnerFree  runner_free,
void *  runner_user 
)

Definition at line 161 of file task.c.

161  {
162  RzCoreTask *task = RZ_NEW0(RzCoreTask);
163  if (!task) {
164  goto fail;
165  }
166 
167  task->sched = sched;
168  task->thread = NULL;
169  task->running_sem = NULL;
170  task->dispatched = false;
171  task->dispatch_cond = rz_th_cond_new();
172  task->dispatch_lock = rz_th_lock_new(false);
173  if (!task->dispatch_cond || !task->dispatch_lock) {
174  goto fail;
175  }
176  task->runner = runner;
177  task->runner_free = runner_free;
178  task->runner_user = runner_user;
179  task->id = sched->task_id_next++;
180  task->state = RZ_CORE_TASK_STATE_BEFORE_START;
181  task->refcount = 1;
182  task->transient = false;
183  return task;
184 
185 fail:
186  task_free(task);
187  return NULL;
188 }
#define RZ_NEW0(x)
Definition: rz_types.h:284
int task_id_next
Definition: rz_core.h:271
#define fail(test)
Definition: tests.h:29
RZ_API RZ_OWN RzThreadCond * rz_th_cond_new(void)
Condition variables are intended to be used to communicate changes in the state of data shared betwee...
Definition: thread_cond.c:13
RZ_API RZ_OWN RzThreadLock * rz_th_lock_new(bool recursive)
Allocates and initialize a RzThreadLock structure.
Definition: thread_lock.c:14

References fail, NULL, RZ_NEW0, rz_th_cond_new(), rz_th_lock_new(), task_free(), and rz_core_tasks_t::task_id_next.

Referenced by rz_core_cmd_task_new(), rz_core_function_task_new(), and rz_core_task_scheduler_init().

◆ rz_core_task_print()

RZ_API void rz_core_task_print ( RzCore core,
RzCoreTask task,
int  mode,
PJ j 
)

Definition at line 758 of file task.c.

758  {
759  rz_return_if_fail(mode != 'j' || j);
760  if (task != core->tasks.main_task && task->runner != cmd_task_runner) {
761  // don't print tasks that are custom function-runners, which come from internal code.
762  // only main and command ones, which should be user-visible.
763  return;
764  }
765  const char *cmd = NULL;
766  if (task != core->tasks.main_task) {
767  cmd = ((CmdTaskCtx *)task->runner_user)->cmd;
768  }
769  switch (mode) {
770  case 'j': {
771  pj_o(j);
772  pj_ki(j, "id", task->id);
773  const char *state;
774  // This is NOT the same as rz_core_task_status()!
775  // rz_core_task_status() is meant to be readable and may be changed.
776  // These are meant to be stable for scripting.
777  switch (task->state) {
778  case RZ_CORE_TASK_STATE_BEFORE_START:
779  state = "before_start";
780  break;
781  case RZ_CORE_TASK_STATE_RUNNING:
782  state = "running";
783  break;
784  case RZ_CORE_TASK_STATE_SLEEPING:
785  state = "sleeping";
786  break;
787  case RZ_CORE_TASK_STATE_DONE:
788  state = "done";
789  break;
790  default:
791  state = "invalid";
792  }
793  pj_ks(j, "state", state);
794  pj_kb(j, "transient", task->transient);
795  if (cmd) {
796  pj_ks(j, "cmd", cmd);
797  }
798  pj_end(j);
799  break;
800  default: {
801  rz_cons_printf("%3d %3s %12s %s\n",
802  task->id,
803  task->transient ? "(t)" : "",
804  rz_core_task_status(task),
805  cmd ? cmd : "-- MAIN TASK --");
806  } break;
807  }
808  }
809 }
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
RZ_API PJ * pj_kb(PJ *j, const char *k, bool v)
Definition: pj.c:177
RZ_API PJ * pj_ki(PJ *j, const char *k, int d)
Definition: pj.c:149
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
Definition: dis.h:43
RZ_API const char * rz_core_task_status(RzCoreTask *task)
Definition: task.c:743

References cmd, cmd_task_runner(), rz_core_tasks_t::main_task, NULL, pj_end(), pj_kb(), pj_ki(), pj_ks(), pj_o(), rz_cons_printf(), rz_core_task_status(), rz_return_if_fail, and rz_core_t::tasks.

Referenced by rz_core_task_list().

◆ rz_core_task_run_sync()

RZ_API int rz_core_task_run_sync ( RzCoreTaskScheduler scheduler,
RzCoreTask task 
)

Definition at line 415 of file task.c.

415  {
416  task->thread = NULL;
417  return task_run_thread(task) != NULL;
418 }

References NULL, and task_run_thread().

◆ rz_core_task_running_tasks_count()

RZ_API int rz_core_task_running_tasks_count ( RzCoreTaskScheduler scheduler)

Definition at line 71 of file task.c.

71  {
73  RzCoreTask *task;
74  int count = 0;
75  TASK_SIGSET_T old_sigset;
76  tasks_lock_enter(scheduler, &old_sigset);
77  rz_list_foreach (scheduler->tasks, iter, task) {
78  if (task != scheduler->main_task && task->state != RZ_CORE_TASK_STATE_DONE) {
79  count++;
80  }
81  }
82  tasks_lock_leave(scheduler, &old_sigset);
83  return count;
84 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98

References count, rz_core_tasks_t::main_task, TASK_SIGSET_T, rz_core_tasks_t::tasks, tasks_lock_enter(), and tasks_lock_leave().

Referenced by rz_main_rizin().

◆ rz_core_task_schedule()

RZ_API void rz_core_task_schedule ( RzCoreTask current,
RzTaskState  next_state 
)

Definition at line 231 of file task.c.

231  {
232  RzCoreTaskScheduler *sched = current->sched;
233  bool stop = next_state != RZ_CORE_TASK_STATE_RUNNING;
234 
235  if (sched->oneshot_running || (!stop && sched->tasks_running == 1 && sched->oneshots_enqueued == 0)) {
236  return;
237  }
238 
239  sched->current_task = NULL;
240 
241  TASK_SIGSET_T old_sigset;
242  tasks_lock_enter(sched, &old_sigset);
243 
244  current->state = next_state;
245 
246  if (stop) {
247  sched->tasks_running--;
248  }
249 
250  cleanup_transient(sched, current);
251 
252  // oneshots always have priority.
253  // if there are any queued, run them immediately.
254  OneShot *oneshot;
255  while ((oneshot = rz_list_pop_head(sched->oneshot_queue))) {
256  sched->oneshots_enqueued--;
257  sched->oneshot_running = true;
258  oneshot->func(oneshot->user);
259  sched->oneshot_running = false;
260  free(oneshot);
261  }
262 
263  RzCoreTask *next = rz_list_pop_head(sched->tasks_queue);
264 
265  if (next && !stop) {
266  rz_list_append(sched->tasks_queue, current);
267  rz_th_lock_enter(current->dispatch_lock);
268  }
269 
270  tasks_lock_leave(sched, &old_sigset);
271 
272  if (next) {
273  rz_th_lock_enter(next->dispatch_lock);
274  next->dispatched = true;
275  rz_th_lock_leave(next->dispatch_lock);
276  rz_th_cond_signal(next->dispatch_cond);
277  if (!stop) {
278  while (!current->dispatched) {
279  rz_th_cond_wait(current->dispatch_cond, current->dispatch_lock);
280  }
281  current->dispatched = false;
282  rz_th_lock_leave(current->dispatch_lock);
283 
284  tasks_lock_enter(sched, &old_sigset);
285  cleanup_transient(sched, current);
286  tasks_lock_leave(sched, &old_sigset);
287  }
288  }
289 
290  if (!stop) {
291  sched->current_task = current;
292  if (sched->ctx_switch) {
293  sched->ctx_switch(current, sched->ctx_switch_user);
294  }
295  }
296 }
RZ_API RZ_OWN void * rz_list_pop_head(RZ_NONNULL RzList *list)
Removes and returns the first element of the list.
Definition: list.c:401
RzList * tasks_queue
Definition: rz_core.h:273
RzCoreTaskContextSwitch ctx_switch
Definition: rz_core.h:267
void * ctx_switch_user
Definition: rz_core.h:268
struct rz_core_task_t * current_task
Definition: rz_core.h:276
static void cleanup_transient(RzCoreTaskScheduler *sched, RzCoreTask *exclude)
Definition: task.c:217
RZ_API void rz_th_cond_signal(RZ_NONNULL RzThreadCond *cond)
This function shall unblock at least one of the threads that are blocked on the specified condition.
Definition: thread_cond.c:34
RZ_API void rz_th_cond_wait(RZ_NONNULL RzThreadCond *cond, RZ_NONNULL RzThreadLock *lock)
The function shall block on a condition variable and shall be called with RzThreadLock locked by the ...
Definition: thread_cond.c:63
RZ_API void rz_th_lock_leave(RZ_NONNULL RzThreadLock *thl)
Releases a RzThreadLock structure.
Definition: thread_lock.c:75
RZ_API void rz_th_lock_enter(RZ_NONNULL RzThreadLock *thl)
Acquires a RzThreadLock structure.
Definition: thread_lock.c:45

References cleanup_transient(), rz_core_tasks_t::ctx_switch, rz_core_tasks_t::ctx_switch_user, rz_core_tasks_t::current_task, free(), NULL, oneshot(), rz_core_tasks_t::oneshot_queue, rz_core_tasks_t::oneshot_running, rz_core_tasks_t::oneshots_enqueued, rz_list_append(), rz_list_pop_head(), rz_th_cond_signal(), rz_th_cond_wait(), rz_th_lock_enter(), rz_th_lock_leave(), TASK_SIGSET_T, tasks_lock_enter(), tasks_lock_leave(), rz_core_tasks_t::tasks_queue, and rz_core_tasks_t::tasks_running.

Referenced by rz_core_task_sleep_begin(), rz_core_task_yield(), and task_end().

◆ rz_core_task_scheduler_fini()

RZ_API void rz_core_task_scheduler_fini ( RzCoreTaskScheduler tasks)

Definition at line 27 of file task.c.

27  {
28  rz_list_free(tasks->tasks);
29  rz_list_free(tasks->tasks_queue);
31  rz_th_lock_free(tasks->lock);
32 }
RzThreadLock * lock
Definition: rz_core.h:278
RZ_API void rz_th_lock_free(RZ_NULLABLE RzThreadLock *thl)
Frees a RzThreadLock structure.
Definition: thread_lock.c:89

References rz_core_tasks_t::lock, rz_core_tasks_t::oneshot_queue, rz_list_free(), rz_th_lock_free(), rz_core_tasks_t::tasks, and rz_core_tasks_t::tasks_queue.

Referenced by rz_core_fini().

◆ rz_core_task_scheduler_init()

RZ_API void rz_core_task_scheduler_init ( RzCoreTaskScheduler sched,
RzCoreTaskContextSwitch  ctx_switch,
void *  ctx_switch_user,
RzCoreTaskBreak  break_cb,
void *  break_cb_user 
)

Definition at line 7 of file task.c.

9  {
10  sched->ctx_switch = ctx_switch;
11  sched->ctx_switch_user = ctx_switch_user;
12  sched->break_cb = break_cb;
13  sched->break_cb_user = break_cb_user;
14  sched->task_id_next = 0;
16  sched->tasks_queue = rz_list_new();
18  sched->oneshots_enqueued = 0;
19  sched->lock = rz_th_lock_new(true);
20  sched->tasks_running = 0;
21  sched->oneshot_running = false;
22  sched->main_task = rz_core_task_new(sched, NULL, NULL, NULL);
23  rz_list_append(sched->tasks, sched->main_task);
24  sched->current_task = NULL;
25 }
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
RzCoreTaskBreak break_cb
Definition: rz_core.h:269
void * break_cb_user
Definition: rz_core.h:270

References rz_core_tasks_t::break_cb, rz_core_tasks_t::break_cb_user, rz_core_tasks_t::ctx_switch, rz_core_tasks_t::ctx_switch_user, rz_core_tasks_t::current_task, free(), rz_core_tasks_t::lock, rz_core_tasks_t::main_task, NULL, rz_core_tasks_t::oneshot_queue, rz_core_tasks_t::oneshot_running, rz_core_tasks_t::oneshots_enqueued, rz_core_task_decref(), rz_core_task_new(), rz_list_append(), rz_list_new(), rz_list_newf(), rz_th_lock_new(), rz_core_tasks_t::task_id_next, rz_core_tasks_t::tasks, rz_core_tasks_t::tasks_queue, and rz_core_tasks_t::tasks_running.

Referenced by rz_core_init().

◆ rz_core_task_self()

RZ_API RzCoreTask* rz_core_task_self ( RzCoreTaskScheduler scheduler)

Definition at line 446 of file task.c.

446  {
447  return scheduler->current_task ? scheduler->current_task : scheduler->main_task;
448 }

References rz_core_tasks_t::current_task, and rz_core_tasks_t::main_task.

Referenced by cmd_task_runner(), rz_core_sleep_begin(), and rz_core_task_yield().

◆ rz_core_task_sleep_begin()

RZ_API void rz_core_task_sleep_begin ( RzCoreTask task)

Definition at line 438 of file task.c.

438  {
439  rz_core_task_schedule(task, RZ_CORE_TASK_STATE_SLEEPING);
440 }
RZ_API void rz_core_task_schedule(RzCoreTask *current, RzTaskState next_state)
Definition: task.c:231

References rz_core_task_schedule().

Referenced by rz_core_sleep_begin(), and rz_core_task_join().

◆ rz_core_task_sleep_end()

RZ_API void rz_core_task_sleep_end ( RzCoreTask task)

Definition at line 442 of file task.c.

442  {
443  task_wakeup(task);
444 }
static void task_wakeup(RzCoreTask *current)
Definition: task.c:298

References task_wakeup().

Referenced by rz_core_sleep_end(), and rz_core_task_join().

◆ rz_core_task_status()

RZ_API const char* rz_core_task_status ( RzCoreTask task)

Definition at line 743 of file task.c.

743  {
744  switch (task->state) {
745  case RZ_CORE_TASK_STATE_RUNNING:
746  return "running";
747  case RZ_CORE_TASK_STATE_SLEEPING:
748  return "sleeping";
749  case RZ_CORE_TASK_STATE_DONE:
750  return "done";
751  case RZ_CORE_TASK_STATE_BEFORE_START:
752  return "before start";
753  default:
754  return "unknown";
755  }
756 }

Referenced by rz_core_task_print().

◆ rz_core_task_sync_begin()

RZ_API void rz_core_task_sync_begin ( RzCoreTaskScheduler scheduler)

Definition at line 421 of file task.c.

421  {
422  RzCoreTask *task = scheduler->main_task;
423  TASK_SIGSET_T old_sigset;
424  tasks_lock_enter(scheduler, &old_sigset);
425  task->thread = NULL;
426  task->state = RZ_CORE_TASK_STATE_BEFORE_START;
427  tasks_lock_leave(scheduler, &old_sigset);
428  task_wakeup(task);
429 }

References rz_core_tasks_t::main_task, NULL, TASK_SIGSET_T, task_wakeup(), tasks_lock_enter(), and tasks_lock_leave().

Referenced by open_core_file(), and rz_main_rizin().

◆ rz_core_task_sync_end()

RZ_API void rz_core_task_sync_end ( RzCoreTaskScheduler scheduler)

Definition at line 432 of file task.c.

432  {
433  task_end(scheduler->main_task);
434 }
static void task_end(RzCoreTask *t)
Definition: task.c:344

References rz_core_tasks_t::main_task, and task_end().

Referenced by open_core_file(), and rz_main_rizin().

◆ rz_core_task_yield()

RZ_API void rz_core_task_yield ( RzCoreTaskScheduler scheduler)

Definition at line 336 of file task.c.

336  {
337  RzCoreTask *task = rz_core_task_self(scheduler);
338  if (!task) {
339  return;
340  }
341  rz_core_task_schedule(task, RZ_CORE_TASK_STATE_RUNNING);
342 }

References rz_core_task_schedule(), and rz_core_task_self().

Referenced by core_perform_auto_analysis(), DEFINE_HANDLE_TS_FCN(), DEFINE_HANDLE_TS_FCN_AND_SYMBOL(), rz_core_analysis_all(), rz_core_analysis_everything(), and rz_core_cmd_foreach().

◆ task_break()

static void task_break ( RzCoreTask task)
static

break without locking, don't call directly and use public api instead!

Definition at line 475 of file task.c.

475  {
476  RzCoreTaskScheduler *sched = task->sched;
477  task->breaked = true;
478  if (sched->break_cb) {
479  sched->break_cb(task, sched->break_cb_user);
480  }
481 }

References rz_core_tasks_t::break_cb, and rz_core_tasks_t::break_cb_user.

Referenced by rz_core_task_break(), and rz_core_task_break_all().

◆ task_end()

static void task_end ( RzCoreTask t)
static

Definition at line 344 of file task.c.

344  {
345  rz_core_task_schedule(t, RZ_CORE_TASK_STATE_DONE);
346 }

References rz_core_task_schedule().

Referenced by rz_core_task_sync_end(), and task_run_thread().

◆ task_free()

static void task_free ( RzCoreTask task)
static

Definition at line 144 of file task.c.

144  {
145  if (!task) {
146  return;
147  }
148  if (task->runner_free) {
149  task->runner_free(task->runner_user);
150  }
151  if (task->thread) {
152  rz_th_wait(task->thread);
153  rz_th_free(task->thread);
154  }
155  rz_th_sem_free(task->running_sem);
156  rz_th_cond_free(task->dispatch_cond);
157  rz_th_lock_free(task->dispatch_lock);
158  free(task);
159 }
RZ_API void rz_th_free(RZ_NULLABLE RzThread *th)
Frees a RzThread structure.
Definition: thread.c:246
RZ_API bool rz_th_wait(RZ_NONNULL RzThread *th)
Awaits indefinetely for a thread to join.
Definition: thread.c:231
RZ_API void rz_th_cond_free(RZ_NULLABLE RzThreadCond *cond)
Frees a RzThreadCond struct.
Definition: thread_cond.c:77
RZ_API void rz_th_sem_free(RZ_NULLABLE RzThreadSemaphore *sem)
Frees a RzThreadSemaphore struct.
Definition: thread_sem.c:73

References free(), rz_th_cond_free(), rz_th_free(), rz_th_lock_free(), rz_th_sem_free(), and rz_th_wait().

Referenced by rz_core_task_decref(), and rz_core_task_new().

◆ task_get()

static RzCoreTask* task_get ( RzCoreTaskScheduler scheduler,
int  id 
)
static

Definition at line 450 of file task.c.

450  {
451  RzCoreTask *task;
452  RzListIter *iter;
453  rz_list_foreach (scheduler->tasks, iter, task) {
454  if (task->id == id) {
455  return task;
456  }
457  }
458  return NULL;
459 }

References NULL, and rz_core_tasks_t::tasks.

Referenced by rz_core_task_break(), and rz_core_task_get_incref().

◆ task_join()

static void task_join ( RzCoreTask task)
static

Definition at line 86 of file task.c.

86  {
87  RzThreadSemaphore *sem = task->running_sem;
88  if (!sem) {
89  return;
90  }
91 
92  rz_th_sem_wait(sem);
93  rz_th_sem_post(sem);
94 }
RZ_API void rz_th_sem_post(RZ_NONNULL RzThreadSemaphore *sem)
increments (releases) a semaphore
Definition: thread_sem.c:97

References rz_th_sem_post(), and rz_th_sem_wait().

Referenced by rz_core_task_join().

◆ task_run_thread()

static void* task_run_thread ( RzCoreTask task)
static

Definition at line 348 of file task.c.

348  {
349  RzCoreTaskScheduler *sched = task->sched;
350 
351  task_wakeup(task);
352 
353  if (task->breaked) {
354  // breaked in RZ_CORE_TASK_STATE_BEFORE_START
355  goto nonstart;
356  }
357 
358  task->runner(sched, task->runner_user);
359 
360  TASK_SIGSET_T old_sigset;
361 nonstart:
362  tasks_lock_enter(sched, &old_sigset);
363 
364  task_end(task);
365 
366  if (task->running_sem) {
367  rz_th_sem_post(task->running_sem);
368  }
369 
370  tasks_lock_leave(sched, &old_sigset);
371  return NULL;
372 }

References NULL, rz_th_sem_post(), task_end(), TASK_SIGSET_T, task_wakeup(), tasks_lock_enter(), and tasks_lock_leave().

Referenced by rz_core_task_enqueue(), and rz_core_task_run_sync().

◆ task_wakeup()

static void task_wakeup ( RzCoreTask current)
static

Definition at line 298 of file task.c.

298  {
299  RzCoreTaskScheduler *sched = current->sched;
300 
301  TASK_SIGSET_T old_sigset;
302  tasks_lock_enter(sched, &old_sigset);
303 
304  sched->tasks_running++;
305  current->state = RZ_CORE_TASK_STATE_RUNNING;
306 
307  // check if there are other tasks running
308  bool single = sched->tasks_running == 1 || sched->tasks_running == 0;
309 
310  rz_th_lock_enter(current->dispatch_lock);
311 
312  // if we are not the only task, we must wait until another task signals us.
313 
314  if (!single) {
315  rz_list_append(sched->tasks_queue, current);
316  }
317 
318  tasks_lock_leave(sched, &old_sigset);
319 
320  if (!single) {
321  while (!current->dispatched) {
322  rz_th_cond_wait(current->dispatch_cond, current->dispatch_lock);
323  }
324  current->dispatched = false;
325  }
326 
327  rz_th_lock_leave(current->dispatch_lock);
328 
329  sched->current_task = current;
330 
331  if (sched->ctx_switch) {
332  sched->ctx_switch(current, sched->ctx_switch_user);
333  }
334 }

References rz_core_tasks_t::ctx_switch, rz_core_tasks_t::ctx_switch_user, rz_core_tasks_t::current_task, rz_list_append(), rz_th_cond_wait(), rz_th_lock_enter(), rz_th_lock_leave(), TASK_SIGSET_T, tasks_lock_enter(), tasks_lock_leave(), rz_core_tasks_t::tasks_queue, and rz_core_tasks_t::tasks_running.

Referenced by rz_core_task_sleep_end(), rz_core_task_sync_begin(), and task_run_thread().

◆ tasks_lock_block_signals()

static void tasks_lock_block_signals ( TASK_SIGSET_T old_sigset)
static

Definition at line 48 of file task.c.

48  {
49  (void)old_sigset;
50 }

Referenced by tasks_lock_enter().

◆ tasks_lock_block_signals_reset()

static void tasks_lock_block_signals_reset ( TASK_SIGSET_T old_sigset)
static

Definition at line 51 of file task.c.

51  {
52  (void)old_sigset;
53 }

Referenced by tasks_lock_leave().

◆ tasks_lock_enter()

◆ tasks_lock_leave()