Multitasking problem

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.
WinExperements
Member
Member
Posts: 97
Joined: Thu Jul 14, 2022 9:45 am
Contact:

Multitasking problem

Post by WinExperements »

Hello i am new in multitasking, and aften base implementation of it using BrokenThrorn tutorial, i receive the invalid desriptor exception, when trying to restore saved context. There are my ISR handler for timer:

Code: Select all

[GLOBAL scheduler_irq]
extern process_schedule
extern runningStack
scheduler_irq:
	cli
	pusha
	mov eax,[runningStack]
	cmp eax,0
	jz _scheduler_exit
	push ds
	push es
	push fs
	push gs
	mov ax,0x10
	mov ds,ax
	mov es,ax
	mov fs,ax
	mov gs,ax
	mov eax,[runningStack]
	mov eax,esp
	call process_schedule
	mov eax,[runningStack]
	mov esp,eax
	pop gs
	pop fs
	pop es
	pop ds
	_scheduler_exit:
	popa
	mov al,0x20
	out 0x20,al
	sti
	iret
The process_schedule function do nothing.
The runningStack is a pointer to stack of running task.
Running task set to idle.
Idle task just in infile loop prints "PE", and when it trying to restore saved context, process throws GPF
There are the screenshot of problem:
Attachments
VirtualBox_other2_14_07_2022_19_00_13.png
VirtualBox_other2_14_07_2022_19_00_13.png (6.92 KiB) Viewed 4002 times
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Multitasking problem

Post by Octocontrabass »

WinExperements wrote:

Code: Select all

	mov eax,[runningStack]
	mov eax,esp
	call process_schedule
	mov eax,[runningStack]
	mov esp,eax
What is this code supposed to do? It's definitely not doing what you want.
WinExperements wrote:

Code: Select all

	popa
	mov al,0x20
	out 0x20,al
Your interrupt handler modifies EAX after restoring the saved value, so every time this interrupt occurs it clobbers EAX in the running program.
WinExperements wrote:

Code: Select all

	sti
	iret
The effect of STI is delayed until after IRET completes, but IRET pops the value of EFLAGS off the stack, so STI has no effect at all. If you want interrupts to be enabled after IRET, you must set that in the copy of EFLAGS on the stack.
WinExperements
Member
Member
Posts: 97
Joined: Thu Jul 14, 2022 9:45 am
Contact:

Re: Multitasking problem

Post by WinExperements »

Thanks yes i update the source, i updated the code like in wyoos tutorials, but the stack passed to the function are invalid, and if i don't call the scheduler method timer irq works fine, also the task didn't work aften second timer interrupt.
Is there are still problems with the stack?
There are my updated handler:

Code: Select all

	cli
	pusha
	mov ax,0x10
	mov ds,ax
	mov es,ax
	mov fs,ax
	mov gs,ax
	push esp    ; Current stack as argument
	call process_schedule
        add esp,4
        mov esp,eax
	_scheduler_exit:
	mov al,0x20
	out 0x20,al
        popa
	iret
Edit: It's also broken argument passing, still have GPF
Is it's problem in my IRQ handler?
There are my process_schedule function:

Code: Select all

int process_schedule(int stack) {
	// debug print segments
	//printf("Code segment: %x\n",stack);
	if (totalTasks == 0) {
		return;
	}
	if (currentPid >= 0) {
		//printf("Saving context\n");
		processList[currentPid].esp = stack;
	}
	if (currentPid++ > totalTasks) {
		currentPid %= totalTasks;
	}
	return processList[currentPid].esp;
}
Last edited by WinExperements on Fri Jul 15, 2022 2:38 pm, edited 1 time in total.
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Multitasking problem

Post by Octocontrabass »

Code: Select all

	cli
An interrupt handler should never start with CLI. If you want interrupts disabled at the start of your interrupt handler, use an interrupt gate in your IDT.

Code: Select all

	mov ax,0x10
	mov ds,ax
	mov es,ax
	mov fs,ax
	mov gs,ax
You load ring 0 selectors into the segment registers at the start of your interrupt handler, but you don't restore ring 3 selectors before IRET.

Code: Select all

        add esp,4
This instruction does nothing.
WinExperements wrote:Edit: It's also broken argument passing, still have GPF
What does "broken argument passing" mean? Can you provide any other information about the #GP?
WinExperements
Member
Member
Posts: 97
Joined: Thu Jul 14, 2022 9:45 am
Contact:

Re: Multitasking problem

Post by WinExperements »

First about the argument passing:
Aften iret instruction the argument to printf function are setted to invalid address.
And About GPF:
I don't have currently bochs, only error code
There are QEMU logs about it:

