Page 1 of 1

read_eip in JamesM's tutorials

Posted: Sun Mar 08, 2009 10:54 pm
by Steve the Pirate
I'm not absolutely sure about this, but isn't the read_eip function and the way it's used most of the time in JamesM's multitasking tutorial not really needed and a bit hacky? The reason is that most of the time you need the instruction pointer, the function you are in will have been called from an interrupt handler. Since the interrupt handler receives a struct of all the registers before the interrupt fired, can't you just use eip from that rather than using the read_eip function and having to use the magic value and everything? Or is this not how the interrupt works?

Also, I was wondering if I could use eip to find the name of the function that was running when an exception fired. Is this how kernel debuggers work? I assume you'd need to include a symbol table (compile with -g?). Then would you be able to work out the code line?

Thanks,

Stephen

Re: read_eip in JamesM's tutorials

Posted: Mon Mar 09, 2009 9:04 am
by Craze Frog
You can implement multitasking without relying on read_eip and corresponding dummy numbers if that's what you're asking. You'd just store the value of eip in the struct (from the interrupt) into the thread control block, then write the new eip into the struct. When you do iret you're in your new task.

If you want to switch tasks "on the fly" (without iret) that'd probably be possible without read_eip as well, but I can't see any good reason for doing it. The simple way is still to set up the stack and iret to whereever you want to go (it doesn't have to be an interrupt before).

Re: read_eip in JamesM's tutorials

Posted: Mon Mar 09, 2009 3:31 pm
by JamesM
Steve the Pirate wrote:I'm not absolutely sure about this, but isn't the read_eip function and the way it's used most of the time in JamesM's multitasking tutorial not really needed and a bit hacky? The reason is that most of the time you need the instruction pointer, the function you are in will have been called from an interrupt handler. Since the interrupt handler receives a struct of all the registers before the interrupt fired, can't you just use eip from that rather than using the read_eip function and having to use the magic value and everything? Or is this not how the interrupt works?

Also, I was wondering if I could use eip to find the name of the function that was running when an exception fired. Is this how kernel debuggers work? I assume you'd need to include a symbol table (compile with -g?). Then would you be able to work out the code line?

Thanks,

Stephen
There are plenty of ways to do it, many of them less hacky than those given in my tutorial. I chose that way because (a) I'd used it for a kernel before I wrote it and (b) it seemed succinct and easy enough to explain.

That particular chapter, along with the heap one, aren't exactly my favourites, let's put it that way... :)

Re: read_eip in JamesM's tutorials

Posted: Tue Mar 10, 2009 6:51 am
by Steve the Pirate
Craze Frog wrote:You can implement multitasking without relying on read_eip and corresponding dummy numbers if that's what you're asking. You'd just store the value of eip in the struct (from the interrupt) into the thread control block, then write the new eip into the struct. When you do iret you're in your new task.

If you want to switch tasks "on the fly" (without iret) that'd probably be possible without read_eip as well, but I can't see any good reason for doing it. The simple way is still to set up the stack and iret to whereever you want to go (it doesn't have to be an interrupt before).
I didn't know that you'd just be able to change those and then iret, but looking at the code it makes a lot of sense. I think I'm going to do it this way.

While I'm here, I thought I'd just see if anyone can clear this up for me: each process has a virtual address space (ie. page directory), which all the threads it owns uses, right? Well, my problem is that each one needs a stack, but I don't know what is the best way to determine an address for each stack. In JamesM's tutorial, he moves the stack to 0xE0000000 with a size of 0x2000. Now, should the next thread (in the same process) have a stack at 0xE0002000? And should I keep track of the last stack location in the process object, and then when a new thread is made just create a stack for it at last_stack_addr + 0x2000?

Re: read_eip in JamesM's tutorials

Posted: Tue Mar 10, 2009 8:29 am
by Craze Frog
Steve the Pirate wrote: I didn't know that you'd just be able to change those and then iret, but looking at the code it makes a lot of sense. I think I'm going to do it this way.
Just be careful to set up the stack so that structure is actually on the stack when you iret (if you run your interrupt handler through, it should work already).
While I'm here, I thought I'd just see if anyone can clear this up for me: each process has a virtual address space (ie. page directory), which all the threads it owns uses, right? Well, my problem is that each one needs a stack, but I don't know what is the best way to determine an address for each stack. In JamesM's tutorial, he moves the stack to 0xE0000000 with a size of 0x2000. Now, should the next thread (in the same process) have a stack at 0xE0002000? And should I keep track of the last stack location in the process object, and then when a new thread is made just create a stack for it at last_stack_addr + 0x2000?
IMO it's not the job of the OS to manage the stacks of the threads. The OS should only make sure the esp register is preserved and that's it. The tutorial uses kernel mode threads which is just another thing altogether. You should probably follow the tutorial or do it your own way, trying to tweak kernel threads into usermode processes and threads is just harder than doing what you want right from the start.

Re: read_eip in JamesM's tutorials

Posted: Tue Mar 10, 2009 6:12 pm
by Steve the Pirate
Craze Frog wrote:IMO it's not the job of the OS to manage the stacks of the threads. The OS should only make sure the esp register is preserved and that's it. The tutorial uses kernel mode threads which is just another thing altogether. You should probably follow the tutorial or do it your own way, trying to tweak kernel threads into usermode processes and threads is just harder than doing what you want right from the start.
OK, that makes sense. The only reason I was asking is before I do anything in user mode, I just wanted to test everything worked with two kernel threads. So I either have to just give each a copy of the kernel's stack, or point them both to the same stack. I was just wondering which would be the better way, and if they should have separate stacks, whether I can just put the next one at the address of the first stack + the size of the stack.

Re: read_eip in JamesM's tutorials

Posted: Wed Mar 11, 2009 6:55 am
by Steve the Pirate
On further inspection, I think that registers struct is passed by value twice before my schedule function is called, so should I just push the regs onto the stack and have the scheduler itret itself, instead of having the common IRQ stub do it?

Re: read_eip in JamesM's tutorials

Posted: Thu Mar 12, 2009 6:37 am
by Craze Frog
Steve the Pirate wrote:The only reason I was asking is before I do anything in user mode, I just wanted to test everything worked with two kernel threads.
Usermode threads are easier than kernel-mode threads with regards to stacks.
that registers struct is passed by value twice before my schedule function is called
Don't do that.
so should I just push the regs onto the stack and have the scheduler itret itself, instead of having the common IRQ stub do it?
Only if you don't have resources that needs to be cleaned up from the functions that calls the scheduler function. But this would be uglier since it would require inline asm or an external asm function to do it.

Re: read_eip in JamesM's tutorials

Posted: Fri Mar 13, 2009 12:04 am
by Steve the Pirate
Craze Frog wrote:
Steve the Pirate wrote:that registers struct is passed by value twice before my schedule function is called
Don't do that.
Yeah, I'll probably go and change it to pass by reference, but it will be a bit of work...
Craze Frog wrote:
Steve the Pirate wrote:so should I just push the regs onto the stack and have the scheduler itret itself, instead of having the common IRQ stub do it?
Only if you don't have resources that needs to be cleaned up from the functions that calls the scheduler function. But this would be uglier since it would require inline asm or an external asm function to do it.
You're right, and that's why I was hesitant to do it - changing the way the registers struct is passed around is probably a better option.