Page 1 of 1

having a problem with my multitasking system

Posted: Fri Nov 09, 2007 10:50 pm
by Pyrofan1
so after reading about TSS for about an hour and then deciding that it was too complex for me, i decided to make my own simple multitasking system
here is task.h

Code: Select all


#include "types.h"
#include "error.h"

#define MAX_TASKS 10

struct TASK tasks[MAX_TASKS];
int current_task=0;
int running_task=0;

void new_task(void *function)
{
	if(current_task==10)
	{
		kerror(ERROR_NO_TASK_SPACE);
	}
	else
	{
		tasks[current_task].eip=(unsigned int)&function;
		asm("mov %%eax, %0"::"g"(tasks[current_task].eax));
		asm("mov %%ebx, %0"::"g"(tasks[current_task].ebx));
		asm("mov %%ecx, %0"::"g"(tasks[current_task].ecx));
		asm("mov %%edx, %0"::"g"(tasks[current_task].edx));
		asm("mov %%esp, %0"::"g"(tasks[current_task].esp));
		asm("mov %%esi, %0"::"g"(tasks[current_task].esi));
		asm("mov %%edi, %0"::"g"(tasks[current_task].edi));
		asm("mov %%ss, %0"::"g"(tasks[current_task].ss));
		asm("mov %%es, %0"::"g"(tasks[current_task].es));
		asm("mov %%gs, %0"::"g"(tasks[current_task].gs));
		asm("mov %%fs, %0"::"g"(tasks[current_task].fs));
		asm("mov %%cs, %0"::"g"(tasks[current_task].cs));
		asm("mov %%ds, %0"::"g"(tasks[current_task].ds));
		asm("pushfl");
		asm("pop %eax");
		asm("mov %%eax, %0"::"g"(tasks[current_task].eflags));

		if(current_task==0)
		{
			tasks[current_task].esp+=(sizeof(long)*100);
		}
		else
		{		
			tasks[current_task].esp+=(sizeof(long)*100)+tasks[current_task-1].esp;
		}
		current_task++;
	}
}

void switch_task(void)
{
	if(running_task==10) running_task=-1;
	running_task++;

	if(tasks[running_task].eip!=0)
	{
		asm("push %0":"=g"(tasks[running_task].eflags));
		asm("popfl");
		asm("mov %0, %%eax":"=g"(tasks[running_task].eax));
		asm("mov %0, %%ebx":"=g"(tasks[running_task].ebx));
		asm("mov %0, %%ecx":"=g"(tasks[running_task].ecx));
		asm("mov %0, %%edx":"=g"(tasks[running_task].edx));
		asm("mov %0, %%edi":"=g"(tasks[running_task].edi));
		asm("mov %0, %%esi":"=g"(tasks[running_task].esi));
		asm("mov %0, %%esp":"=g"(tasks[running_task].esp));
		asm("mov %0, %%ebp":"=g"(tasks[running_task].ebp));
		asm("mov %0, %%ss":"=g"(tasks[running_task].ss));
		asm("mov %0, %%gs":"=g"(tasks[running_task].gs));
		asm("mov %0, %%fs":"=g"(tasks[running_task].fs));
		asm("mov %0, %%cs":"=g"(tasks[running_task].cs));
		asm("mov %0, %%ds":"=g"(tasks[running_task].ds));
		asm("jmp %0":"=g"(tasks[running_task].eip));
	}
}
my TASK structure

Code: Select all

struct TASK
{
	unsigned int gs;
	unsigned int fs;
	unsigned int ds;
	unsigned int ss;
	unsigned int cs;
	unsigned int es;
	unsigned int edi;
	unsigned int esi;
	unsigned int ebp;
	unsigned int esp;
	unsigned int ebx;
	unsigned int edx;
	unsigned int ecx;
	unsigned int eax;
	unsigned int eflags;
	unsigned int eip;
};
here's my main

Code: Select all

void _main(void* mbd,unsigned int magic)
{
	idt_install();
	gdt_install();

	clrscr(BLACK,BLACK);
	set_color(WHITE,BLACK);
	set_echo(1);

	Put("Welcome to PyroS\n");
	init_tasks();
}
my init_tasks function

Code: Select all

void main_loop(void)
{
	for(;;);
}

void init_tasks(void)
{
	new_task((void*)main_loop);
}	
now when i run my OS i get an Invalid opcode exception, but don't see anything in the code that would cause this.

Posted: Sat Nov 10, 2007 2:42 am
by ucosty
My best guess is that you are messing up the stack in the new_task function.

In any case this method of task switching is pretty limited and you would be much better of figuring out how to set up a single tss and use proper software switching. It is very easy to get working. The TSS for the most part is set and forget.

