voron

experimental ARM OS
git clone git://git.2f30.org/voron
Log | Files | Refs | README | LICENSE

commit 44c6403f317da166dfc0621e7e6a42bb16a2178d
parent b45fc0f1a2f75f53f7f82ff64c313ee6c757a5d0
Author: oblique <psyberbits@gmail.com>
Date:   Tue, 13 Nov 2012 07:07:34 +0200

add sched_disable(), sched_enable(), sched_is_enabled()

Diffstat:
Minclude/sched.h | 3+++
Mkernel/sched.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
2 files changed, 59 insertions(+), 27 deletions(-)

diff --git a/include/sched.h b/include/sched.h @@ -49,6 +49,9 @@ void sleep(u32 seconds); void msleep(u32 milliseconds); int kthread_create(void (*routine)(void *), void *arg); void schedule(void); +void sched_disable(); +void sched_enable(); +int sched_is_enabled(); void suspend_task(u32 channel); void suspend_task_no_schedule(u32 channel); void resume_tasks(u32 channel); diff --git a/kernel/sched.c b/kernel/sched.c @@ -12,6 +12,7 @@ struct task_struct *curr_task = NULL; static struct list_head task_list_head; static struct list_head ht_sleep[MAX_HASH_ENT]; static uatomic_t ms_counter = UATOMIC_INIT(0); +static int __sched_enabled = 0; static pid_t get_new_pid(void) @@ -36,7 +37,6 @@ static void task_remove(void) { current->state = TASK_TERMINATE; - /* force schedule */ schedule(); } @@ -74,18 +74,16 @@ kthread_create(void (*routine)(void *), void *arg) task->regs.cpsr = CPS_SYS; /* add it to task list of the scheduler */ - irq_disable(); - list_add(&task->list, &task_list_head); - irq_enable(); - - /* force schedule if it's the only task */ - if (list_is_singular(&task_list_head)) - schedule(); + if (sched_is_enabled()) { + sched_disable(); + list_add(&task->list, &task_list_head); + sched_enable(); + } else + list_add(&task->list, &task_list_head); return 0; } -/* force schedule */ void schedule(void) { @@ -187,26 +185,52 @@ sched(struct regs *regs) __switch_to(regs, new_curr); } + void -suspend_task(u32 channel) +sched_enable() +{ + u32 flags = irq_get_flags(); + irq_disable(); + writel(1, &__sched_enabled); + irq_set_flags(flags); +} + +void +sched_disable() { + u32 flags = irq_get_flags(); irq_disable(); + writel(0, &__sched_enabled); + irq_set_flags(flags); +} + +int +sched_is_enabled() +{ + return readl(&__sched_enabled); +} + +void +suspend_task(u32 channel) +{ + sched_disable(); current->sleep_chan = channel; current->sleep_reason = SLEEPR_SUSPEND; current->state = TASK_SLEEPING; - irq_enable(); + sched_enable(); schedule(); } void suspend_task_no_schedule(u32 channel) { - irq_disable(); + /* caller *must* call sched_disable() + * before this function */ current->sleep_chan = channel; current->sleep_reason = SLEEPR_SUSPEND; current->state = TASK_SLEEPING; - irq_enable(); - /* caller *must* run schedule() */ + /* caller *must* call sched_enable() + * and then schedule() after this function */ } void @@ -214,17 +238,20 @@ resume_tasks(u32 channel) { struct list_head *iter, *n; struct task_struct *task; - int i; + int i, sched_e; i = hash_chan(channel) % MAX_HASH_ENT; list_for_each_safe(iter, n, &ht_sleep[i]) { task = list_entry(iter, struct task_struct, list); if (task->sleep_chan == channel) { task->state = TASK_RUNNABLE; - irq_disable(); + sched_e = sched_is_enabled(); + if (sched_e) + sched_disable(); list_del(iter); list_add(iter, &task_list_head); - irq_enable(); + if (sched_e) + sched_enable(); } } } @@ -232,19 +259,19 @@ resume_tasks(u32 channel) void sleep(u32 seconds) { - irq_disable(); + sched_disable(); current->wakeup_ms = uatomic_read(&ms_counter) + seconds * 1000; current->sleep_reason = SLEEPR_SLEEP; current->state = TASK_SLEEPING; - irq_enable(); - /* force schedule */ + sched_enable(); + /* schedule */ schedule(); } void msleep(u32 milliseconds) { - irq_disable(); + sched_disable(); /* TODO: if ms is smaller than SCHED_INT_MS * do a loop and don't schedule */ if (milliseconds < SCHED_INT_MS) @@ -252,8 +279,7 @@ msleep(u32 milliseconds) current->wakeup_ms = uatomic_read(&ms_counter) + milliseconds; current->sleep_reason = SLEEPR_SLEEP; current->state = TASK_SLEEPING; - irq_enable(); - /* force schedule */ + sched_enable(); schedule(); } @@ -261,13 +287,15 @@ static void sched_handler(__unused int timer_id, struct regs *regs) { uatomic_add(SCHED_INT_MS, &ms_counter); - sched(regs); + if (sched_is_enabled()) + sched(regs); } static void -force_sched_handler(__unused u32 irq_num, struct regs *regs) +manual_sched_handler(__unused u32 irq_num, struct regs *regs) { - sched(regs); + if (sched_is_enabled()) + sched(regs); } __attribute__((__constructor__)) @@ -280,6 +308,7 @@ sched_init(void) for (i = 0; i < ARRAY_SIZE(ht_sleep); i++) INIT_LIST_HEAD(&ht_sleep[i]); - irq_register(1, force_sched_handler); + irq_register(1, manual_sched_handler); dmtimer_register(1, sched_handler, SCHED_INT_MS); + sched_enable(); }