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.
I've been working on software multitasking for sometime now and I have finally finished it. My scheduler allows each task to run for the same number of timer ticks as its priority e.g. a task with priority 10 will run for 10 timer ticks. I then added the ability for a task to call REGISTER_ATOMIC() before it started an atomic operation. The scheduler wouldn't increment the time a task has been running for until UNREGISTER_ATOMIC() was called. I also added a pause function which did the exact same thing and the amount of time the task had been running for would only increment after the unpause function had been called.
The above all worked completely fine in BOCHS and as long as I didn't call the register atomic or the pause functions and left it paused it worked fine on real hardware. However as soon as I called the pause function and left it paused on the main task everything went wrong. Despite this working in BOCHS on real hardware the computer triple faulted. Everything was like BOCHS and then about half a second later the computer triple faulted.
I have been stuck on this for about 2 weeks now. I would be very grateful if you could have a look at my code and tell me what is happening.
To be honest, there is almost certainly going to be no difference between the way bochs and a real machine executes that code. It has no stack fiddling, no real bit twiddling and no asm!
I'd be more interested in seeing your task-switching code. That'd be FAR more likely to cause a triple fault than a simple if statement. (If you notice that code you posted is just updating kernel internal variables - nothing that can affect the operation of the computer at all.)
And as a helpy-hint, One of the major major differences between bochs and a real machine is that boch zero's all its memory. Check you're not relying on that. And if you're using your own bootloader, check you're zero'ing the .bss section.
JamesM wrote:To be honest, there is almost certainly going to be no difference between the way bochs and a real machine executes that code. It has no stack fiddling, no real bit twiddling and no asm!
Actually, Bochs often executes (properly) buggy code. It's emulation is not dependable. This is why it is suggested to test in multiple emulators (I work with QEMU, Bochs, and Virtual PC), and on real hardware.
Something like a "memset( <var>, 0, <size> );" often helps.
But the code he posted is just setting some local variables! Theres nothing there that could cause a fault - there is only one indirection, thats for the variable t, which I assume is non-NULL. If t is undefined then bochs could differ with a real machine. But if not, there is nothing there that should differ.
And bochs tends to (for me, anyway) give me an illegal opcode fault when it hits an illegal instruction. If that is not handled, it panics.
@OP:
I would suggest looking elsewhere in your code - the error could be there and just appearing to be here.
The task switching itself is fine. However when I call either the register_atomic or the pause functions and I leave the schedule_modifier variable altered the computer triple faults after a seemingly random number of interrupts (number of interrupts differs each time) however it doesn't triple fault in BOCHS.
Here is my task switching code if you would care to look at it and the whole of my scheduler is at the bottom.
was an error because I had nealy the same thing. I changed it for the value of my user stack and now my own scheduler work on all emulators, virtual pc, box, qemu. I just read somewhere that iret just pop 3 registers? How is that possible? I was sure I targeted the bug.
IRET will always pop an ESP value off the stack. How can it possibly not? the idea is that after an IRET the state of the machine should be pretty identical to what it was before. Doesn't matter if a ring switch occurs, it always stores then pops the stack pointer.
JamesM wrote:IRET will always pop an ESP value off the stack. [...]. Doesn't matter if a ring switch occurs, it always stores then pops the stack pointer.
That is wrong. Look into the Intel Manuals (5.12.1 Exception- or Interrupt-Handler Procedures). SS/ESP are only pushed, when the handler procedure is going to be executed at a numerically lower privilege level.