Posted: Sat Nov 10, 2007 5:31 am
by Combuster
asm("mov %0, %%eax":"=g"(tasks[running_task].eax));
asm("mov %0, %%ebx":"=g"(tasks[running_task].ebx));
asm("mov %0, %%ecx":"=g"(tasks[running_task].ecx));
asm("mov %0, %%edx":"=g"(tasks[running_task].edx));
asm("mov %0, %%edi":"=g"(tasks[running_task].edi));
asm("mov %0, %%esi":"=g"(tasks[running_task].esi));
asm("mov %0, %%esp":"=g"(tasks[running_task].esp));
asm("mov %0, %%ebp":"=g"(tasks[running_task].ebp));
asm("mov %0, %%ss":"=g"(tasks[running_task].ss));
asm("mov %0, %%gs":"=g"(tasks[running_task].gs));
asm("mov %0, %%fs":"=g"(tasks[running_task].fs));
asm("mov %0, %%cs":"=g"(tasks[running_task].cs));
asm("mov %0, %%ds":"=g"(tasks[running_task].ds));
You are suggesting gcc to pick a register, then move it into another. the result is that at least one of the registers will not have the correct contents as it is overwritten by subsequent MOVs.

In fact, register clobbering and will never allow to store a full state directly to tasks[running_task] without using special measures. The best way to do software multitasking is by using stack switching. Nevertheless, a TSS is practically all normal cases required.

Posted: Sat Nov 10, 2007 12:07 pm
by Pyrofan1
okay, scene now i have to use a TSS, i have some questions about it. The intel manuals seem to imply that each task needs to have a LDT is this true? and also the TSS holds spaces for stacks at different privilege levels, what if i don't have any privilege levels in my OS.

Posted: Sat Nov 10, 2007 9:14 pm
by ucosty
You don't need any LDT's. The TSS does hold the ring 0 tss for when your os needs to do high ring -> ring 0 transitions. If you are already in ring 0 it will be ignored.

Posted: Tue Nov 13, 2007 2:46 am
by blackcatcoder
if you're gonna to implement the TSS you should also think of implementing GDT IDT and so on and trap gates ........ so first do GDT and IDT with the apropriate Gates, LDT is not necessary at all you just can leave it 0.

Posted: Tue Nov 13, 2007 8:01 pm
by Dandee Yuyo
You might not only be ruining the process task but scratching some other registers aswell... :roll: I would suggest to write that code completely in ASM and debug it line by line.

Good luck! :wink:

Posted: Wed Nov 14, 2007 4:35 am
by jal
Pyrofan1 wrote:okay, scene now i have to use a TSS, i have some questions about it. The intel manuals seem to imply that each task needs to have a LDT is this true? and also the TSS holds spaces for stacks at different privilege levels, what if i don't have any privilege levels in my OS.
Please note that using a TSS is by no means the only or standard way of doing things. Many developers here would advise against it, as it is slow and very Intel specific.


JAL

Posted: Wed Nov 14, 2007 4:47 am
by JamesM
jal: On the x86 you HAVE to use a TSS if you want a stack switch on interrupt (use a kernel stack much?). What we tend to do is only use one TSS as opposed to one for each process.

Posted: Wed Nov 14, 2007 8:39 am
by jal
JamesM wrote:jal: On the x86 you HAVE to use a TSS if you want a stack switch on interrupt (use a kernel stack much?). What we tend to do is only use one TSS as opposed to one for each process.
Yeah, but you don't need to use a TSS if you want to switch the stack manually, iirc, and that's faster than using a TSS.


JAL

Posted: Wed Nov 14, 2007 8:42 am
by AJ
If you want to run ring 3 tasks, yes you do. Otherwise, the processor cannot switch back to a ring 0 stack when an interrupt happens. You will need one TSS for each core.

Cheers,
Adam

Posted: Wed Nov 14, 2007 9:06 am
by JamesM
jal wrote:
JamesM wrote:jal: On the x86 you HAVE to use a TSS if you want a stack switch on interrupt (use a kernel stack much?). What we tend to do is only use one TSS as opposed to one for each process.
Yeah, but you don't need to use a TSS if you want to switch the stack manually, iirc, and that's faster than using a TSS.


JAL
Have you implemented tasking, perchance?

Posted: Wed Nov 14, 2007 2:55 pm
by jal
AJ wrote:If you want to run ring 3 tasks, yes you do. Otherwise, the processor cannot switch back to a ring 0 stack when an interrupt happens. You will need one TSS for each core.
Ok, I stand corrected. I must have confused the matter with something else.


JAL

Posted: Wed Nov 14, 2007 2:56 pm
by jal
JamesM wrote:Have you implemented tasking, perchance?
I haven't, and I misrecalled something someone told me recently. It was indeed that one only needs one TSS, that being enough (as opposed to using a TSS for each task), not that you need no TSS at all. Appologies again if I caused confusion.


JAL