COBE 0.1 ALPHA

D:/COBE-Packet/cobe/system/multitasking.c

gehe zur Dokumentation dieser Datei
00001 #include <multitasking.h>
00002 #include <stdio.h>
00003 #include <pmm.h>
00004 #include <pgng.h>
00005 #include <sysfunc.h>
00006 
00007 #ifndef NULL
00008 #define NULL (void *)0
00009 #endif
00010 
00011 extern struct paging_directory* kernel_map; //----------Die Kernel-Map wird auch hier deklariert----------
00012 
00013 new_task_t* first_task = NULL; //----------Zwei Listenelemente für die Tasks, den Startpunkt und den immer derzeitigen Task----------
00014 new_task_t* current_task = NULL;
00015 phy_alloc_list_t* current_list = NULL; //----------Ein Listenelemente für die allokierten Teile eines Modules, die derzeitige Liste----------
00016 
00017 new_tss_t tss; //----------Die TSS wird erzeugt----------
00018 
00020 
00021 void init_mm(multiboot_info_t* mbinfo) {
00022         load_grub_module(0, mbinfo);    //----------Das erste GRUB-Modul wird geladen----------
00023         return;
00024 }
00025 
00027 
00028 uint32_t getnew_pid() {
00029         static uint32_t pid_counter = 0;
00030         return pid_counter++;
00031 }
00032 
00034 
00035 new_task_t* init_task(void* entry_point, char* name, phy_alloc_list_t* alloc_list) {
00036 
00037         uint8_t* stack = pmm_alloc();   //----------4Kbyte jeweils für den Kernel-Stack und den User-Stack des neuen Tasks werden reserviert und erzeugt----------
00038         uint8_t* usr_stack = pmm_alloc();
00039         new_task_t* task = pmm_alloc();         //----------Für das Task-Element wird eine 4Kbyte Seite wird reserviert----------
00040         struct paging_directory* new_pd = paging_map();         //----------Ein neues PageDirectory(Addressraum) für den neuen Task wird angelegt und initialisiert----------
00041 
00042         
00043         //----------Vorläufig wird der Addressraum gleichgesetzt,  phys. Addresse = virtuelle Addresse, alle Pages werden mit dem Usermode belegt----------
00044         for(int i = 0; i < 1024 * 4096; i += 0x1000) identity_mapping(new_pd, i, i, ACCS_BIT | WRITE_BIT | ALL_ACCS_BIT);
00045         
00046         //----------Die verteilten physischen Speicherblöcke in denen das Programm liegt werden in virtuelle Reihenfolge gelegt----------
00047         new_map_addresses(alloc_list, new_pd, 0x200000);
00048         
00049         kernel_mapping(new_pd);         //----------Der Kernel wird auf RING0 belegt----------
00050         task->task_pd = new_pd;         //----------Die Adresse des PageDirectory wird in das Task-Element geschrieben, da es beim Scheduling gewechselt wird----------
00051 
00052         //----------Der CPU-Zustand wird erzeugt, eip zeigt auf den Einsprungspunkt, esp zeigt auf den User-Stack, die Segmente enthalten die RING3-Werte, bei eflags werden Interrupts freigeschaltet----------
00053         cpu_regs new_cpu = {
00054                 .eax = 0,
00055                 .ebx = 0,
00056                 .ecx = 0,
00057                 .edx = 0,
00058                 .esi = 0,
00059                 .edi = 0,
00060                 .ebp = 0,
00061                 .eip = (uint32_t) entry_point,
00062                 .esp = (uint32_t) usr_stack + 4096,
00063                 .ss = 0x23,
00064                 .cs = 0x1B,
00065                 .ds = 0x23,
00066                 .es = 0x23,
00067                 .eflags = 0x200,
00068         };
00069         
00070         cpu_regs* state = (void*) (stack + 4096 - sizeof(new_cpu));     //----------Der CPU-Zustand wird auf den Kernel-Stack des Tasks geschrieben----------
00071         *state = new_cpu;
00072         
00073         task->cpu_state = state;        //----------Der CPU-Zustand wird in das Task-Element geschrieben----------
00074         task->kernel_stack = (uint32_t) stack;  //----------Die Addresse des Kernel-Stack wird in das Task-Element geschrieben----------
00075         task->usr_stack = (uint32_t) usr_stack;
00076         task->next_task = first_task;   //----------Als nachfolgenden Task wird der erste Task gesetzt----------
00077         task->memory_list = alloc_list;
00078         kstrcpy(task->name,name);
00079         task->pid = getnew_pid();
00080         first_task = task;      //----------Der erste Task ist nun dieser Task----------
00081         
00082         return task;
00083 }
00084 
00086 
00087 uint32_t kill_task(uint32_t pid) {
00088         new_task_t* prev_task = first_task;
00089         new_task_t* current_t = first_task;
00090         do {
00091                 if(current_t->pid == pid) {
00092                         prev_task->next_task = current_t->next_task;
00093                         delete_map_addresses(current_t->memory_list,current_t->task_pd);
00094                         pmm_free((void*)current_t->kernel_stack);
00095                         pmm_free((void*)current_t->usr_stack);
00096                         pmm_free((void*)current_t);
00097                         return 0;
00098                 }
00099                 prev_task = current_t;
00100                 current_t = current_t->next_task;
00101         } while(current_t->next_task != first_task);
00102         return 1;
00103 }
00105 
00106 void set_tss_stack(uint32_t stack) {
00107         tss.esp0 = stack;       //----------Der Kernel-Stack des neuen Tasks wird in die TSS geschrieben----------
00108         return;
00109 }
00110 
00112 
00113 cpu_regs* schedule(cpu_regs* cpu) {
00114         if(current_task != NULL) current_task->cpu_state = cpu;         //----------Sichere den alten CPU-Zustand im alten Task----------
00115         if(current_task == NULL) current_task = first_task;     //----------Möglicherweise war noch kein Task an der Reihe, der erste Task der Liste wird der neue Task----------
00116 
00117         else {                          //----------Wenn doch schon ein Task dran war, dann...----------
00118                 current_task = current_task->next_task;  //----------...setze den nächsten Task als aktuellen Task----------
00119                 if(current_task == NULL) current_task = first_task;     //----------Falls es nun der letzte Task ist, setze den ersten Task als aktuellen Task----------
00120         }
00121         cpu = current_task->cpu_state;  //----------Der CPU-Zustand des neuen Tasks ist der Rückgabewert----------
00122         act_dir(current_task->task_pd);         //----------Der Addressraum des neuen Tasks wird aktiviert----------
00123         return cpu;     //----------Der neue CPU-Zustand wird zurückgegeben----------
00124 
00125 }
00126 
00128 
00129 void load_grub_module(int num, multiboot_info_t* mbinfo) {
00130         
00131         uint32_t address = 0x1000;      //----------Der Zwischenwert für die neu zu kopierende Addresse----------
00132         uint32_t list_address;  //----------Die aktuelle Addresse der Liste wird deklariert----------
00133 
00134         module_t* grub_module = (void*)mbinfo->mods_addr;       //----------Alle Grub-Module werden deklariert----------
00135         uint32_t module_size = grub_module[num].mod_end - grub_module[num].mod_start;   //----------Die Differenz aus End- und Startaddresse des aktuellen Moduls, ist die Größe des Moduls----------
00136         uint32_t rest_of_module = module_size % 0x1000;         //----------Der Rest der letzten geraden 0x1000-Größe----------
00137         module_size = module_size - rest_of_module;     //----------Der überstehende Rest wird von der Modul-Größe abgeschnitten----------
00138 
00139         list_address = (uint32_t) pmm_alloc();  //----------Ein Speicherbereich für die gesamte Liste wird reserviert----------
00140         
00141         phy_alloc_list_t* new_list = (void*)list_address;       //----------Das erste Element wird an den Anfang des Speicherblocks geladen----------
00142         list_address += sizeof(phy_alloc_list_t);       //----------Die Addresse wird um ein Listen-Element hochgesetzt----------
00143         
00144         new_list->addr = pmm_alloc();   //----------Die Addresse zeigt auf einen leeren Speicherblock----------
00145         current_list = new_list;        //----------Die erste Liste, ist die aktuelle Liste----------
00146         kmemcpy(new_list->addr, (void*) grub_module[num].mod_start, 0x1000);    //----------Die ersten 4096Byte des Moduls werden an den ersten Speicherblock geschrieben----------
00147         
00148         //----------Wenn das Modul mehr als 4096Byte hat, müssen die restlichen Blöcke auch einen Platz finden----------
00149         if(module_size > 0x1000)
00150         {
00151                 //----------Das ganze wird so oft durchlaufen, bis alle Blöcke kopiert wurden----------
00152                 for(int i = module_size; i > address; address += 0x1000)
00153                 {
00154                         //----------Debug-Ausgaben----------
00155                         phy_alloc_list_t* new_phy_list = (void*)list_address;   //----------Eine neue Liste wird an der aktuellen Adresse des Speicherblocks für die Listen angelegt, die Addresse wird wieder hochgesetzt----------
00156                         list_address += sizeof(phy_alloc_list_t);
00157                         new_phy_list->addr = pmm_alloc();       //----------Die Addresse zeigt auf einen leeren Speicherblock----------
00158                         current_list->next = new_phy_list;      //----------Die nächste Liste ist die neue Liste----------
00159                         current_list = new_phy_list;    //----------Die neue Liste ist nun die aktuelle Liste----------
00160                         kmemcpy(new_phy_list->addr, (void*) (grub_module[num].mod_start + address), 0x1000);  //----------Die nächsten 4096Byte des Moduls werden an den nächsten Speicherblock geschrieben----------
00161                 }
00162         }
00163         //----------Das gleiche nochmal für den letzten Rest, wobei der Rest auch einen ganzen Speicherblock bekommt, anders geht es nicht!----------
00164         phy_alloc_list_t* new_list_end = (void*)list_address;
00165         list_address += sizeof(phy_alloc_list_t);
00166         new_list_end->addr = pmm_alloc();
00167         current_list->next = new_list_end;
00168         new_list_end->next = NULL;      //----------Eine nächste Liste gibt es nicht, die Liste muss abgebrochen werden----------
00169 
00170         kmemcpy(new_list_end->addr, (void*) (grub_module[num].mod_start + address), rest_of_module);
00171         
00172         //----------Das Modul wird als Task gestart, der erste Speicherblock ist der Einsprungspunkt, der Name liegt im Modul, die Liste mit den physischen Addressen wird übergeben----------
00173         init_task(new_list->addr, (char*)grub_module[num].string, new_list);
00174 
00175         return;
00176 }
00177 
00179 
00180 void new_map_addresses(phy_alloc_list_t* alloc_list, struct paging_directory* pd, uint32_t adr) {
00181         
00182         if(alloc_list == 0) return;
00183         uint32_t address = adr;
00184         phy_alloc_list_t* current_list = alloc_list;    //----------Die erste Liste ist die aktuelle Liste----------
00185         while(current_list->next != NULL)       //----------Solange die nächste Liste nicht NULL ist, verfolge die Liste----------
00186         {
00187                 identity_mapping(pd, address, (uint32_t)current_list->addr, ACCS_BIT | WRITE_BIT | ALL_ACCS_BIT);  //----------Mappe die virtuelle Addresse in einer Reihenfolge, mit den verteilten physischen Addressen----------             
00188                 address += 0x1000;
00189                 current_list = current_list->next;
00190         }
00191         identity_mapping(pd, address, (uint32_t)current_list->addr, ACCS_BIT | WRITE_BIT | ALL_ACCS_BIT); //----------Den Rest auch noch mappen!----------
00192 
00193         return;
00194 }
00195 
00197 
00198 void delete_map_addresses(phy_alloc_list_t* alloc_list, struct paging_directory* pd) {
00199         
00200         if(alloc_list == 0) return;
00201         phy_alloc_list_t* current_list = alloc_list;    //----------Die erste Liste ist die aktuelle Liste----------
00202         pmm_free((void*)pd);
00203         pmm_free((void*)pd->page_directory);
00204         while(current_list->next != NULL)       //----------Solange die nächste Liste nicht NULL ist, verfolge die Liste----------
00205         {
00206                 pmm_free((void*)current_list->addr);
00207                 current_list = current_list->next;
00208         }
00209         pmm_free((void*)current_list->addr); //----------Den Rest auch noch löschen!----------
00210 
00211         return;
00212 }
 Alle Datenstrukturen Dateien Funktionen Variablen Typdefinitionen Makrodefinitionen