Re: A questionable piece of code for context switching (very short, only 5 lines)

"climber.cui" <spamtrap@xxxxxxxxxx> wrote in message
On Jul 16, 3:59 pm, Bjarni Juliusson <spamt...@xxxxxxxxxx> wrote:
climber.cui wrote:
The second thread argument is supposed to start running upon the
function return.

Well, I think you just answered your question yourself then...

When thread A calls SWITCH, the return address of that call is saved in
the state struct of thread A. Then a previously saved return address
from thread B is put instead on the stack, the state of thread B is
loaded into the registers, and SWITCH returns to where it was last
called from thread B. When B calls SWITCH, its return address is saved,
and SWITCH returns to where it was called from A before, and so on.
Where's the problem?


hmm. I understand what the program is trying to do. It is just the
last couple of lines really confused me:
..... # loading register values for thread B
1 movl _ESP(%eax),%esp
# restore stack pointer
2 movl _PC(%eax),%eax
# restore return address into eax
3 movl %eax,4(%esp)
# copy over the ret address on the stack ?! why?
4 movl _eax_save,%eax
5 ret
# end of SWITCH
Line 2: move the saved Return address of Thread B to eax.
Line 3: move that saved return address to the stack, but the location
is the memory slot below the stack top, right? that means it just
overwrite the content saved at that location. And then, when 'ret'
instruction is reached, the stack top is poped(let's say the poped
value is x), and the program resumes execution at address x. This
makes no sense, bacause the return address of B is not poped, rather,
it is still on the stack. I would like to replace this line(line 3)
by "pushl %eax", so that the return address is placed at the top of
the stack, and upon execution of 'ret', this return address is poped
in to %eip. In this way, the original stack is not modified, and more
importantly, thread B starts execution at its saved return address.

Either I am wrong or the author was wrong. How do think about it?

My guess is that another routine is being returned to. I.e., there is
another return address on the stack.

There seem to be a few versions of NachOS, and perhaps a couple OSes by that
name. But, from the one I was looking at, it appears that it is an
"educational" OS - so, first, I'm not confident the code is correct... But,
what I saw from the code was that a task is interrupted and an interrupt
handler begins execution. The interrupt handler eventually calls SWITCH
with saves the interrupted task ('x'), and sets up another task to be called
('B'). Then SWITCH returns to 'x' (not 'B'), which runs until it calls
"currentThread->Yield()". Then, currentThread->Yield() causes the 'B'
thread to be called. Of course, if I'm correct (I might not be - I only
looked at it for a few minutes and I don't code C++...), that means that
when 'x' resumes it will return to it's interrupted location, not the
location of "currentThread->Yield()". So, some of the code in 'x' is
actually being executed twice... I.e., the code between the interrupted
location and "currentThread->Yield()". If the thread is small, this doesn't
matter much. But, if the thread is large, executing code twice is a waste
of CPU time. However, it appears that some part of the interrupt routine
also calls "currentThread->Yield()" at predetermined intervals. This is
probably to cause a switch to occur for larger threads without executing the
thread far beyond the interrupt location, i.e., less waste of CPU time.
Also, I didn't see any mention of an 'iret', or code to pop cs, or code to
correct the stack pointer when returning from an x86 interrupt. It might be
there, but I just didn't see it. If it's not there, there could be a stack

Rod Pemberton