read_eip in JamesM's tutorials
- Steve the Pirate
- Member
- Posts: 152
- Joined: Fri Dec 15, 2006 7:01 am
- Location: Brisbane, Australia
- Contact:
read_eip in JamesM's tutorials
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
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
-
- Member
- Posts: 368
- Joined: Sun Sep 23, 2007 4:52 am
Re: read_eip in JamesM's tutorials
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).
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
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.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
That particular chapter, along with the heap one, aren't exactly my favourites, let's put it that way...
- Steve the Pirate
- Member
- Posts: 152
- Joined: Fri Dec 15, 2006 7:01 am
- Location: Brisbane, Australia
- Contact:
Re: read_eip in JamesM's tutorials
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.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).
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?
-
- Member
- Posts: 368
- Joined: Sun Sep 23, 2007 4:52 am
Re: read_eip in JamesM's tutorials
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).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.
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.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?
- Steve the Pirate
- Member
- Posts: 152
- Joined: Fri Dec 15, 2006 7:01 am
- Location: Brisbane, Australia
- Contact:
Re: read_eip in JamesM's tutorials
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.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.
- Steve the Pirate
- Member
- Posts: 152
- Joined: Fri Dec 15, 2006 7:01 am
- Location: Brisbane, Australia
- Contact:
Re: read_eip in JamesM's tutorials
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?
-
- Member
- Posts: 368
- Joined: Sun Sep 23, 2007 4:52 am
Re: read_eip in JamesM's tutorials
Usermode threads are easier than kernel-mode threads with regards to stacks.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.
Don't do that.that registers struct is passed by value twice before my schedule function is called
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.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?
- Steve the Pirate
- Member
- Posts: 152
- Joined: Fri Dec 15, 2006 7:01 am
- Location: Brisbane, Australia
- Contact:
Re: read_eip in JamesM's tutorials
Yeah, I'll probably go and change it to pass by reference, but it will be a bit of work...Craze Frog wrote:Don't do that.Steve the Pirate wrote:that registers struct is passed by value twice before my schedule function is called
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.Craze Frog wrote: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.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?