I need more about creating a task/process

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.
Kim

Re:I need more about creating a task/process

Post by Kim »

You have to init the stack before you enable interrupts / timer.
With other words the first task handle call.

For a ring0 task:

Code: Select all

task[0].task_esp <- unsigned long *task_esp;

task[0].task_esp = kallocpage(1, kernel_page) + page_size; //your paging manager maps a pyshical page in the address space.
//eflags
*task[0].task_esp-- = 1 << 9;
//cs
*task[0].task_esp-- = mycodeselector;
//eip
*task[0].task_esp-- = &mytaskentrypoint;
//eax
*task[0].task_esp-- = 0;
//ecx
*task[0].task_esp-- = 0;
//edx
*task[0].task_esp-- = 0;
//ebx
*task[0].task_esp-- = 0;
//esp note: the popa instruction doesn't pop esp off only //increases esp
*task[0].task_esp-- = 0;
//ebp
*task[0].task_esp-- = 0;
//esi
*task[0].task_esp-- = 0;
//edi
*task[0].task_esp-- = 0;
//ds
*task[0].task_esp-- = mydataselector;
//es
*task[0].task_esp-- = mydataselector;
//fs
*task[0].task_esp-- = mydataselector;
//gs
*task[0].task_esp = mydataselector;
calpis

Re:I need more about creating a task/process

Post by calpis »

This is my context_switch code. I am trying to change it and see if it works...I got alot of bizarrard result...none of them works. Please help me~! I am so stuck.

Code: Select all

context_switch:
   cld
   ;;cli
   pushad ;;pusha
   ;;pushfd  
   push ds
   push es
   push fs
   push gs
   ;;--------------
   mov eax, [current_task_esp]
   mov [eax], esp
   ;;lea eax, [kstack_end] ;;DOn't know why i need this.
   mov esp,eax
   ;;--------------
   mov [current_task_esp],esp   
   call scheduler_handler
   ;;mov esp, [current_task_esp]
   
   mov eax,[current_task_esp]
   mov esp,[eax]
   mov ebx, [eax+8]
   mov [tss+4], ebx
   mov al, 0x20
   out 0x20, al
   
   pop gs
   pop fs
   pop es
   pop ds
   ;;popfd
   popad ;;popa
   iretd

Thank you
calpis

Re:I need more about creating a task/process

Post by calpis »

I have init a stack on every process I create including the first, because I basically use the same method for all process.

