Multitasking

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.
Post Reply
cg123
Member
Member
Posts: 41
Joined: Wed Sep 27, 2006 2:34 pm

Multitasking

Post by cg123 »

I've been working on this for a while, and I can't quite get it right. It doesn't crash anymore, but it doesn't do anything. Here's the assembly part:

Code: Select all

[GLOBAL hwint00]
[extern _timer_handler]
hwint00:
	REG_SAVE
	cli
    call _timer_handler
	mov dx,20h
	mov al,20h
	out dx,al
	REG_RESTORE_MASTER
	ret ; shouldn't get here, but...

%macro REG_SAVE 0
	cld
	pushad
	push ds
	push es
	push fs
	push gs
	mov eax,[cPROC] ;put the adress of the struct of CURRENT PROCESS in eax.(the CONTENT of pointer p)
	mov [eax],esp ;save esp in the location of esp in the CURRENT PROCESS-STRUCT.
	lea eax,[kstackend] ; switch to the kernel's own stack.
	mov esp,eax
%endmacro

%macro REG_RESTORE_MASTER 0
	mov eax,[cPROC] ;put adress of struct of current process in eax.
	mov esp,[eax] ;restore adress of esp.
	mov ebx,[eax+8];put content of the k-stack field into ebx.
	mov [cTSS+4],ebx ;update system tss.
	mov al,0x20
	out 0x20,al
	pop gs
	pop fs
	pop es
	pop ds
	popad
	iretd
%endmacro
Here's the C part:

Code: Select all

#include <system.h>

#define KSTACKTOP 1024
#define USTACKTOP 1024

typedef struct {
	uint_t esp;
	uint_t ss;
	uint_t kstack;
	uint_t ustack;
	uint_t cr3;
	ulong_t PADDING;
	uint_t pid;
	uchar_t name[32];
} pdata_t;

typedef struct {
	ushort_t	backlink, __blh;
	uint_t		esp0;
	ushort_t	ss0, __ss0h;
	uint_t		esp1;
	ushort_t	ss1, __ss1h;
	uint_t		esp2;
	ushort_t	ss2, __ss2h;
	uint_t		cr3;
	uint_t		eip;
	uint_t		eflags;
	uint_t		eax, ecx, edx, ebx;
	uint_t		esp, ebp, esi, edi;
	ushort_t	es, __esh;
	ushort_t	cs, __csh;
	ushort_t	ss, __ssh;
	ushort_t	ds, __dsh;
	ushort_t	fs, __fsh;
	ushort_t	gs, __gsh;
	ushort_t	ldt, __ldth;
	ushort_t	trace, bitmap;
} tss_t;

tss_t cTSS;
pdata_t processes[32];
pdata_t* cPROC;
uint_t procnum = 1;
unsigned char kstacks[32][KSTACKTOP];
unsigned char stacks[32][USTACKTOP]; 

void init_task( int task , unsigned epoint )
{
	uint_t *stacksetup;
	stacksetup=(uint_t*)&kstacks[task][KSTACKTOP]; //esp0
	 stacksetup-- ;         //SS
	*stacksetup--=0x0202;  //flags
	*stacksetup--=0x08;    // CS
	*stacksetup--=epoint;  // Instruction pointer
	*stacksetup--= 0;      //error code
	*stacksetup--=0x20;    // interupt no.
	
	*stacksetup--=0;    //ebp
	*stacksetup--=0;    //esp
	*stacksetup--=0;    //edi
	*stacksetup--=0;    //esi
	*stacksetup--=0;    //edx
	*stacksetup--=0;    //ecx
	*stacksetup--=0;    //ebx
	*stacksetup--=0;    //eax
	
	*stacksetup--=0x20; //ds
	*stacksetup--=0x20; //es
	*stacksetup--=0x20; //fs
	*stacksetup=  0x20; //gs
	
	//filling in the struct.
    processes[task].esp=(uint_t)stacksetup;
    processes[task].ss=0x10;
    processes[task].kstack=(uint_t)&kstacks[task][KSTACKTOP];
    processes[task].ustack=(uint_t)&stacks[task][USTACKTOP];
	processes[task].PADDING = (ulong_t)"PUDDING!";
	processes[task].pid = task;
	
}

void schedule()
{
	//putch('s');
	++procnum;
	if (procnum > 3) {procnum = 1;}
	cPROC = &processes[procnum];
}

