Skip to content

Commit 83cc25c

Browse files
committed
sched: add task repetition functionality
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 <wipawel@grsecurity.net>
1 parent 3be17e6 commit 83cc25c

3 files changed

Lines changed: 61 additions & 6 deletions

File tree

common/sched.c

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ static task_t *create_task(void) {
8787
task->id = next_tid++;
8888
task->gid = TASK_GROUP_ALL;
8989
set_task_state(task, TASK_STATE_NEW);
90+
atomic_set(&task->exec_count, 0);
91+
set_task_once(task);
9092

9193
return task;
9294
}
@@ -155,6 +157,20 @@ task_t *get_task_by_name(cpu_t *cpu, const char *name) {
155157
return NULL;
156158
}
157159

160+
static const char *task_repeat_string(task_repeat_t repeat) {
161+
static char buf[20] = {0};
162+
163+
switch (repeat) {
164+
case TASK_REPEAT_ONCE:
165+
return "ONCE";
166+
case TASK_REPEAT_LOOP:
167+
return "LOOP";
168+
default:
169+
snprintf(buf, sizeof(buf), "%u times", repeat);
170+
return buf;
171+
}
172+
}
173+
158174
int schedule_task(task_t *task, cpu_t *cpu) {
159175
ASSERT(task);
160176

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

166182
BUG_ON(get_task_state(task) != TASK_STATE_READY);
167183

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

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

183200
wait_for_task_state(task, TASK_STATE_SCHEDULED);
184201

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

187205
set_task_state(task, TASK_STATE_RUNNING);
188206
if (task->type == TASK_TYPE_USER)
@@ -214,6 +232,24 @@ void wait_for_task_group(const cpu_t *cpu, task_group_t group) {
214232
} while (busy);
215233
}
216234

235+
void process_task_repeat(task_t *task) {
236+
switch (task->repeat) {
237+
case TASK_REPEAT_ONCE:
238+
printk("%s task '%s' finished on CPU[%u] with result %ld (Run: %lu times)\n",
239+
task->type == TASK_TYPE_KERNEL ? "Kernel" : "User", task->name,
240+
task->cpu->id, task->result, atomic_read(&task->exec_count));
241+
destroy_task(task);
242+
break;
243+
case TASK_REPEAT_LOOP:
244+
set_task_state(task, TASK_STATE_SCHEDULED);
245+
break;
246+
default:
247+
task->repeat--;
248+
set_task_state(task, TASK_STATE_SCHEDULED);
249+
break;
250+
}
251+
}
252+
217253
void run_tasks(cpu_t *cpu) {
218254
task_t *task, *safe;
219255

@@ -225,10 +261,7 @@ void run_tasks(cpu_t *cpu) {
225261
list_for_each_entry_safe (task, safe, &cpu->task_queue, list) {
226262
switch (task->state) {
227263
case TASK_STATE_DONE:
228-
printk("%s task '%s' finished on CPU[%u] with result %ld\n",
229-
task->type == TASK_TYPE_KERNEL ? "Kernel" : "User", task->name,
230-
cpu->id, task->result);
231-
destroy_task(task);
264+
process_task_repeat(task);
232265
break;
233266
case TASK_STATE_SCHEDULED:
234267
run_task(task);

include/sched.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,20 @@ typedef enum task_type task_type_t;
5959

6060
typedef unsigned int tid_t;
6161

62+
typedef enum task_repeat {
63+
TASK_REPEAT_LOOP = 0,
64+
TASK_REPEAT_ONCE = 1,
65+
} task_repeat_t;
66+
6267
struct task {
6368
list_head_t list;
6469

6570
tid_t id;
6671
task_type_t type;
6772
task_group_t gid;
6873
task_state_t state;
74+
task_repeat_t repeat;
75+
atomic64_t exec_count;
6976

7077
cpu_t *cpu;
7178
void *stack;
@@ -110,4 +117,18 @@ static inline void execute_tasks(void) {
110117
run_tasks(get_bsp_cpu());
111118
wait_for_all_cpus();
112119
}
120+
121+
static inline void set_task_repeat(task_t *task, task_repeat_t value) {
122+
ASSERT(task);
123+
task->repeat = value;
124+
}
125+
126+
static inline void set_task_loop(task_t *task) {
127+
set_task_repeat(task, TASK_REPEAT_LOOP);
128+
}
129+
130+
static inline void set_task_once(task_t *task) {
131+
set_task_repeat(task, TASK_REPEAT_ONCE);
132+
}
133+
113134
#endif /* KTF_SCHED_H */

tests/unittests.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ int unit_tests(void *_unused) {
169169
task_user1 = new_user_task("test1 user", test_user_task_func1, NULL);
170170
task_user2 = new_user_task("test2 user", test_user_task_func2, NULL);
171171

172+
set_task_repeat(task1, 10);
172173
schedule_task(task1, get_bsp_cpu());
173174
schedule_task(task2, get_cpu(1));
174175
schedule_task(task_user1, get_bsp_cpu());

0 commit comments

Comments
 (0)