Note that there are some explanatory texts on larger screens.

plurals
  1. POTask switching using a queue
    primarykey
    data
    text
    <p>i'm developing my own hobby os, and now i'm stuck with a problem on the scheduler/task switching.</p> <p>I planned to use a FIFO queue as structure to hold processes. I implemented it using linked list. </p> <p>I also decided to use the iret method to switch from a task to another (so when the os was serving an interrupt request just before the iret i change the ESP register in order to move to the new task).</p> <p>But i have a problem. When the os start it launch two tasks: </p> <ul> <li>idle</li> <li>shell</li> </ul> <p>And with these two i have no problem. But if i try to launch two other tasks (with a simply printf inside), the task queue was corrupted. </p> <p>If after that i try to print the queue it print only two tasks that are the 2 just created and with idle and shell disappeared, but the os continues to work (i think that in a specific moment the esp field of the new tasks was replaced with the esp content of the shell). </p> <p>The task data structure is: </p> <pre><code>typedef struct task_t{ pid_t pid; char name[NAME_LENGTH]; void (*start_function)(); task_state status; task_register_t *registers; unsigned int cur_quants; unsigned int eip; long int esp; unsigned int pdir; unsigned int ptable; struct task_t *next; }task_t; </code></pre> <p>and the tss is: </p> <pre><code>typedef struct { unsigned int edi; //+0 unsigned int esi; //+1 unsigned int ebp; //+2 unsigned int esp; //+3 (can be null) unsigned int ebx; //+4 unsigned int edx; //+5 unsigned int ecx; //+6 unsigned int eax; //+7 unsigned int eip; //+8 unsigned int cs; //+9 unsigned int eflags; //+10 unsigned int end; } task_register_t; </code></pre> <p>The scheduler function is the following: </p> <pre><code>void schedule(unsigned int *stack){ asm("cli"); if(active == TRUE){ task_t* cur_task = dequeue_task(); if(cur_task != NULL){ cur_pid = cur_task-&gt;pid; dbg_bochs_print("@@@@@@@"); dbg_bochs_print(cur_task-&gt;name); if(cur_task-&gt;status!=NEW){ cur_task-&gt;esp=*stack; } else { cur_task-&gt;status=READY; ((task_register_t *)(cur_task-&gt;esp))-&gt;eip = cur_task-&gt;eip; } enqueue_task(cur_task-&gt;pid, cur_task); cur_task=get_task(); if(cur_task-&gt;status==NEW){ cur_task-&gt;status=READY; } dbg_bochs_print(" -- "); dbg_bochs_print(cur_task-&gt;name); dbg_bochs_print("\n"); //load_pdbr(cur_taskp-&gt;pdir); *stack = cur_task-&gt;esp; } else { enqueue_task(cur_task-&gt;pid, cur_task); } } active = FALSE; return; asm("sti"); } </code></pre> <p>The tss is initalized with the following values: </p> <pre><code>void new_tss(task_register_t* tss, void (*func)()){ tss-&gt;eax=0; tss-&gt;ebx=0; tss-&gt;ecx=0; tss-&gt;edx=0; tss-&gt;edi =0; tss-&gt;esi =0; tss-&gt;cs = 8; tss-&gt;eip = (unsigned)func; tss-&gt;eflags = 0x202; tss-&gt;end = (unsigned) suicide; //tss-&gt;fine = (unsigned)end; //per metterci il suicide return; } </code></pre> <p>And the function that creates a new task is the following: </p> <pre><code>pid_t new_task(char *task_name, void (*start_function)()){ asm("cli"); task_t *new_task; table_address_t local_table; unsigned int new_pid = request_pid(); new_task = (task_t*)kmalloc(sizeof(task_t)); strcpy(new_task-&gt;name, task_name); new_task-&gt;next = NULL; new_task-&gt;start_function = start_function; new_task-&gt;cur_quants=0; new_task-&gt;pid = new_pid; new_task-&gt;eip = (unsigned int)start_function; new_task-&gt;esp = (unsigned int)kmalloc(STACK_SIZE) + STACK_SIZE-100; new_task-&gt;status = NEW; new_task-&gt;registers = (task_register_t*)new_task-&gt;esp; new_tss(new_task-&gt;registers, start_function); local_table = map_kernel(); new_task-&gt;pdir = local_table.page_dir; new_task-&gt;ptable = local_table.page_table; //new_task-&gt;pdir = 0; //new_task-&gt;ptable = 0; enqueue_task(new_task-&gt;pid, new_task); //(task_list.current)-&gt;cur_quants = MAX_TICKS; asm("sti"); return new_pid; } </code></pre> <p>I'm sure that i just forgot something, or i miss some consideration. But i cannot figure what i'm missing.</p> <p>Actually i'm working only in kernel mode, and inside the same address space (pagiing is enabled, but actually i use the same pagedir for all tasks). </p> <p>The ISR macros are defined here: <a href="https://github.com/inuyasha82/DreamOs/blob/master/include/processore/handlers.h" rel="nofollow">https://github.com/inuyasha82/DreamOs/blob/master/include/processore/handlers.h</a></p> <p>I declared four kinds of function in order to handle ISR: </p> <ol> <li>EXCEPTION</li> <li>EXCEPTION_EC (an exception with an error code)</li> <li>IRQ</li> <li>SYSCALL</li> </ol> <p>Obviously the scheduler is called by an IRQ routine, so the macro looks like: </p> <pre><code>__asm__("INT_"#n":"\ "pushad;" \ "movl %esp, %eax;"\ "pushl %eax;"\ "call _irqinterrupt;"\ "popl %eax;"\ "movl %eax, %esp;"\ "popad;"\ "iret;") </code></pre> <p>the irq handler function is: </p> <pre><code>void _irqinterrupt(unsigned int esp){ asm("cli;"); int irqn; irqn = get_current_irq(); IRQ_s* tmpHandler; if(irqn&gt;=0) { tmpHandler = shareHandler[irqn]; if(tmpHandler!=0) { tmpHandler-&gt;IRQ_func(); #ifdef DEBUG printf("2 - IRQ_func: %d, %d\n", tmpHandler-&gt;IRQ_func, tmpHandler); #endif while(tmpHandler-&gt;next!=NULL) { tmpHandler = tmpHandler-&gt;next; #ifdef DEBUG printf("1 - IRQ_func (_prova): %d, %d\n", tmpHandler-&gt;IRQ_func, tmpHandler); #endif if(tmpHandler!=0) tmpHandler-&gt;IRQ_func(); } } else printf("irqn: %d\n", irqn); } else printf("IRQ N: %d E' arrivato qualcosa che non so gestire ", irqn); if(irqn&lt;=8 &amp;&amp; irqn!=2) outportb(MASTER_PORT, EOI); else if(irqn&lt;=16 || irqn==2){ outportb(SLAVE_PORT, EOI); outportb(MASTER_PORT, EOI); } schedule(&amp;esp); asm("sti;"); return; } </code></pre> <p>And these are the enqueue_task and dequeue_task functions: </p> <pre><code>void enqueue_task(pid_t pid, task_t* n_task){ n_task-&gt;next=NULL; if(task_list.tail == NULL){ task_list.head = n_task; task_list.tail = task_list.head; } else { task_list.head-&gt;next=n_task; task_list.head = n_task; } } task_t* dequeue_task(){ if(task_list.head==NULL){ return NULL; } else { task_t* _task; _task = task_list.tail; task_list.tail=_task-&gt;next; return _task; } return; } </code></pre> <p>Thanks in advance, and let me know if you need more details!</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload