OSDev.org
https://forum.osdev.org/

Multitasking problem
https://forum.osdev.org/viewtopic.php?f=1&t=56362
Page 4 of 4

Author:  Octocontrabass [ Sat Aug 06, 2022 4:14 pm ]
Post subject:  Re: Multitasking problem

Here's one way to do it:

Code:
uint32_t phys_addr = pte & ~0xFFF;


You'll have a hard time writing an OS if you're not already familiar with this sort of thing.

Author:  WinExperements [ Thu Sep 01, 2022 5:23 am ]
Post subject:  Re: Multitasking problem

Hello, again!
I have problem with implementing child waiting, after i run program twice, first run works but state of parent are always are "running", but second process after exit, throws to me the #PF, what is reason?
Here how i implement the process waiting:
Code:
if (runningTask->pid == 0 || pid < 0) return;
   if (!process_getProcess(pid)) {
       printf("process_wait: no such process %d, system halted\n",pid);
       return;
   }
   struct process *p = process_getProcess(pid);
   p->state = 2;
   // update pointer
   process_yield();

process_exit:
Code:
void process_exit(int pid,int exitCode) {
   process_getProcess(pid)->state = 1;
}

process_getProcess:
Code:
struct process *process_getProcess(int pid) {
   return process_findID(pid);
}

process_findID:
Code:
struct process *process_findID(int id) {
   clist_head_t *c = clist_find(task_list,process_findIdDispatcher,id);
   if (c) {
      return (struct process *)c->data;
   }
   return NULL;
}

And finally, the schedule function:
Code:
// send end of interrupt to interrupt controller
   io_writePort(PIC_SLAVE_COMMAND , 0x20);
   io_writePort(PIC_MASTER_COMMAND , 0x20);
   struct process *next_task = NULL;
   // update clocks
   clocks++;
   // don't save context on first switch
   if (!fswitch || runningTask->state == PROCESS_RUNNING) {
      runningTask->esp = stack;
   }
   if (!fswitch) {
      if (!runningTask) {
         next_task = process_findByStatus(PROCESS_RUNNING);
      } else {
         next_task = process_findNextByStatus(PROCESS_RUNNING,runningTask->lAddr);
      }
   }
   if (next_task == NULL) {
      // first switch
      next_task = process_findByStatus(PROCESS_RUNNING);
   }
   if (next_task == NULL) {
      printf("Next task null\n");
      return stack;
   }
   if (runningTask->state == PROCESS_KILLING) {
      if (runningTask->parent != 0) { // idle task hasn't waiting for any pid
         struct process *parent = process_findID(runningTask->parent);
         if (parent->state != PROCESS_WAIPID) {
            printf("Cannot unlock parent: Parent didn't waiting for any child PID: %d\n",runningTask->pid);
         } else {
            parent->state = PROCESS_RUNNING;
            fswitch = true;
            return  idle->esp;
         }
         curTasks--;
         arch_destroyStack(runningTask->esp);
         pmml_free(runningTask->esp);
         pmml_free((void *)runningTask->dir);
         if (runningTask->kernelESP != 0) {
            pmml_free((void *)runningTask->kernelESP);
         }
         if (runningTask->page_start != 0) {
            pmml_freePages((void *)runningTask->page_start,runningTask->pages);
         }
         clist_delete_entry(task_list,(clist_head_t *)runningTask->lAddr);
         pmml_free(runningTask);
      }
   }
   if (next_task->wait_time != 0) {
      next_task->wait_time--;
      fswitch = true;
      return stack;
   }
   tss_set_stack(0x10,next_task->kernelESP);
   vmm_switch((int *)next_task->dir);
   fswitch = false;
   runningTask = next_task;
   return runningTask->esp;
}

Screenshot of error in attachments.
EDIT: I fixed #PF, but now i have #GP with error code 1, i just replace process_yield code to waiting for next interrupt, also i fixed the "ready" state bug
UPDATE 2: I fixed the #GP, but now tasks always points to idle, maybe problem in context saving in process_schedule?

Attachments:
QEMU 01.09.2022 14_20_27.png
QEMU 01.09.2022 14_20_27.png [ 10.39 KiB | Viewed 1157 times ]

Author:  WinExperements [ Sat Sep 03, 2022 9:31 am ]
Post subject:  Re: Multitasking problem

