Autor Thema: Multitasking bug?  (Gelesen 7058 mal)

clemensoft

  • Beiträge: 92
    • Profil anzeigen
    • http://www.clemensoft.de
Gespeichert
« am: 22. March 2005, 14:16 »
Ich hab hier irgendeinen Bug im Multitasking, und zwar wird beim return von task_scheduler() irgendwo hingesprungen, wo gar nicht gesprungen werden soll. Wers hinkriegt, darf den taskhandler behalten/benutzen
task.asm (handler)


[global _timer_int]
[extern _task_scheduler]
_timer_int:

cli
pusha ;Save registers
push ds
push es
push fs
push gs

call _task_scheduler ;Call C Scheduler

mov esp, eax ;Put return value(eax) into esp

;Send EOI to PIC
mov al, 0x20
out 0x20, al

pop gs
pop fs
pop es
pop ds
popa
sti
iret


task.c (die logik und alles)

/*-------------------------------------------------------------------------------------------

Delta Nanocore
This file is part of the implementation of Delta Nanocore.
You may use this code to understand how things work, but
you may NOT copy/use this code for your own purposes.
If you want to, you need permission by the Author of this code (Clemens Brust).
You may distribute the binaries for free. If you want to sell them, ask the Author
for permission.

Copyright (C) 2005 by Clemens-Alexander Brust

-------------------------------------------------------------------------------------------*/
struct task
{
unsigned long t_esp;
unsigned long t_id;
unsigned long t_cr3;
char* t_descriptor;
};


struct task_node
{
struct task t_task;
struct task_node* prev;
struct task_node* next;
};

struct task_node* task_current;
unsigned long task_enable=0;
unsigned long esptarget;
unsigned long cr3target;
// Prototypes:

struct task_node* task_init();
unsigned long task_add(unsigned long t_eip, unsigned long t_esp, unsigned long t_id, unsigned long t_cr3, char* descriptor);
struct task_node* task_last();
struct task_node* task_first();
void task_unlink(struct task_node* tnode);
void task_attach(struct task_node* tnode);
void task_next();
unsigned long task_scheduler();
void task_store_data();

//Implementations
struct task_node* task_init()
{
task_current=kmalloc(sizeof(struct task_node));
if(task_current==0)
return 0;
task_current->prev=0;
task_current->next=0;
task_current->t_task.t_id=0;
task_current->t_task.t_esp=read_esp();
task_current->t_task.t_cr3=read_cr3();
task_current->t_task.t_descriptor="Nanocore";
task_enable=1;
return task_current;
}

unsigned long task_add(unsigned long t_eip, unsigned long t_esp, unsigned long t_id, unsigned long t_cr3, char* descriptor)
{
struct task_node* tnode=0;
tnode=kmalloc(sizeof(struct task_node));
if(tnode==0)
{
return 0;
}
tnode->t_task.t_esp=t_esp;
*(unsigned long*)t_esp=t_eip;
asm("cli");
unsigned long tmp_esp=read_esp();
write_esp(t_esp-4);
asm("pushal");
asm("push %ds");
asm("push %es");
asm("push %fs");
asm("push %gs");
write_esp(tmp_esp);

tnode->t_task.t_id=t_id;
tnode->t_task.t_cr3=t_cr3;
tnode->t_task.t_descriptor=descriptor;
tnode->prev=task_current;
task_attach(tnode);
asm("sti");
return;
}


struct task_node* task_last()
{
struct task_node* p=task_current;
while(p->next)
{
p=p->next;
}
return p;
}
struct task_node* task_first()
{
struct task_node* p=task_current;
while(p->prev)
{
p=p->prev;
}
return p;
}

void task_unlink(struct task_node* tnode)
{
if(tnode)
{
if(tnode->next)
tnode->next->prev=tnode->prev;
if(tnode->prev)
tnode->prev->next=tnode->next;
}
return;
}

void task_attach(struct task_node* tnode)
{
task_last()->next=tnode;
return;
}

void task_next()
{
if(task_current->next)
{
task_current=task_current->next;
}
else
{
task_current=task_first();
}
return;
}

unsigned long task_scheduler()
{
printm("task_scheduler","test");
if(task_enable)
{
task_store_data(); // Save
task_next(); // All the logic is in there
printm("using task",task_current->t_task.t_descriptor);
char esp_d[8];
itoa(esp_d,'x',task_current->t_task.t_esp);
printm("esp",esp_d);
return task_current->t_task.t_esp; //<<<<<------ ERROR!
}
printm("task_scheduler","done");
return read_esp();
}


void task_store_data()
{
task_current->t_task.t_esp=read_esp();
task_current->t_task.t_cr3=read_cr3();
return;
}


clemensoft

  • Beiträge: 92
    • Profil anzeigen
    • http://www.clemensoft.de
Gespeichert
« Antwort #1 am: 22. March 2005, 18:23 »
Du hast nur was übersehen! read_esp() wird zurückgegeben, wenn MT noch nicht aktiv ist! Ansonsten wird return task_current->t_task.t_esp.

clemensoft

  • Beiträge: 92
    • Profil anzeigen
    • http://www.clemensoft.de
Gespeichert
« Antwort #2 am: 22. March 2005, 19:54 »
>Hat der Code schon mal funktioniert