Code: Select all

check_exception old: 0xffffffff new 0xd
     3: v=0d e=e984 i=0 cpl=0 IP=0008:0010191a pc=0010191a SP=0010:00000020 env->regs[R_EAX]=f000ff53
EAX=f000ff53 EBX=f000ff53 ECX=f000ff53 EDX=f000ff54
ESI=f000ff53 EDI=f000ff73 EBP=f000e2c3 ESP=00000020
EIP=0010191a EFL=00000016 [----AP-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =002b 00108060 00000068 0000e900 DPL=3 TSS32-avl
GDT=     00108020 0000002f
IDT=     00108100 000007ff
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=00000004 CCD=00002000 CCO=ADDL
EFER=0000000000000000
check_exception old: 0xffffffff new 0xd
     4: v=0d e=f880 i=0 cpl=0 IP=0008:07f91302 pc=07f91302 SP=0010:ffffffc4 env->regs[R_EAX]=8966ef00
EAX=8966ef00 EBX=4866edfa ECX=f00053fe EDX=0000000d
ESI=76fdf883 EDI=f000ff74 EBP=f000e2c3 ESP=ffffffc4
EIP=07f91302 EFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =002b 00108060 00000068 0000e900 DPL=3 TSS32-avl
GDT=     00108020 0000002f
IDT=     00108100 000007ff
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=8966ef00 CCD=8966ef00 CCO=ADDB
EFER=0000000000000000
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Multitasking problem

Post by Octocontrabass »

WinExperements wrote:

Code: Select all

		return;
If you don't see a compiler warning about this line of code in your process_schedule function, you need to turn on more compiler warnings.

Then you need to fix all of the warnings.
WinExperements
Member
Member
Posts: 97
Joined: Thu Jul 14, 2022 9:45 am
Contact:

Re: Multitasking problem

Post by WinExperements »

Octocontrabass wrote:
WinExperements wrote:

Code: Select all

		return;
If you don't see a compiler warning about this line of code in your process_schedule function, you need to turn on more compiler warnings.

Then you need to fix all of the warnings.
Thank you i fix this problems, but i still have #GP with error codes: e894 and f880, when i trying to restore last stack, and aften second calling the interrupt, the process_schedule argument set to random address.
Last edited by WinExperements on Fri Jul 15, 2022 3:09 pm, edited 1 time in total.
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Multitasking problem

Post by Octocontrabass »

WinExperements wrote:Thank you i fix this problems,
Can I see how you fixed them?
WinExperements
Member
Member
Posts: 97
Joined: Thu Jul 14, 2022 9:45 am
Contact:

Re: Multitasking problem

Post by WinExperements »

Octocontrabass wrote:
WinExperements wrote:Thank you i fix this problems,
Can I see how you fixed them?
Oh sorry i mean the process_schedule function, not the problem
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Multitasking problem

Post by Octocontrabass »

Yes, that's what I'm talking about. Can I see how you fixed process_schedule? The version you posted earlier was returning a corrupt stack pointer (take a look at ESP in your QEMU logs) and the corrupt stack pointer caused all of the other problems you saw.
WinExperements
Member
Member
Posts: 97
Joined: Thu Jul 14, 2022 9:45 am
Contact:

Re: Multitasking problem

Post by WinExperements »

Octocontrabass wrote:Yes, that's what I'm talking about. Can I see how you fixed process_schedule? The version you posted earlier was returning a corrupt stack pointer (take a look at ESP in your QEMU logs) and the corrupt stack pointer caused all of the other problems you saw.
First about my fix: I only replace "return" to "return stack", think's that it fix the problem, but now i have the reason and the problem caller, now i try to fix that by debugging.
WinExperements
Member
Member
Posts: 97
Joined: Thu Jul 14, 2022 9:45 am
Contact:

Re: Multitasking problem

Post by WinExperements »

Yes i found the problem. The saved stack sets to 0. This is a reason why i got the error.
To find the reason i use temp variable named as 'lastFrame'.
The variable before saving:

Code: Select all

(gdb) p lastFrame 
$3 = (stackFrame *) 0x10bf70 <prc_stack+16208>
And the same variable but, after the saving:

Code: Select all

(gdb) p lastFrame 
$1 = (stackFrame *) 0x0
(gdb) p *lastFrame 
$2 = {eax = 4026597203, ebx = 4026597203, ecx = 4026589891, edx = 4026597203, esi = 4026597203, edi = 4026597204, esp = 4026597203, 
  ebp = 4026597203, eip = 4026597029, cs = 4026591623, flags = 4026586170}
But there are one problem: I can't find reason why it's happining.
Edit: Yes i finally fix it.
The problem is in my process_schedule currentPid check, process schedule method return null stack from empty process.
There are updated process_schedule method:

Code: Select all

stackFrame *process_schedule(stackFrame *stack) {
	if (totalTasks == 0) {
		return stack;
	}
	if (currentPid >= 0) {
		//printf("Saving context\n");
		processList[currentPid].esp = stack;
		runningTask = &processList[currentPid];
		lastFrame = processList[currentPid].esp;
	}
	if (++currentPid >= totalTasks) {
		currentPid %= totalTasks;
	}
	runningTask = &processList[currentPid];
	lastFrame = processList[currentPid].esp;
	return processList[currentPid].esp;
}
WinExperements
Member
Member
Posts: 97
Joined: Thu Jul 14, 2022 9:45 am
Contact:

Re: Multitasking problem

Post by WinExperements »

Hello again, i have problem with user space tasks.
If i create only one task with user mode segments it's works fine, but if i set the user mode registers to other tasks, the switch works fine too, but aften saving the last task state, the registers address point always to the last task.
What i do wrong?
Here my task creation function:

Code: Select all

struct process *process_create(void (*entryPoint)(),bool isUser,char *name) {
	struct process *p = process_allocateProcess();
	if (p->used) {
		printf("%s: %d\n",__func__,p->pid);
		stackFrame *frame = (pmml_alloc(true))-sizeof(stackFrame);
		frame->flags = 0x202;
		frame->cs    = (isUser ? 0x1b : 0x8);
 		frame->eip   = (uint32_t)entryPoint;
 		frame->ebp   = 0;
  		frame->esp   = 0;
  		frame->edi   = 0;
  		frame->esi   = 0;
  		frame->edx   = 0;
  		frame->ecx   = 0;
  		frame->ebx   = 0;
  		frame->eax   = 0;
  		frame->ds    = (isUser ? 0x23 : 0x10);
		frame->es = frame->ds;
		frame->fs = frame->ds;
		frame->gs = frame->ds;
		frame->ss = frame->ds;
		frame->usersp = (isUser ? ((int)pmml_alloc(true)+1024) : 0);
		p->esp = frame;
		p->name = name;
		processList[p->pid].esp = frame;
		printf("Process %d, user stack: %x\n",p->pid,frame->usersp);
	}
	return p;	// not implemented
}
Here my schedule function:

Code: Select all

stackFrame *process_schedule(stackFrame *stack) {
	// don't save context on first switch
	if (!scs.fswitch) {
		processList[scs.threadndx].esp = stack;
	}
	if (!scs.fswitch) {
		for (scs.threadndx = (scs.threadndx+1) & 0xf; !processList[scs.threadndx].used; scs.threadndx = (scs.threadndx +1) & 0xf);
	}
	scs.fswitch = false;
	stackFrame *fr = processList[scs.threadndx].esp;
	return fr;
}
scs struct:

Code: Select all

typedef struct _state {
	bool fswitch; 	// first switchk
	uint32_t threadndx; 	// index of thread
} state;
state scs;
And finally the irq handler:

Code: Select all

scheduler_irq:
	pusha
  push ds
  push es
  push fs
  push gs
	mov ax,0x10
	mov ds,ax
	mov es,ax
	mov fs,ax
	mov gs,ax
  push esp
	call process_schedule
  cmp eax,0
  jz _scheduler_error
  mov esp,eax
  pop gs
  pop fs
  pop es
  pop ds
	_scheduler_exit:
	mov al,0x20
	out 0x20,al
  popa
	iret
  _scheduler_error:
  push _schedulerError
  push _schedulerName
  push _schedulerFile
  call panic

section .data
_schedulerError db "Returned stack null",0
_schedulerName db "scheduler_irq",0
_schedulerFile db "interruptsasm.asm",0
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Multitasking problem

Post by Octocontrabass »

WinExperements wrote:

Code: Select all

		stackFrame *frame = (pmml_alloc(true))-sizeof(stackFrame);
Aren't you placing the stack frame outside the memory you just allocated?
WinExperements
Member
Member
Posts: 97
Joined: Thu Jul 14, 2022 9:45 am
Contact:

Re: Multitasking problem

Post by WinExperements »

Octocontrabass wrote:
WinExperements wrote:

Code: Select all

		stackFrame *frame = (pmml_alloc(true))-sizeof(stackFrame);
Aren't you placing the stack frame outside the memory you just allocated?
Yeah i already fixed the problem but it's works with problem that you write. I fixed that using TSS update in process_schedule and it's works fine. Thank
Post Reply