calcite/src/kernel/scheduler.c
2026-01-06 13:04:05 -05:00

100 lines
2.9 KiB
C

/* Calcite, src/kernel/scheduler.c
* Copyright 2025-2026 Benji Dial
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "scheduler.h"
#include "process.h"
#include "utility.h"
#include "debug.h"
#include "heap.h"
struct continuation_queue ready_continuations;
void init_scheduler() {
create_queue(&ready_continuations, 128);
}
//defined in scheduler.asm
[[noreturn]] void resume_continuation(const struct continuation_info *info);
[[noreturn]] void resume_next_continuation() {
running_thread = 0;
struct continuation_info ci;
while (!take_from_queue(&ready_continuations, &ci)) {
__asm__ ("sti");
__asm__ ("hlt");
__asm__ ("cli");
}
assert(running_thread == 0)
assert(ci.running_thread != 0)
resume_continuation(&ci);
}
void create_queue(struct continuation_queue *queue, int buffer_size) {
queue->cis = heap_alloc(buffer_size * sizeof(struct continuation_info));
queue->next_read_index = 0;
queue->buffer_size = buffer_size;
queue->count = 0;
}
void destroy_queue(struct continuation_queue *queue) {
assert(queue->count == 0)
heap_dealloc(queue->cis, queue->buffer_size * sizeof(struct continuation_info));
}
void add_to_queue(struct continuation_queue *queue, struct continuation_info *ci) {
if (queue->count == queue->buffer_size) {
struct continuation_info *new_buffer =
heap_alloc(2 * queue->buffer_size * sizeof(struct continuation_info));
memcpy(
new_buffer, &queue->cis[queue->next_read_index],
(queue->buffer_size - queue->next_read_index) * sizeof(struct continuation_info));
memcpy(
&new_buffer[queue->buffer_size - queue->next_read_index],
queue->cis, queue->next_read_index * sizeof(struct continuation_info));
heap_dealloc(queue->cis, queue->buffer_size * sizeof(struct continuation_info));
queue->cis = new_buffer;
queue->buffer_size *= 2;
queue->next_read_index = 0;
}
memcpy(
&queue->cis[(queue->next_read_index + queue->count) % queue->buffer_size],
ci, sizeof(struct continuation_info));
++queue->count;
}
int take_from_queue(struct continuation_queue *queue, struct continuation_info *ci) {
if (queue->count == 0)
return 0;
memcpy(ci, &queue->cis[queue->next_read_index], sizeof(struct continuation_info));
queue->next_read_index = (queue->next_read_index + 1) % queue->buffer_size;
--queue->count;
return 1;
}