kern/kernel/sched.c
fef 5a5135f416
update license terms
As of now, everything except the code imported
from FreeBSD is proprietary.  Of course, it won't
be like this for long, only until we have decided
which license we like to use.  The rationale is
that releasing everything under a copyleft license
later is always easier than doing so immediately
and then changing it afterwards.
Naturally, any changes made before this commit are
still subject to the terms of the CNPL.
2021-11-15 19:23:22 +01:00

101 lines
2.5 KiB
C

/* Copyright (C) 2021 fef <owo@fef.moe>. All rights reserved. */
#include <arch/cpufunc.h>
#include <arch/sched.h>
#include <gay/clist.h>
#include <gay/sched.h>
#include <gay/types.h>
struct task kernel_task = {
.parent = nil,
.pid = 0,
.state = TASK_READY,
.critnest = 0,
};
struct task *current_array[CFG_MAX_CPU] = {
&kernel_task,
};
/*
* Two run queues, one active and one inactive. The scheduler takes tasks out
* of the active queue, runs them if possible, and then puts them into the
* inactive queue if they aren't dead. When the active queue gets empty, the
* queues are switched and everything starts over again.
* The `current` task is always in neither queue.
*/
static struct clist _run_queues[2];
static struct clist *active_queue = &_run_queues[0];
static struct clist *inactive_queue = &_run_queues[1];
int sched_init(void)
{
clist_init(active_queue);
clist_init(inactive_queue);
return 0;
}
void schedule(void)
{
struct task *old = current;
struct task *new = nil;
if (old->critnest)
return;
clist_add(inactive_queue, &old->run_queue);
/* Dijkstra would be so mad if he saw this */
try_again:
if (clist_is_empty(active_queue)) {
struct clist *tmp = active_queue;
active_queue = inactive_queue;
inactive_queue = tmp;
}
struct task *cursor, *tmp;
clist_foreach_entry_safe(active_queue, cursor, tmp, run_queue) {
clist_del(&cursor->run_queue);
if (cursor->state == TASK_READY) {
new = cursor;
break;
} else if (cursor->state == TASK_BLOCKED) {
clist_add(inactive_queue, &cursor->run_queue);
}
}
/*
* This should really make the CPU go idle rather than constantly
* looping around until some event occurs, but i have no idea how to do
* that (yet)
*/
if (new == nil)
goto try_again;
if (new != old)
switch_to(new, old);
}
void switch_to(struct task *new, struct task *old)
{
disable_intr();
set_current(new);
arch_switch_to(&new->tcb, &old->tcb);
set_current(old);
enable_intr();
}
/*
* This file is part of GayBSD.
* Copyright (c) 2021 fef <owo@fef.moe>.
*
* GayBSD is nonviolent software: you may only use, redistribute, and/or
* modify it under the terms of the Cooperative Nonviolent Public License
* (CNPL) as found in the LICENSE file in the source code root directory
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
* of the license, or (at your option) any later version.
*
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPL for details.
*/