#include "clib.h"
#include "i386.h"
#include "systab.h"
#include "sched.h"
#include "phmem.h"
#include "kmalloc.h"
#include "paging.h"
#define tasks (tasks_list)
tss_t *tasks_list[NR_TASK];
tss_t* sel2tss(selector_t seltss)
{
descriptor_t d;
if (get_gdt_descriptor(seltss shr 3, &d) == 0)
return (tss_t*)get_descriptor_base(&d);
else {
WARNING("return NULL");
return NULL;
}
}
tss_t* alloc_tss(tss_t* tss, const char* name)
{
int i;
for (i = 0; i < NR_TASK; i++) {
if (tasks_list[i] == NULL) {
descriptor_t d;
int di;
int lim;
di = alloc_gdt_descriptor();
if (di == 0) goto _ret;
if (tss == NULL) {
tss = kmalloc(sizeof(tss_t));
tss->limit = sizeof(tss_t) - 1;
}
tasks_list[i] = tss;
lim = tss->limit;
memset(tss, 0, sizeof(tss_t)); // CANCELLA TSS
tss->index = i;
tss->tss_sel = di shl 3;
tss->limit = lim;
strncpy((char*)tss->name, name, MAX_TASK_NAME_LENGTH);
set_system_descriptor(&d, (dword)tss, tss->limit,
SDT_A386TSS + SDT_PRESENT);
set_gdt_descriptor(di, &d);
return tss;
}
}
_ret:
WARNING("return NULL");
return NULL;
}
void free_tss(tss_t* tss)
{
ASSERT(tss != NULL);
if (tss->index > 0 && tss->index < NR_TASK) {
tasks_list[tss->index] = NULL;
/* free CR3 */
free_task_pgtable(tss);
/* free tls */
if (tss->tls) {
kfree(tss->tls);
}
/* free LDT */
if (tss->ldt_sel != 0) {
kfree(tss->ldt.table);
free_gdt_descriptor(tss->ldt_sel shr 3);
}
/* free TSS */
free_gdt_descriptor(tss->tss_sel shr 3);
kfree(tss);
} else WARNING("invalid TSS");
}
void sched_setup(void)
{
memset(tasks_list, 0, sizeof(tasks_list));
}
void task_dump(selector_t tss_sel)
{
descriptor_t d;
tss_t *t;
if (get_gdt_descriptor(tss_sel shr 3, &d) != 0) goto _inval;
t = (tss_t*) get_descriptor_base(&d);
if (t) {
kprintf("task `%s' dump (index %d dec):\n"
"tr %04x ldt %04x cr3 %08x\n"
"cs:eip %04x:%08x ss:esp %04x:%08x\n"
"ss0:esp0 %04x:%08x eflags %08x\n"
"ds %04x es %04x fs %04x gs %04x\n"
"eax %08x ebx %08x edx %08x ecx %08x\n"
"ebp %08x esi %08x edi %08x \n"
"tls %08x status %xh\n",
t->name, t->index,
t->tss_sel, t->ldt_sel, t->cr3,
t->cs, t->eip, t->ss, t->esp,
t->ss0, t->esp0, t->eflags,
t->ds, t->es, t->fs, t->gs,
t->eax, t->ebx, t->edx, t->ecx,
t->ebp, t->esi, t->edi,
t->tls, t->status);
return;
}
_inval:
;
kprintf("invalid tss selector %xh", tss_sel);
}
bool task_signal(tss_t *task, int signal)
{
if (task->handler) {
dword buf[2];
buf[0] = (dword)task->eip;
buf[1] = signal;
task->eip = task->handler;
task->esp -= sizeof(buf);
write_to_task(task, (addr_t)task->esp, buf, sizeof(buf));
return true;
} else return false;
}