Can I just ask, do I need to create a new global stack(for kernel only on the first task? Or do I need to do it everytime I create a new process.

What the stack is used for?

thank you.
P.S. I also had this error message when I did the switch manually, from keyboard input.
>>PANIC<< fetch_raw_descriptor: LDTR.valid=0
calpis

Re:I need more about creating a task/process

Post by calpis »

I think I am getting closer...my bochs freeze only...
but I get this. I had this problem before at this post
http://www.mega-tokyo.com/forum/index.p ... 6#msg68646.

But only with a 31 and limit 23 instead. This time is too big~

Code: Select all

00007495963i[CPU  ] selector->index*8 + 7 = 1055
00007495963i[CPU  ] gdtr.limit = 31
00007495963i[CPU  ] fetch_raw_descriptor: GDT: index > limit
Help please...Thank you
Kim

Re:I need more about creating a task/process

Post by Kim »

He, your getesp function what does it do?
It should return an non used page in the address space with a physical page mapped to it, that can be used for the stack.
I hope your not doing mov eax, esp as return value...
calpis

Re:I need more about creating a task/process

Post by calpis »

Yes it is. Why? But I think I only use it in my tss or gdt or somthing.

Code: Select all

getgs:
???mov eax, gs
???ret

getfs:
???mov eax, fs
???ret

getebp:
???mov eax, ebp
???ret

getesp:
???mov eax, esp
???ret

Most of are the same. Why? Whats wrong? Altho, it doesn't return correct values sometime I feel.
Kim

Re:I need more about creating a task/process

Post by Kim »

Well in your create_task function you are doing,

Code: Select all

this_task[0].task_esp = getesp();
this is never going to work, you are using your current stack for the task!

If you use different address spaces for the tasks, you will have to allocate a page in the task his address space... can't help you much with this, because i only implemented kernel threading and not tasks in my learning kernel :)

Code: Select all

this_task[0].task_esp = kpagealloc(stack_size, task_page_flags) + stacksize;
You better start with some fresh code and try to get one address space threading to work, it only took me an hour of three to read and get it working, its only a small asm stub, timer handle of a couple of lines, and some code to init a thread.
Multitasking is the next step...
calpis

Re:I need more about creating a task/process

Post by calpis »

aha~! That was from my old code. But my task point to a stack like so.

Code: Select all

unsigned int create_task(void (*function)(), unsigned int priority)//, priority)
{
   //store all the regs into task_state_info by save reg
   interrupt_off();
   kprintf("\n---- Creating task---- \n");
   unsigned int *task_stack;
   kstack_end = 0;
   if(!first_task )
   {

      free_id += 1;
         /*-------------------------------<<< remember to check this!!! And add recovery used number.*/
   }
   else
   {
      free_id = 0;
   }
   
   task_stack = &kstacks[free_id][(unsigned int)kstack_top];
   *task_stack--;
   *task_stack--=0x0202;
   *task_stack--=0x08;
   *task_stack--=function;
   *task_stack--=0;    //ebp
   *task_stack--=0;   //esp
   *task_stack--=0;   //edi
   *task_stack--=0;   //esi
   *task_stack--=0;   //edx
   *task_stack--=0;   //ecx
   *task_stack--=0;   //ebx
   *task_stack--=0;   //eax
   *task_stack--=0x10;   //ds
   *task_stack--=0x10;   //es
   *task_stack--=0x10;   //fs
   *task_stack--=0x10;   //gs

   struct task_control_block *this_task = (struct task_control_block *)page_allocator(sizeof(struct task_control_block));
   
   this_task[0].task_esp = (unsigned int)task_stack;//(unsigned int *)task_stack;160805//getesp();
   this_task[0].task_ss = 0x10;
   this_task[0].task_kstack = (unsigned int) &kstacks[free_id][(unsigned int)kstack_top];  //rows, columns
   
   this_task[0].task_time_to_run = 10;
   this_task[0].task_cr3 = first_page_directory;
   this_task[0].task_priority = priority;
   this_task[0].task_number = free_id ;

   kprintf(" this_task.task_kstacks:%h task_stack: %h\n",this_task[0].task_kstack, task_stack);

   kprintf("functions:%h %h %h\n",function, &function, (unsigned int) function);
   
    interrupt_on();
    kprintf("------Task created------\n.");
   return (unsigned int) this_task;
}

As I said, I use it to create my very first task where you mention about initialize a stack before hand. And I use it for creating other tasks for testing.

I asked about on my last post or 2, about initialize the stack like above, do I need to do just for the first task? or do I do it in every task. Thats where I got confuse.

Also, any idea how to fix the selector->index*8 problem?
Here is my context switch code in case you are interested to help with that too. I use switch 2 simple tasks by pressing key.

Thank you~ You are my only hope at the moment~

Code: Select all

context_switch:
   cld
   ;;cli
   pushad ;;pusha
   ;;pushfd  
   push ds
   push es
   push fs
   push gs
   ;;--------------
   ;;mov eax, [current_task_esp]
   ;;mov [eax], esp
   ;;lea eax, [kstack_end]
   ;;mov esp,eax
   ;;--------------
   
   mov [current_task_esp],esp   
   call scheduler_handler
   mov esp, [current_task_esp]
   
   ;;mov eax,[current_task_esp]
   ;;mov esp,[eax]
   ;;mov ebx, [eax+8]
   ;;mov [tss+4], ebx
   ;;mov al, 0x20
   ;;out 0x20, al
   
   pop gs
   pop fs
   pop es
   pop ds
   ;;popfd
   popad ;;popa
   iretd;;d
calpis

Re:I need more about creating a task/process

Post by calpis »

Ha ha....T_T

I keep getting lots of errors.

I made some changes to the stack. and also using ret instead of iretd.

Help please~ T_T
ret, I get this

Code: Select all


00006945968e[CPU  ] seg = DS
00006945968e[CPU  ] seg->selector.value = 0000
00006945968e[CPU  ] write_virtual_checks: valid bit = 0
00006945968e[CPU  ] CS: 0008
00006945968e[CPU  ] IP: 0000

iret and iretd, I then get this...and realize that I have the registers set to 0?

Code: Select all

00021975967p[CPU  ] >>PANIC<< iret: return CS selector null
00021975967i[SYS  ] Last time is 1124497417
00021975967i[CPU  ] protected mode
00021975967i[CPU  ] CS.d_b = 32 bit
00021975967i[CPU  ] SS.d_b = 32 bit
00021975967i[CPU  ] | EAX=00000000  EBX=00000000  ECX=00000000  EDX=00000000
00021975967i[CPU  ] | ESP=0012e030  EBP=00000000  ESI=00000000  EDI=00000000
00021975967i[CPU  ] | IOPL=0 NV UP DI PL NZ AC PE NC
00021975967i[CPU  ] | SEG selector     base    limit G D
00021975967i[CPU  ] | SEG sltr(index|ti|rpl)     base    limit G D
00021975967i[CPU  ] |  DS:0000( 0000| 0|  0) 00000000 000fffff 1 1
00021975967i[CPU  ] |  ES:0000( 0000| 0|  0) 00000000 000fffff 1 1
00021975967i[CPU  ] |  FS:0000( 0000| 0|  0) 00000000 000fffff 1 1
00021975967i[CPU  ] |  GS:0000( 0000| 0|  0) 00000000 000fffff 1 1
00021975967i[CPU  ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00021975967i[CPU  ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00021975967i[CPU  ] | EIP=001002a7 (001002a6)
00021975967i[CPU  ] | CR0=0xe0000011 CR1=0x00000000 CR2=0x00000000
00021975967i[CPU  ] | CR3=0x0009c000 CR4=0x00000000
00021975967i[     ] restoring default signal behavior
00021975967i[CTRL ] quit_sim called with exit code 1

Kim

Re:I need more about creating a task/process

Post by Kim »

You have to init the stack for all tasks before they run because, if it isn't you will pop invalid data of the stack when switching.

Can you post your scheduler handler.
calpis

Re:I need more about creating a task/process

Post by calpis »

My context switch that I think is correct.

Code: Select all

context_switch:
   ;;cld
   cli
   pusha ;;pusha
   ;;pushf 
   push ds
   push es
   push fs
   push gs
   ;;--------------
   ;;mov eax, [current_task_esp]
   ;;mov [eax], esp
   ;;lea eax, [kstack_end]
   ;;mov esp,eax
   ;;--------------
   
   mov [current_task_esp],esp   
   call scheduler_handler
   ;;mov esp, [current_task_esp];;[current_task_esp];;changed 200805
   mov esp, [current_task_esp];;[current_task_stack_end]newly added
   
   ;;mov eax,[current_task_esp]
   ;;mov esp,[eax]
   ;;mov ebx, [eax+8];;mov ebx, [eax+8]
   ;;mov [tss+4], ebx
   ;;mov al, 0x20
   ;;out 0x20, al
   
   
   
   pop gs
   pop fs
   pop es
   pop ds
   ;;popf
   popa ;;popa
   ;;iretd;;d

   ret

Its just a very simple round robin scheduler. It does switches .

Code: Select all

void scheduler_handler(void)
{
   if(task_queue[(int)(task_pos + 1)] !=0)  //tested!
      task_pos = task_pos + 1;
   else
      task_pos = 0;
   
   current_task = (struct task_control_block *)task_queue[task_pos];
   
   
   current_task_esp = (unsigned int *)current_task[0].task_esp;//(unsigned int )current_task[0].task_esp; ///problems
   current_task_stack_end =(unsigned int *) current_task[0].task_stack_end;
   
}
And this to add a single task.

Code: Select all

void add_task(unsigned int *task)
{
   interrupt_off();
   
   if(first_task)
   {
      kprintf(" \n ---first task initializing---\n");
      //task_tail = task_head = 
      task_queue = (unsigned int *) page_allocator((sizeof(task_queue))*255);
      task_queue[0] =  (unsigned int)task;
      num_of_tasks = 1;
      first_task = 0;
      kprintf(" The task_queue[%d]:%h\n",task_pos, task_queue[task_pos]);
      kprintf("  ---first task added---\n\n");


   }
   else
   {
      //current_task = task;
      kprintf(" \n ---Adding task---\n");
      task_pos+=1;
      task_queue[task_pos] = (unsigned int) task;
      //task_tail = task_queue[task_pos];
      //task_head = task_queue[0];
      num_of_tasks += 1;
      kprintf(" The task_queue[%d]:%h\n",task_pos, task_queue[task_pos]);
      kprintf("  ---Task added---\n\n");
      
   }
   
   
   int i;
      for (i = 0; i<5; i++)
         kprintf(" task_queue[%d]:%h\n",i,task_queue[i]);
      
   
   interrupt_on();

   
}

Thank you~
Kim

Re:I need more about creating a task/process

Post by Kim »

You forgot to save the task his stack pointer:

Code: Select all

void scheduler_handler(void)
{

   //save running task his stack
   //if current_task is null then its the first time we taskswitch
   //so don't save stack pointer then
   if (current_task != NULL) then
        current_task[0].task_esp = current_task_esp;

   //let next task run
   if(task_queue[(int)(task_pos + 1)] !=0)
      task_pos = task_pos + 1;
   else
      task_pos = 0;
   
   //switch task
   current_task = (struct task_control_block *)task_queue[task_pos];
   
   
   current_task_esp = (unsigned int *)current_task[0].task_esp;
   current_task_stack_end =(unsigned int *) current_task[0].task_stack_end;
}
calpis

Re:I need more about creating a task/process

Post by calpis »

Hi, thanks, It kind of switched the first task to first task, then I think tries to switch to the second then crush. I guess there its something wrong with my test kernel.

This is like my test code, after the kernel finish loading.

I first create the main task and attach a task to the queue.
Then I create another task and attach it as well.

Here is the thing, the task that I attached to the code, doesn't really execute. I don't understand. Its a simple print statment in loop really.
And I tried to only run attach one task and run. It I think switches fine. But do nothing really.

Boch gives me this error when it died.

Code: Select all

00022596638e[CPU  ] seg = DS
00022596638e[CPU  ] seg->selector.value = 0000
00022596638e[CPU  ] write_virtual_checks: valid bit = 0
00022596638e[CPU  ] CS: 0008
00022596638e[CPU  ] IP: 0000
00034734000p[MGUI ] >>PANIC<< POWER button turned off.
00034734000i[SYS  ] Last time is 1124557584
00034734000i[CPU  ] protected mode
00034734000i[CPU  ] CS.d_b = 32 bit
00034734000i[CPU  ] SS.d_b = 32 bit
00034734000i[CPU  ] | EAX=00000007  EBX=00000000  ECX=00000000  EDX=000003d5
00034734000i[CPU  ] | ESP=0012ffdc  EBP=00000000  ESI=00000000  EDI=00000000
00034734000i[CPU  ] | IOPL=0 NV UP DI PL NZ NA PO NC
00034734000i[CPU  ] | SEG selector     base    limit G D
00034734000i[CPU  ] | SEG sltr(index|ti|rpl)     base    limit G D
00034734000i[CPU  ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00034734000i[CPU  ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00034734000i[CPU  ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00034734000i[CPU  ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00034734000i[CPU  ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00034734000i[CPU  ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00034734000i[CPU  ] | EIP=00100fdb (00100fdb)
00034734000i[CPU  ] | CR0=0xe0000011 CR1=0x00000000 CR2=0x00000000
00034734000i[CPU  ] | CR3=0x0009c000 CR4=0x00000000
00034734000i[     ] restoring default signal behavior
00034734000i[CTRL ] quit_sim called with exit code 1
Thanks for your help kim~
calpis

Re:I need more about creating a task/process

Post by calpis »

Hi, I have got stack switch and it execute the first task. But it only prints ten statement then stopped. I thought it could be that I don't have a scheduler. So added one more task and added a scheduler.

But after that. I get a page fault exception 14. I read about it, the only thing I learnt its that it will push a page on the stack, then to CR2. and something about the last bit being set to 0. But I don't know how to tackle it. As I am using a physical page allocator with 4MB to work with.

Any idea?

Any help would be greato~ thank you~

Code: Select all

00000330074i[KBD  ] reset-disable command received
00000345000e[VGA  ] character height = 1, skipping text update
00002367063i[BIOS ] ata0-0: PCHS=3047/16/63 translation=large LCHS=761/64/63
00002742677i[BIOS ] int15: Func 24h, subfunc 01h, A20 gate control not supported
00002756030i[BIOS ] int13_harddisk: function 41, unmapped device for DL=81
00002760554i[BIOS ] int13_harddisk: function 08, unmapped device for DL=81
00002765088i[BIOS ] *** int 15h function AX=00C0, BX=0000 not yet supported!
00002769568i[BIOS ] *** int 15h function AX=5300, BX=0000 not yet supported!
00002773983i[BIOS ] *** int 15h function AX=5304, BX=0000 not yet supported!
00096386497e[CPU  ] enter() with level > 0. The emulation of this instruction may not be complete.  This warning will be printed only once per bochs run.
00145048500i[KBD  ] internal keyboard buffer full, ignoring scancode.(cd)
00145196500i[KBD  ] internal keyboard buffer full, ignoring scancode.(e0)
00145196500i[KBD  ] internal keyboard buffer full, ignoring scancode.(4d)

00181043000p[MGUI ] >>PANIC<< POWER button turned off.
00181043000i[SYS  ] Last time is 1124675108
00181043000i[CPU  ] protected mode
00181043000i[CPU  ] CS.d_b = 32 bit
00181043000i[CPU  ] SS.d_b = 32 bit
00181043000i[CPU  ] | EAX=00000007  EBX=0012cff8  ECX=000b8000  EDX=000003d5
00181043000i[CPU  ] | ESP=0012cfe4  EBP=fffffffc  ESI=00000000  EDI=00000000
00181043000i[CPU  ] | IOPL=0 NV UP DI PL NZ NA PE NC
00181043000i[CPU  ] | SEG selector     base    limit G D
00181043000i[CPU  ] | SEG sltr(index|ti|rpl)     base    limit G D
00181043000i[CPU  ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00181043000i[CPU  ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00181043000i[CPU  ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00181043000i[CPU  ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00181043000i[CPU  ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00181043000i[CPU  ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00181043000i[CPU  ] | EIP=00100ff8 (00100ff8)
00181043000i[CPU  ] | CR0=0xe0000011 CR1=0x00000000 CR2=0xfffffffc
00181043000i[CPU  ] | CR3=0x0009c000 CR4=0x00000000
00181043000i[     ] restoring default signal behavior
00181043000i[CTRL ] quit_sim called with exit code 1
calpis

Re:I need more about creating a task/process

Post by calpis »

I am trying to my whole scheduler in my timer handler.

And I get this: Its a general protection faults 13.

Code: Select all

00004341284e[CPU  ] load_seg_reg: GDT: GS: index(0606) > limit(00001f)
I am running out idea la~ thanks in advance
Post Reply