Skip to content

Commit

Permalink
sched: add task repetition functionality
Browse files Browse the repository at this point in the history
By default tasks run once and get destroyed. It might be useful to run
them in an infinite loop (task done -> task scheduled -> ...) in order
to achieve tasks interleaving (multiple tasks scheduled on the same
CPU).
It might be also useful to set an arbitrary value of repetitions for a
given task.

This commit adds simple set_task_repeat() and set_task_loop() API to
allow task repetitions.

Signed-off-by: Pawel Wieczorkiewicz <[email protected]>
  • Loading branch information
wipawel committed Aug 21, 2023
1 parent 3be17e6 commit 810ad44
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 6 deletions.
45 changes: 39 additions & 6 deletions common/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ static task_t *create_task(void) {
task->id = next_tid++;
task->gid = TASK_GROUP_ALL;
set_task_state(task, TASK_STATE_NEW);
atomic_set(&task->exec_count, 0);
set_task_once(task);

return task;
}
Expand Down Expand Up @@ -155,6 +157,20 @@ task_t *get_task_by_name(cpu_t *cpu, const char *name) {
return NULL;
}

static const char *task_repeat_string(task_repeat_t repeat) {
static char buf[20] = {0};

switch (repeat) {
case TASK_REPEAT_ONCE:
return "ONCE";
case TASK_REPEAT_LOOP:
return "LOOP";
default:
snprintf(buf, sizeof(buf), "%u times", repeat);
return buf;
}
}

int schedule_task(task_t *task, cpu_t *cpu) {
ASSERT(task);

Expand All @@ -165,7 +181,8 @@ int schedule_task(task_t *task, cpu_t *cpu) {

BUG_ON(get_task_state(task) != TASK_STATE_READY);

printk("CPU[%u]: Scheduling task %s[%u]\n", cpu->id, task->name, task->id);
printk("CPU[%u]: Scheduling task %s[%u] (%s)\n", cpu->id, task->name, task->id,
task_repeat_string(task->repeat));

spin_lock(&cpu->lock);
list_add_tail(&task->list, &cpu->task_queue);
Expand All @@ -182,7 +199,8 @@ static void run_task(task_t *task) {

wait_for_task_state(task, TASK_STATE_SCHEDULED);

printk("CPU[%u]: Running task %s[%u]\n", task->cpu->id, task->name, task->id);
if (atomic64_inc_return(&task->exec_count) == 0)
printk("CPU[%u]: Running task %s[%u]\n", task->cpu->id, task->name, task->id);

set_task_state(task, TASK_STATE_RUNNING);
if (task->type == TASK_TYPE_USER)
Expand Down Expand Up @@ -214,6 +232,24 @@ void wait_for_task_group(const cpu_t *cpu, task_group_t group) {
} while (busy);
}

void process_task_repeat(task_t *task) {
switch (task->repeat) {
case TASK_REPEAT_ONCE:
printk("%s task '%s' finished on CPU[%u] with result %ld (Run: %lu times)\n",
task->type == TASK_TYPE_KERNEL ? "Kernel" : "User", task->name,
task->cpu->id, task->result, atomic_read(&task->exec_count));
destroy_task(task);
break;
case TASK_REPEAT_LOOP:
set_task_state(task, TASK_STATE_SCHEDULED);
break;
default:
task->repeat--;
set_task_state(task, TASK_STATE_SCHEDULED);
break;
}
}

void run_tasks(cpu_t *cpu) {
task_t *task, *safe;

Expand All @@ -225,10 +261,7 @@ void run_tasks(cpu_t *cpu) {
list_for_each_entry_safe (task, safe, &cpu->task_queue, list) {
switch (task->state) {
case TASK_STATE_DONE:
printk("%s task '%s' finished on CPU[%u] with result %ld\n",
task->type == TASK_TYPE_KERNEL ? "Kernel" : "User", task->name,
cpu->id, task->result);
destroy_task(task);
process_task_repeat(task);
break;
case TASK_STATE_SCHEDULED:
run_task(task);
Expand Down
21 changes: 21 additions & 0 deletions include/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,20 @@ typedef enum task_type task_type_t;

typedef unsigned int tid_t;

typedef enum task_repeat {
TASK_REPEAT_LOOP = 0,
TASK_REPEAT_ONCE = 1,
} task_repeat_t;

struct task {
list_head_t list;

tid_t id;
task_type_t type;
task_group_t gid;
task_state_t state;
task_repeat_t repeat;
atomic64_t exec_count;

cpu_t *cpu;
void *stack;
Expand Down Expand Up @@ -110,4 +117,18 @@ static inline void execute_tasks(void) {
run_tasks(get_bsp_cpu());
wait_for_all_cpus();
}

static inline void set_task_repeat(task_t *task, task_repeat_t value) {
ASSERT(task);
task->repeat = value;
}

static inline void set_task_loop(task_t *task) {
set_task_repeat(task, TASK_REPEAT_LOOP);
}

static inline void set_task_once(task_t *task) {
set_task_repeat(task, TASK_REPEAT_ONCE);
}

#endif /* KTF_SCHED_H */
1 change: 1 addition & 0 deletions tests/unittests.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ int unit_tests(void *_unused) {
task_user1 = new_user_task("test1 user", test_user_task_func1, NULL);
task_user2 = new_user_task("test2 user", test_user_task_func2, NULL);

set_task_repeat(task1, 10);
schedule_task(task1, get_bsp_cpu());
schedule_task(task2, get_cpu(1));
schedule_task(task_user1, get_bsp_cpu());
Expand Down

0 comments on commit 810ad44

Please sign in to comment.