void t1() {putch('1');}
void t2() {putch('2');}
void t3() {putch('3');}

void mtask_init()
{
	init_task(1,(unsigned)t1);
	init_task(2,(unsigned)t2);
	init_task(3,(unsigned)t3);
}
I'm pretty sure there's an obvious mistake somewhere in here, but I'm unable to find it. Any help would be appreciated.
0Scoder
Member
Member
Posts: 53
Joined: Sat Nov 11, 2006 8:02 am

Post by 0Scoder »

Where's the code for the _timer_handler function that you call from the assembly? I can see something called schecule() in the c code, is that what it is meant to be?
cg123
Member
Member
Posts: 41
Joined: Wed Sep 27, 2006 2:34 pm

Post by cg123 »

Ah, forgot that part.

Code: Select all

void timer_handler()
{
    ++timer_ticks;
    if (timer_ticks % 18 == 0)
    {
		++seconds;
		if (seconds % 60 == 0)
		{
			++minutes;
		}
    }
	schedule();
}
cg123
Member
Member
Posts: 41
Joined: Wed Sep 27, 2006 2:34 pm

Post by cg123 »

I've been working on this for 3 months now, and I'm unable to continue working on my OS before I get multitasking done.... I would really, really appreciate a little help.
Mikae
Member
Member
Posts: 94
Joined: Sun Jul 30, 2006 1:08 pm

Post by Mikae »

Please, give more info about your system -- are all (256) ISR routines installed? Which size is your IDT? Do you use Bochs?


A few assumptions:

1. You said 'but it doesn't do anything.' -- may be, CPU enters into 'shutdown mode'? Have you handler of 0x8 interrupt installed?
2. Are you sure that size of your structs are the same as you expect? (May be they are larger because of alignment.)
oscoder
Member
Member
Posts: 59
Joined: Mon Mar 27, 2006 12:00 am
Location: UK

Post by oscoder »

Hi
Could you also give a zip file with your code? Sometimes I find its easier to work out whats going wrong by tracing things in bochs than looking at source code.

In what way does it do nothing? Is the interrupt ever called (and it just stays on the same task)? If so, does it get stuck in an infinite loop, or something, and not go back to what started it.

In order to test this, you can do something that would cause a tripple fault in your timer handler, so as to see if it gets called or not. In order to see if it just gets stuck there, use the 'hlt' command just after youve enabled the timer interrupt. I've found that after an interrupt has been served, execution starts AFTER this command, so you can see if its just dropping back into your original task.

Hope this helps (and isn't just a confusing mess!),
OScoder
cg123
Member
Member
Posts: 41
Joined: Wed Sep 27, 2006 2:34 pm

Post by cg123 »

Here's a zip with the source:
http://www.ihud.com/file.php?file=files ... os-src.zip

I've been using Bochs.
User avatar
pulsar
Member
Member
Posts: 49
Joined: Wed Nov 22, 2006 1:01 am
Location: chennai

Post by pulsar »

If you can't get an error then it means the code is working properly. What result do you expect and what is it doing? Have you checked your bochsout file. It might have some information that would be more help. get a bochs debugger and see what is happeining? It seems to be like beyond infinity's tutorial you followed, then you should take some time to read it carefullly, if you don't understand then read it again and agian untill you understand. You were happy that it doesn't crash anymore, if i were you i won't be happy for that, "you can't fight the enemy, you can't find".

Could u clarify the doubts, when do you enable the interrupts, have you enabled interrupts before creating process ? then where do you set cr3 register? if the process finishes executing where will it return? Once timer interrupt is enabled it executes the processes, will it execute your main code then? where do you switch processes?

you fake multitasking by pushing registers onto the kernel stack, when a timer interrupt happens it will override the current task's kernel stack. So if you want to begin a task you should pop it first right and do a iret; the next time when timer intterrupt happens it will push registers into it's own kernel stack and continues..

So this is how you can do.
you have a default process, and set the current process field to the default process process i.e your main program. the when you create a new task, the default process's registers will be pushed onto the default process's stack and not onto newly created process's stack ( this might be your problem, the derfault process's regs override your new process stack ).

I haven't gone thru the infinity's code, anyway i might have misunderstood it.

- pulsar
everyone here are best programmers ( not yet not yet)
Post Reply