Page 4 of 4
Re: Multitasking problem
Posted: Sat Aug 06, 2022 4:14 pm
by Octocontrabass
Re: Multitasking problem
Posted: Thu Sep 01, 2022 5:23 am
by WinExperements
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: Select all
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: Select all
void process_exit(int pid,int exitCode) {
process_getProcess(pid)->state = 1;
}
process_getProcess:
Code: Select all
struct process *process_getProcess(int pid) {
return process_findID(pid);
}
process_findID:
Code: Select all
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: Select all
// 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?
Re: Multitasking problem
Posted: Sat Sep 03, 2022 9:31 am
by WinExperements
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?
Re: Multitasking problem
Posted: Sat Sep 03, 2022 10:28 am
by Octacone
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.
Re: Multitasking problem
Posted: Wed Oct 05, 2022 1:14 pm
by WinExperements
Hello again! How i can add switching to user mode for user's tasks using Brendan's multitasking tutorial?
Re: Multitasking problem
Posted: Wed Oct 05, 2022 1:24 pm
by Octocontrabass
When you initialize the task, fill the stack with values that will make the task return to ring 3 when you switch to it.
Re: Multitasking problem
Posted: Wed Oct 05, 2022 1:51 pm
by WinExperements
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?
Re: Multitasking problem
Posted: Wed Oct 05, 2022 2:01 pm
by Octocontrabass
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.
Re: Multitasking problem
Posted: Wed Oct 05, 2022 2:11 pm
by WinExperements
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?
Re: Multitasking problem
Posted: Wed Oct 05, 2022 2:29 pm
by Octocontrabass
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.
Re: Multitasking problem
Posted: Wed Oct 05, 2022 2:49 pm
by devc1
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.
Re: Multitasking problem
Posted: Thu Oct 06, 2022 6:36 am
by Gigasoft
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.
Re: Multitasking problem
Posted: Wed Oct 12, 2022 6:16 am
by WinExperements
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: Select all
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.
Re: Multitasking problem
Posted: Wed Oct 12, 2022 11:33 am
by Octocontrabass
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.