kernel threading again

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
xvedejas
Member
Member
Posts: 168
Joined: Thu Jun 04, 2009 5:01 pm

kernel threading again

Post by xvedejas »

Switching stacks seems to corrupt the stack and mess up my memory manager... I've labeled the spot where it dies:

Code: Select all


u32int next_thread_id = 1;
volatile thread_t *current_thread = 0;

void new_stack(thread_t *thread, u32int current_esp, u32int current_ebp)
{
	u32int size, offset, new_stack_start, i;
	size = current_thread->stack_start - current_esp;
	thread->stack = (u32int)malloc(0x2000); // reserve 8192 bytes for stack
	// start of stack is at _end_ of allocation
	new_stack_start = thread->stack + 0x2000;
	offset = new_stack_start - current_thread->stack_start;
	// find the esp and ebp for the new stack
	thread->stack_start = new_stack_start;
	thread->esp = current_esp + offset;
	thread->ebp = current_ebp + offset;
	// copy over the old stack to the new one
	memcpyd((u32int*)thread->esp, (u32int*)current_esp, size);
	u32int *tmp;
	for (tmp = thread->esp; tmp <= thread->stack_start; tmp++)
	{
		if (*tmp < current_thread->stack_start && *tmp > current_esp)
		{
			*tmp += offset;
		}
	}
	thread->stack_start = new_stack_start;
	thread->stack_size = size;
}
void threads_install()
{
	u32int esp, ebp;
	current_thread = (thread_t*)malloc(sizeof(thread_t));
	current_thread->stack_start = initial_esp;
	asm volatile("mov %%esp, %0" : "=r"(esp));
	asm volatile("mov %%ebp, %0" : "=r"(ebp));
	new_stack(current_thread, esp, ebp);
	asm volatile("mov %0, %%esp" :: "r"(current_thread->esp));
	asm volatile("mov %0, %%ebp" :: "r"(current_thread->ebp));
	current_thread->id = next_thread_id++;
	current_thread->status = 0;
	current_thread->next = current_thread;
	current_thread->previous = current_thread;
	current_thread->priority = 20;
	current_thread->counter = 20;
}
u32int fork()
{   // make new thread
	__asm__ __volatile__("cli");
	thread_t *parent_thread = (thread_t*)current_thread;
	thread_t *new_thread = (thread_t*)malloc(sizeof(thread_t));
	new_thread-> id = next_thread_id++;
	new_thread->next = parent_thread->next;
	new_thread->next->previous = new_thread;
	parent_thread->next = new_thread;
	new_thread->previous = parent_thread;
	new_thread->priority = parent_thread->priority;
	new_thread->counter = new_thread->priority;
	new_thread->status = 1; // ready
	current_thread->counter = 0;
	switch_thread(); // force switch to new thread
	__asm__ __volatile__("sti");
	if (current_thread == parent_thread)
		return new_thread->id;
	return 0;
}
void switch_thread()
{
	if (current_thread->counter)
	{
		current_thread->counter--;
		return;
	}
	
	if (current_thread->next == current_thread) return;
	// reset counter
	current_thread->counter = current_thread->priority;
	// get stack
	u32int esp, ebp;
	asm volatile("mov %%esp, %0" : "=r"(esp));
	asm volatile("mov %%ebp, %0" : "=r"(ebp));
	// save stack
	current_thread->esp = esp;
	current_thread->ebp = ebp;
	// advance current_thread
	thread_t *working_thread = current_thread;
	do
	{
		working_thread = working_thread->next;
		switch (working_thread->status)
		{
			case 1: // ready
				new_stack(working_thread, esp, ebp);
				working_thread->status = 0;
			break;
			case 3: // zombie
				working_thread->previous->next = working_thread->next;
				working_thread->next->previous = working_thread->previous;
				free(working_thread->stack);
				free(working_thread);
			break;
		}
	}
	while (working_thread->status);
	current_thread = working_thread;
	// switch stack
	esp = current_thread->esp;
	ebp = current_thread->ebp;
	/// CRASH ///
	__asm__ __volatile__("mov %0, %%esp" :: "r"(esp));
	__asm__ __volatile__("mov %0, %%ebp" :: "r"(ebp));
}
void exit()
{
	current_thread->status = 3; // zombie
	current_thread->counter = 0;
	switch_thread();
	panic("Failed to kill thread\n");
}
u32int get_pid()
{
	return current_thread->id;
}
Am I handling the stack wrong? I think the answer is yes, now the question is how?
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: kernel threading again

Post by NickJohnson »

Within your malloc() implementation, do you make sure to use invlpg to partially flush the TLB when allocating new pages into the heap? 90% of the time I have some sort of stack corruption near thread duplication, the TLB has been the problem.
User avatar
xvedejas
Member
Member
Posts: 168
Joined: Thu Jun 04, 2009 5:01 pm

Re: kernel threading again

Post by xvedejas »

Pages? My memory allocation deals with physical memory. There are no "pages".

Hrm... the stack doesn't need to be aligned does it?
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: kernel threading again

Post by NickJohnson »

xvedejas wrote:Pages? My memory allocation deals with physical memory. There are no "pages".
Sorry, I just assumed you were using paging.
xvedejas wrote:Hrm... the stack doesn't need to be aligned does it?
I think the stack may need to be dword aligned, but definitely not page aligned.

Hmm...

Code: Select all

   esp = current_thread->esp;
   ebp = current_thread->ebp;
   /// CRASH ///
   __asm__ __volatile__("mov %0, %%esp" :: "r"(esp));
   __asm__ __volatile__("mov %0, %%ebp" :: "r"(ebp));
You're not trying to load the stack pointers with data potentially coming from the current stack, are you? :wink:

I'd recommend having an in-kernel stack for doing process manipulation and using pure assembly in an interrupt handler to mess with the stack position. I don't know if that will work in your kernel though, especially b/c it doesn't use paging and I think you're trying to make in-kernel threads.
User avatar
xvedejas
Member
Member
Posts: 168
Joined: Thu Jun 04, 2009 5:01 pm

Re: kernel threading again

Post by xvedejas »

I think the stack may need to be dword aligned, but definitely not page aligned.
Everything should be dword aligned.
You're not trying to load the stack pointers with data potentially coming from the current stack, are you?
Hrm that's probably something to look into...
I'd recommend having an in-kernel stack for doing process manipulation and using pure assembly in an interrupt handler to mess with the stack position. I don't know if that will work in your kernel though, especially b/c it doesn't use paging and I think you're trying to make in-kernel threads.
Yes, they are in-kernel threads... and I try to shy away from assembly as much as possible.
User avatar
xvedejas
Member
Member
Posts: 168
Joined: Thu Jun 04, 2009 5:01 pm

Re: kernel threading again

Post by xvedejas »

That doesn't seem to be the problem... Hrm...
Post Reply