Some more help on MultiTasking

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
ashishkumar4
Member
Member
Posts: 73
Joined: Wed Dec 23, 2015 10:42 pm

Some more help on MultiTasking

Post by ashishkumar4 »

As adviced by Brenden sir, I made a co-operative multitasking system first. But as said by others to not to use inline asm with optimizations, I tried to use nasm-only for the task_switch but I failed at it (believe me I tried a lot) So instead I made use of inlines BUT WITHOUT OPTIMIZATIONS. and guess what? IT WORKED! :D but now as you see, I have only co-operative multitasking. But I want a better one means using interrupts. Now I modified my switch code a bit for the interrupts and DISABLED the "save earlier EIP before switch to next task" but retained all the other code like saving the registers, segment registers etc. So as you can guess, It works in round-robin fashion but goes straight to the start of the task function everytime a new task is switched to (that's what I intended, going in through cycles starting from 1st task to last task and again to 1st task but not saving the eip)

Though That WONT BE MULTITASKING either (I just did it for testing). For it I need to save the EIP also along with registers. I know that when an interrupt occurs, the last EIP and eflags, cs are pushed on the stack and I can pop them from there but I don't know EXACTLY HOW TO DO THAT.
I have registered my switch_task function in the interrupt handler of my PIT. I tried to pop the eax reg in the start of the function thinking EIP would be the last to be pushed. But that didn't worked. Also I tried to make my function as
void switch_task(irqregs_t regs) and do this inside: old_task->regs.eip=regs.eip; (the old_task-> regs is a separate struct, not related to irqregs_t)
the definition of irqregs_t is similar to :
typedef struct
{
uint32_t eflags,cs,eip;
}irqregs_t;

because I got to know from somewhere that its pushed in that fashion
but this didn't worked too.
I tried with this struct then:
typedef struct
{
uint32_t eip,cs,eflags;
}irqregs_t;
This too didn't worked after 1st cycle
In all the cases above, everything works fine for the 1st cycle that is, everything works fine until the "saved state of the task" is switched to rather then the "initial state of the task that I made while creating it"
my tasks are infinite while loops printing 1,2,3,4,5 depending on the task it is (1st task,2nd task...)
if everything works fine, I should print an infinite sequence like this :
1111111222222233333334444444555555511111112222222333333344444445555555.....
but its like this :
11111112222222333333344444445555555 that's it :/

Please give me a good way of handling the interrupt and getting the EIP from the stack (Please give me code with explanation and not only explanation because that's why I am in this situation :p)

here is my switch_task function:

Code: Select all



void switch_task(irqregs_t regs)
{
    // If we haven't initialised tasking yet, just return.
    //printf("\nSwitching Task\n");
    asm volatile("cli");

    old_task=current_task;
    current_task=current_task->next;
    //asm volatile("popl %%eax;": "=a"(old_task->regs.eip));
    //printf("\nEIP: %x",old_task->regs.eip);
    //asm volatile("add $0xc, %esp");
    //switchTask(&old_task->regs, &current_task->regs);

  	asm volatile("movl %%ebx, %0;":"=r"(old_task->regs.ebx));
  	asm volatile("movl %%ecx, %0;":"=r"(old_task->regs.ecx));
  	asm volatile("movl %%edx, %0;":"=r"(old_task->regs.edx));
  	asm volatile("movl %%esi, %0;":"=r"(old_task->regs.esi));
  	asm volatile("movl %%edi, %0;":"=r"(old_task->regs.edi));
  	asm volatile("movl %%ebp, %0;":"=r"(old_task->regs.ebp));

    asm volatile("pushl %eax");
	  asm volatile("pushl %ebx");
  	asm volatile("pushl %ecx");
  	asm volatile("pushl %edx");
  	asm volatile("pushl %esi");
  	asm volatile("pushl %edi");
  	asm volatile("pushl %ebp");
  	asm volatile("pushl %ds");
  	asm volatile("pushl %es");
  	asm volatile("pushl %fs");
  	asm volatile("pushl %gs");//*/
  	//asm volatile("mov %%esp, %0":"=r"(old_task->StackTop));
    //old_task->regs.eip=regs.eip;

    asm volatile("    movw    $16, %ax		"); /* KERNEL_DATA_SEG!!!! */
    asm volatile("    movw    %ax, %ds		");
    asm volatile("    movw    %ax, %es		");
    asm volatile("    movw    %ax, %fs		");
    asm volatile("    movw    %ax, %gs		");

  	asm volatile("movl %%ds, %0;":"=r"(old_task->ds));
  	asm volatile("movl %%es, %0;":"=r"(old_task->es));
  	asm volatile("movl %%fs, %0;":"=r"(old_task->fs));
  	asm volatile("movl %%gs, %0;":"=r"(old_task->gs));
  	asm volatile("movl %%ss, %0;":"=r"(old_task->ss));

    stack=(uint32_t*)current_task->StackTop;
    *--stack = current_task->regs.eflags; // eflags
    *--stack = current_task->regs.cs; // cs
    *--stack = current_task->regs.eip; // eip
  	*--stack = current_task->regs.eax; // eax
  	*--stack = current_task->regs.ebx; // ebx
  	*--stack = current_task->regs.ecx; // ecx
  	*--stack = current_task->regs.edx; //edx
  	*--stack = current_task->regs.esi; //esi
  	*--stack = current_task->regs.edi; //edi
  	*--stack = current_task->regs.ebp; //ebp
  	*--stack = current_task->ds; // ds
  	*--stack = current_task->fs; // fs
  	*--stack = current_task->es; // es
  	*--stack = current_task->gs; // gs


    //old_task->regs.eip=regs.eip;
  	asm volatile("movl %%eax, %%esp;": :"a"(current_task->regs.esp));
  	asm volatile("movl %%eax, %%ss;": :"a"(current_task->ss));
  	asm volatile("popl %gs");
  	asm volatile("popl %fs");
  	asm volatile("pop %es");
  	asm volatile("popl %ds");
  	asm volatile("popl %ebp");
  	asm volatile("popl %edi");
  	asm volatile("popl %esi");
  	asm volatile("out %%al, %%dx": :"d"(0x20), "a"(0x20)); // send EoI to master PIC
  	asm volatile("popl %edx");
  	asm volatile("popl %ecx");
  	asm volatile("popl %ebx");
  	asm volatile("popl %eax");
    //asm volatile("addl $8, %esp");
  	//asm volatile("push %0"::"r"(current_task->regs.eip));
  /*  asm volatile("\
    sti; \
    jmp *%0": :"r"(current_task->regs.eip));
    //asm volatile("jmp *%0" :: "r"(current_task->regs.eip));
    asm volatile("sti");
    asm volatile("iret");/*
    saveState();
    asm volatile("mov %%esp, %%eax;":"=a"(old_task->regs.esp));
    asm volatile("mov %%eax, %%esp;"::"a"(current_task->regs.esp));
    loadState();*/
    asm volatile("sti");
    asm volatile("iret");
}

:p I am a newbie :p
The best method for accelerating a computer is the one that boosts it by 9.8 m/s2.
My OS : https://github.com/AshishKumar4/Aqeous
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Some more help on MultiTasking

Post by Brendan »

Hi,
ashishkumar4 wrote:As adviced by Brenden sir, I made a co-operative multitasking system first. But as said by others to not to use inline asm with optimizations, I tried to use nasm-only for the task_switch but I failed at it (believe me I tried a lot) So instead I made use of inlines BUT WITHOUT OPTIMIZATIONS. and guess what? IT WORKED! :D
It doesn't work; it only seems like it works because you've only found one of the problems so far (enabling optimisations breaks it) and haven't found the other problems yet.

For a simple example, imagine you're writing a kernel API function that waits for data to arrive then returns it (e.g. "getMessage()" or "read()" or something). The basic idea for these types of functions is:

Code: Select all

    while( no_data() ) {

        block_task();              // Wait for the arrival of data to unblock this task and
                                   //   cause a task switch back to this task
    }
    data = get_data_from_wherever();
    return data;                   // Return the data back to user-space
How do you intend to implement anything like this when a task switch causes an implied "return to CPL=3 without the data"?

Something causes a switch from CPL=3 to CPL=0 (which may be an IRQ or exception or SYSCALL or SYSENTER or...); the kernel does stuff (that may or may not involve one or more task switches); then when the kernel has nothing else to do it returns to CPL=3 (to whatever task happens to be the current task at the time).

Note that when a task switch happens; it's always from CPL=0 to CPL=0 and has nothing at all to do with CPL=3 in any way whatsoever.

This means (e.g.) there is never any need to load/save segment registers during task switches because the kernel's segment registers are always the same for all tasks. Something causes a switch from CPL=3 to CPL=0 (and CPL=3 segment registers are saved and kernel segment registers are set to fixed values); then the kernel does stuff (that may or may not involve task switches between tasks at CPL=0); then when the kernel has nothing else to do it returns to CPL=3 (and kernel's segment registers are discarded and not saved, and CPL=3 segment registers are loaded).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
ashishkumar4
Member
Member
Posts: 73
Joined: Wed Dec 23, 2015 10:42 pm

Re: Some more help on MultiTasking

Post by ashishkumar4 »

I haven't thought about them because I want the simplest possible multitasking (Just a scheduler) right now because I want my program to evolve. I want to understand every possible way to do one thing. Later on when I get a success doing this, I would go on to this locking and unlocking tasks stuff :p for now please help me do this first because I want to achieve success in this first, then think of other possibilities so that I can make a better code. Otherwise I wont understand it to the fullest :/ please sir, help me in my question above :p
The best method for accelerating a computer is the one that boosts it by 9.8 m/s2.
My OS : https://github.com/AshishKumar4/Aqeous
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Some more help on MultiTasking

Post by Brendan »

Hi,
ashishkumar4 wrote:please sir, help me in my question above :p
Imagine someone needs to travel 2 Km to the west, but for no sane reason they're heading towards the east and expecting people to help them with problems that are directly caused by the fact that they're heading in the wrong direction. Do you dislike the person enough to help them continue getting further and further away from their goal; or do you like the person enough to force them to go in the right direction instead of helping them make their situation worse?

You are going in the wrong direction. I don't dislike you enough to provide the "anti-help" you're asking for.


Cheers,

brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: Some more help on MultiTasking

Post by tsdnz »

Brendan wrote:Hi,
ashishkumar4 wrote:please sir, help me in my question above :p
Imagine someone needs to travel 2 Km to the west, but for no sane reason they're heading towards the east and expecting people to help them with problems that are directly caused by the fact that they're heading in the wrong direction. Do you dislike the person enough to help them continue getting further and further away from their goal; or do you like the person enough to force them to go in the right direction instead of helping them make their situation worse?

You are going in the wrong direction. I don't dislike you enough to provide the "anti-help" you're asking for.


Cheers,

brendan
Also..... You will learn a lot by figuring it out, once you are heading in the right direction.
Read the manuals on interrupts, put pen to paper and write down exactly the stack, check your code, check the assembly output.
Good luck.
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: Some more help on MultiTasking

Post by SpyderTL »

This feels like deja vu, but why do you need the value of EIP?

If it's sitting on the stack, it will still be there when you want to switch back to that thread in the future?

If you are inside a subroutine, just swap to the new stack and call RET. If you are in an interrupt handler, just swap to the new stack and call IRET.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
ashishkumar4
Member
Member
Posts: 73
Joined: Wed Dec 23, 2015 10:42 pm

Re: Some more help on MultiTasking

Post by ashishkumar4 »

lol ok i got it. not making anything now because my PC dies :'( my PSU burnt up :/
The best method for accelerating a computer is the one that boosts it by 9.8 m/s2.
My OS : https://github.com/AshishKumar4/Aqeous
ashishkumar4
Member
Member
Posts: 73
Joined: Wed Dec 23, 2015 10:42 pm

Re: Some more help on MultiTasking

Post by ashishkumar4 »

ok i got that point, not to save segment registers because it isnt needed, right? will do this once my pc is back to life again :'(
The best method for accelerating a computer is the one that boosts it by 9.8 m/s2.
My OS : https://github.com/AshishKumar4/Aqeous
Post Reply