#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; }