Wenn ich das Schreiben der Daten unterbinde, funktioniert zumindest die Logik, er zeigt halt Thread 1, 2, 3, 1, 2, 3, 1, 2 ,3... an. Ich werde das mal debuggen, leider geht das mit C nicht so einfach :-(

clemensoft

  • Beiträge: 92
    • Profil anzeigen
    • http://www.clemensoft.de
Gespeichert
« Antwort #3 am: 22. March 2005, 22:46 »
struct!=class.
Ich benutze kein C++. Die printms hab ich nur zum debuggen. wenn alles geht kommen die natürlich raus!
EDIT: Ich versuche es jetzt auf dem Papier (immer ne gute lösung). Kann jemand mal seine MT-Implementation posten?

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #4 am: 23. March 2005, 09:30 »
ein tipp, den ich damals von roshl bekam: nimm das pusha und popa raus und nimm stattdessen einfach "push ax, push bx...", das geht schneller, sagte er...
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 23. March 2005, 13:56 »
Zitat von: sp

struct task_node* task_init() Wird das aufgerufen, hab irgendwie keine Codestelle dazu gefunden, allerdings hab ich den Code auch nur überfolgen.

Ich denke das wird beim Booten aufgerufen, also nur einmal von einer anderen Funktion.

Ansonsten sollte man vielleicht nicht direkt task_scheduler() aufrufen, sondern eine art Dummy Funktion, die in C geschrieben ist und in der man evtl noch ein paar Debug-Messages machen kann.

clemensoft

  • Beiträge: 92
    • Profil anzeigen
    • http://www.clemensoft.de
Gespeichert
« Antwort #6 am: 23. March 2005, 15:46 »
ICh habe jetzt tausende von Bugs behoben, unter anderem hab ich vergessen, vor der Adresse das CS auf den Stack zu pushen, und ich hab vergessen, dass der Stack nach unten wächst. Er bleibt jetzt bei task_add stehen (ich zeig gleich wo) und springt in den thread rein, weil die funktion zum espschreiben ihre parameter auf den stack bekommt :-@
Ich bräuchte nur eine Möglichkeit, mit inline-assembly t_esp in esp zu schreiben.
task_scheduler wird vom timerint aufgerufen, der den returnwert von task_scheduler in espschreib und dann popa pop ds es fs gs macht.
task.c:


//Implementations
struct task_node* task_init()
{
task_current=kmalloc(sizeof(struct task_node));
if(task_current==0)
return 0;
task_current->prev=0;
task_current->next=0;
task_current->t_task.t_id=0;
task_current->t_task.t_esp=read_esp();
task_current->t_task.t_cr3=read_cr3();
task_current->t_task.t_descriptor="Nanocore";
task_enable=1;
return task_current;
}

unsigned long task_add(unsigned long t_eip, unsigned long t_esp, unsigned long t_id, unsigned long t_cr3, char* descriptor, unsigned short t_cs)
{
task_enable=0;
asm("cli");
printm("nanocore","tasking disabled!");
struct task_node* tnode=0;
tnode=kmalloc(sizeof(struct task_node));
if(tnode==0)
{
nanocore_panic("Could not malloc enough memory!");
return 0;
}

*(unsigned long*)t_esp=t_eip;
unsigned long tmp_esp=read_esp();
write_esp(t_esp);
printm("nanocore","wrote esp");
pushval(t_eip);
asm("pushw %0":"=r"(t_cs));
asm("pushal");
asm("push %ds");
asm("push %es");
asm("push %fs");
asm("push %gs");
tnode->t_task.t_esp=read_esp();
        printm("nanocore","second write_esp()"); //<<< das geht noch
write_esp(tmp_esp); //<<<<<<<<<<<<<<<<---------- ERROR
printm("nanocore","wrote esp again!"); //<<< das kommt nicht mehr, stattdessen springt er in den thread, der gerade erstellt wurde und hat die ints aus.,
tnode->t_task.t_id=t_id;
tnode->t_task.t_cr3=t_cr3;
tnode->t_task.t_descriptor=descriptor;
tnode->prev=task_current;
task_attach(tnode);
printm("nanocore","going to enable tasking!");
task_enable=1;
asm("sti");
return;
}


struct task_node* task_last()
{
struct task_node* p=task_current;
while(p->next)
{
p=p->next;
}
return p;
}
struct task_node* task_first()
{
struct task_node* p=task_current;
while(p->prev)
{
p=p->prev;
}
return p;
}

void task_unlink(struct task_node* tnode)
{
if(tnode)
{
if(tnode->next)
tnode->next->prev=tnode->prev;
if(tnode->prev)
tnode->prev->next=tnode->next;
}
return;
}

void task_attach(struct task_node* tnode)
{
task_last()->next=tnode;
return;
}

void task_next()
{
if(task_current->next)
{
task_current=task_current->next;
}
else
{
task_current=task_first();
}
return;
}

unsigned long task_scheduler()
{

if(task_enable)
{
task_store_data(); // Save
task_next(); // All the logic is in there
#ifdef _NANO_DEBUG_
printm("using task",task_current->t_task.t_descriptor);
char esp_d[8];
itoa(esp_d,'x',task_current->t_task.t_esp);
printm("esp",esp_d);
#endif
return task_current->t_task.t_esp;
}
else
{
gemstone_putc('N');
return 0;
}
}


void task_store_data()
{
task_current->t_task.t_esp=read_esp();
task_current->t_task.t_cr3=read_cr3();
return;
}


clemensoft

  • Beiträge: 92
    • Profil anzeigen
    • http://www.clemensoft.de
Gespeichert
« Antwort #7 am: 28. April 2005, 20:07 »
*läuftimmernochnich*

 :cry:  :cry:  :cry:  :cry:  :cry:  :cry:  :cry:  :cry:  :cry:

 

Einloggen