Nucleus
Barry Kernel threads + threads share address space 6217f0d (3 years, 1 month ago)
/*
* This file is in control of initialising the tasking subsystem. It also
* implements the Task object.
*/
#include <stddef.h>
#include <stdint.h>
#include <nucleus/cpu.h>
#include <nucleus/lib.h>
#include <nucleus/memory.h>
#include <nucleus/object.h>
#include <nucleus/task.h>
#include <nucleus/vfs.h>
void timer_handler(struct InterruptFrame *frame);
void syscall_handler(struct InterruptFrame *frame);
static void task_new(Object *);
static void task_delete(Object *);
/* Task object type */
ObjectType taskType = {
.name = "TASK",
.size = KERNEL_STACK_SIZE, //sizeof(Task),
.new = task_new,
.delete = task_delete,
};
extern char stackTop[];
/* Create a new Task */
static void
task_new(Object *obj)
{
static pid_t tid = 1;
Task *task = (void *) obj;
task->tid = tid++;
task->tgid = task->tid;
task->priority = NORMAL;
task->state = READY;
}
/* Destroy a Task object */
static void
task_delete(Object *obj)
{
Task *task = (void *) obj;
if (task->executable)
put(task->executable);
if (task->target)
put(task->target);
if (task->wait)
destroy_list(task->wait);
if (task->fs)
put(task->fs);
if (task->files)
put(task->files);
if (task->vm)
put(task->vm);
if (task->signals)
put(task->signals);
}
/* Initialise tasking */
void
init_tasking(void)
{
current = new(&taskType);
current->state = RUNNING;
/* File System namespace */
current->fs = new(&fsType);
/* Files namespace */
current->files = new(&filesType);
/* Virtual Memory namespace */
current->vm = new(&virtualMemoryType);
/* Signals namespace */
current->signals = new(&signalsType);
cpu->scheduler->tasks = 1;
register_interrupt(0, timer_handler);
register_exception(128, syscall_handler);
set_kernel_stack((uintptr_t) current + KERNEL_STACK_SIZE);
}
/* Get the current task's PID */
pid_t
getpid(void)
{
return current->tgid;
}
/* Block a task */
void
block_task(enum State reason, ObjectList *list)
{
lock(current);
current->state = reason;
if (list)
add(list, current);
unlock(current);
schedule();
}
/* Unblock a task */
void
unblock_task(Task *task)
{
lock(task);
task->state = READY;
unlock(task);
enqueue_task(task);
}
/* Find a task by ID */
Task *
find_task(pid_t tid)
{
Task *task = NULL;
foreach (taskType.objects, task) {
if (task->tid == tid)
break;
}
return task;
}