Problem when implementing fork

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
User avatar
serviper
Member
Member
Posts: 31
Joined: Sat Jul 16, 2011 6:05 am
Location: China
Contact:

Problem when implementing fork

Post by serviper »

Hi everyone.
I'm implementing a 32-bit OS, but there's something wrong with fork (used to clone a process). My fork implementation just clones the address space of parent task (by clone the page directory), then set some context (ESP, EBP and EIP) for the child (when the running task is parent) or recover EBP and returns (when the running task is child).
The code below causes child process do nothing, rather than printing some characters to the screen:

Code: Select all

	if (fork() != 0) {
		if (fork() != 0) {
			while(1) { 
				monitor_write("a");   // works
				u32int i;
				for (i = 0; i < 5000; i++);
			}
		} else {
			if (fork() != 0) {
				while(1) { 
					monitor_write("m");  // works
					u32int i;
					for (i = 0; i < 5000; i++);
				}
			} else {
				while(1) { 
					monitor_write("n");  // do nothing
					u32int i;
					for (i = 0; i < 5000; i++);
				}
			}
		}
	} else {
		if (fork() == 0) {
			while(1) { 
				monitor_write("p");  // do nothing
				u32int i;
				for (i = 0; i < 5000; i++);
			}
		} else {
			if (fork() != 0) {
				while(1) { 
					monitor_write("b");  // works
					u32int i;
					for (i = 0; i < 5000; i++);
				}
			} else {
				while(1) { 
					monitor_write("q");  // do nothing
					u32int i;
					for (i = 0; i < 5000; i++);
				}
			}
		}
Only 'a', 'b' and 'm' are printed to the screen. Other tasks do nothing but waiting. When a timer interrupt occurs, the EBP pushed by the do-nothing task is 0x8. I'm confused about that.

btw, each task has its 4KB kernel stack on virtual address 0xE0000000 and below is the code for task switching:

Code: Select all

[EXTERN __switch_to]
schedule:
	push	esi
	push	edi
	push	ebp
	mov	[eax+0x4], esp			    ; prev->esp
	mov	dword [eax+0xc], .bpoint    ; prev->eip
	mov	cr3, ecx			            ; next->page_dir->physaddr
	mov	esp, [edx+0x4]			    ; next->esp
	push	dword [edx+0xc]		    ; next->eip
	jmp	__switch_to
.bpoint:
	pop	ebp
	pop	edi
	pop	esi
	;sti
	ret
Can anyone give me some tips? Thanks in advance!
rdos
Member
Member
Posts: 3310
Joined: Wed Oct 01, 2008 1:55 pm

Re: Problem when implementing fork

Post by rdos »

Assuming the return value of fork is EAX, you should set EAX to 0 in one of the processes and to 1 in the other. I don't see you setting the return value for fork anywhere.
User avatar
serviper
Member
Member
Posts: 31
Joined: Sat Jul 16, 2011 6:05 am
Location: China
Contact:

Re: Problem when implementing fork

Post by serviper »

rdos wrote:Assuming the return value of fork is EAX, you should set EAX to 0 in one of the processes and to 1 in the other. I don't see you setting the return value for fork anywhere.
Because the C code above is just a test...Parts of the implements below:

Code: Select all

	cli;
	eip = read_eip();

	// here we fork
	if (current_task == parent_task) {
		asm volatile ("mov %%esp, %0" : "=r"(esp));
		asm volatile ("mov %%ebp, %0" : "=r"(ebp));
		new_task->esp = esp;
		new_task->ebp = ebp;
		new_task->eip = eip;
		sti;

		return new_task->id;
	} else {
		asm volatile ("mov %0, %%ebp"::"r" (current_task->ebp));
		sti;
		return 0;
	}
}

Post Reply