Hello!
And first about previous post, after this post i edited my scheduler method and add context save/switch.
And i have some problem: when i receive keyboard interrupt, the handler correctly returns to the process wait key function, but if this function returns(it's must return key if it pressed) it's jumps to 0x0000010 why?

Author:  Octacone [ Sat Sep 03, 2022 10:28 am ]
Post subject:  Re: Multitasking problem

WinExperements wrote:
but if this function returns(it's must return key if it pressed) it's jumps to 0x0000010 why?


It jumps to 0x10 because that's the "last" thing that was stored on the stack. Inspect it to make sure it's not corrupted.

Author:  WinExperements [ Wed Oct 05, 2022 1:14 pm ]
Post subject:  Re: Multitasking problem

Hello again! How i can add switching to user mode for user's tasks using Brendan's multitasking tutorial?

Author:  Octocontrabass [ Wed Oct 05, 2022 1:24 pm ]
Post subject:  Re: Multitasking problem

When you initialize the task, fill the stack with values that will make the task return to ring 3 when you switch to it.

Author:  WinExperements [ Wed Oct 05, 2022 1:51 pm ]
Post subject:  Re: Multitasking problem

Octocontrabass wrote:
When you initialize the task, fill the stack with values that will make the task return to ring 3 when you switch to it.

How i can fill correctly it, because i fill it with some parameters to my user startup function, that switches to user mode and jumps to the entry point, but after the restoring it from the saved state, it's switches to kernel mode. Do i need to change my switch function?

Author:  Octocontrabass [ Wed Oct 05, 2022 2:01 pm ]
Post subject:  Re: Multitasking problem

Task switches only happen in ring 0. If the task itself is meant to run in ring 3, then the saved/restored state should be inside an IRQ or syscall handler that will eventually return to ring 3.

If that's not happening, something is wrong with how you're switching tasks.

Author:  WinExperements [ Wed Oct 05, 2022 2:11 pm ]
Post subject:  Re: Multitasking problem

Octocontrabass wrote:
Task switches only happen in ring 0. If the task itself is meant to run in ring 3, then the saved/restored state should be inside an IRQ or syscall handler that will eventually return to ring 3.

As I understand it, the context switch should be called in an IRQ or system call that will return to ring 3? Or what?

Author:  Octocontrabass [ Wed Oct 05, 2022 2:29 pm ]
Post subject:  Re: Multitasking problem

A ring 3 task can only get to ring 0 by a syscall or an IRQ, so a ring 3 task can only call the context switch in a syscall or IRQ handler.

When some other task calls the context switch, the ring 3 task will resume in ring 0 in the syscall or IRQ handler.

Author:  devc1 [ Wed Oct 05, 2022 2:49 pm ]
Post subject:  Re: Multitasking problem

To switch to a user mode task from an IRQ you simply must save and restore the page table and segment registers CS, DS, SS, ES, GS, FS. When you select your task you must build a stack frame then "iret" and congrats, you have made it to user mode.

This must happen when CPL=0 (kernel mode), probably inside an IRQ handler.

Author:  Gigasoft [ Thu Oct 06, 2022 6:36 am ]
Post subject:  Re: Multitasking problem

There is a type of design called a single stack kernel, sometimes used for microkernels. In this case, the task switching code operates on the interrupt return frame. This is not by definition "wrong", but comes with its own set of challenges. On the plus side, it saves memory. There is a version of the L4 Pistachio kernel that does this, as does the Playstation 1 BIOS. Most kernels uses a separate stack for each thread, and task switching only involves switching stacks and saving and loading a few registers.

Author:  WinExperements [ Wed Oct 12, 2022 6:16 am ]
Post subject:  Re: Multitasking problem

Hello! I am have again problem, that my keyboard wait key function returns to 0x10. How i can correctly save the ESP for tasks?
Here the saving code:
Code:
void arch_saveContext(struct process *forWho,registers_t *stack) {
    registers_t *f = (registers_t *)forWho->esp;
    f->eax = stack->eax;
    f->ecx = stack->ecx;
    f->edx = stack->edx;
    f->ebx = stack->ebx;
    f->ebp = stack->ebp;
    f->esi = stack->esi;
    f->edi = stack->edi;
    f->eip = stack->eip;
    f->eflags = stack->eflags;
    f->useresp = stack->useresp;
}

My context switching function used iret instruction and useresp field to switch to task, before it i only loads register values from the registers_t structure.

Author:  Octocontrabass [ Wed Oct 12, 2022 11:33 am ]
Post subject:  Re: Multitasking problem

I already gave you an example of how to perform a context switch in another thread. The code simultaneously saves the current task's ring 0 stack pointer to the provided location and sets ESP to the new task's ring 0 stack pointer.

When you have one ring 0 stack per thread, you don't need to save or restore anything except the ring 0 stack pointer.

Page 4 of 4 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/