Nucleus
Barry Signals and small task functions 9d6eb50 (3 years, 2 months ago)
/*
* This file is in control of initialising the tasking subsystem. It also
* implements the Task object.
*/
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <nucleus/cpu.h>
#include <nucleus/task.h>
#include <nucleus/memory.h>
#include <nucleus/object.h>
#include <nucleus/vfs.h>
void init_scheduler(void);
void timer_handler(struct InterruptFrame *frame);
static void task_new(Object *);
static void task_delete(Object *);
/* Task object type */
ObjectType taskType = {
.name = "TASK",
.size = sizeof(Task),
.new = task_new,
.delete = task_delete,
};
Task *currentTask[MAX_CPUS];
pid_t nextTid = 1;
extern char stackTop[];
/* Create a new Task */
static void
task_new(Object *obj)
{
Task *task = (void *) obj;
task->tid = nextTid++;
task->tgid = task->tid;
task->priority = NORMAL;
task->state = READY;
}
/* Destroy a Task object */
static void
task_delete(Object *obj)
{
Task *task = (void *) obj;
put(task->executable);
put(task->stack);
if (task->target)
put(task->target);
if (task->wait)
destroy_list(task->wait);
put(task->fs);
put(task->files);
put(task->vm);
put(task->signals);
}
/* Move the stack */
static void
move_stack(uintptr_t top, size_t size)
{
size_t offset;
uintptr_t oldStack, oldBase;
uintptr_t newStack, newBase;
top -= sizeof(uintptr_t);
asm volatile("mov %%esp, %0" : "=r" (oldStack));
asm volatile("mov %%ebp, %0" : "=r" (oldBase));
offset = top - (uintptr_t) stackTop;
newStack = oldStack + offset;
newBase = oldBase + offset;
memcpy((void *) newStack, (void *) oldStack, (size_t) stackTop - oldStack);
/* Update pointers on the stack */
uintptr_t i, tmp;
for (i = top; i > top - size; i -= sizeof(uintptr_t)) {
tmp = *(uintptr_t *) i;
if (tmp > oldStack && tmp < (uintptr_t) stackTop) {
tmp += offset;
*(uintptr_t *) i = tmp;
}
}
asm volatile("mov %0, %%esp" :: "r" (newStack));
asm volatile("mov %0, %%ebp" :: "r" (newBase));
}
/* Initialise tasking */
void
init_tasking(void)
{
move_stack(0xF0800000, 0x2000);
current = new(&taskType);
asm volatile("mov %%cr3, %0" : "=r" (current->pageDir));
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);
init_scheduler();
register_interrupt(0, timer_handler);
}
/* 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();
}
/* 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;
}