diff --git a/common/sched.c b/common/sched.c
index 4d8fa50f..6a5bc6cc 100644
--- a/common/sched.c
+++ b/common/sched.c
@@ -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;
 }
@@ -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);
 
@@ -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);
@@ -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)
@@ -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;
 
@@ -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);
diff --git a/include/sched.h b/include/sched.h
index 2e4af358..86438ead 100644
--- a/include/sched.h
+++ b/include/sched.h
@@ -59,6 +59,11 @@ 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;
 
@@ -66,6 +71,8 @@ struct task {
     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;
@@ -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 */
diff --git a/tests/unittests.c b/tests/unittests.c
index fd8ab052..0b40974f 100644
--- a/tests/unittests.c
+++ b/tests/unittests.c
@@ -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());