[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: General Question on Scheduler
On Tue, Mar 05, 2002 at 11:27:03AM +0530, Ganesh P wrote:
> 1. How does the scheduler perform a task switch i.e. where do I find the
> exact code that performs the task switch.
In include/asm-i386/system.h (I'll insert some additional comments):
/*
* This whole procedure is essentially a coroutine call. Coroutines
* are independent execution "streams" that transfer control to each
* other, basically cooperative multithreading.
* The essential parts of this switching are:
* (1) save current registers on our stack
* (2) save stack pointer and program counter in a buffer
* (3) restore stack pointer from another buffer
* (4) jump to saved program counter from the other buffer
* (5) make sure that when waking up, we restore our registers from
* the stack
* -- wli
*/
#define switch_to(prev,next) do { \
/* \
* The first thing we'll do is store the three registers we \
* must absolutely save across function calls onto the stack. \
* Essentially, we're doing a "call by hand" because the \
* part normally after the call that restores registers is \
* done differently. \
* -- wli \
*/ \
asm volatile("pushl %%esi\n\t" \
"pushl %%edi\n\t" \
"pushl %%ebp\n\t" \
\
/* \
* Now one of the arguments to the inline asm is a \
* pointer to a place we can save our stack pointer \
* and another is a place where we can save our \
* program counter (EIP in Intel nomenclature). \
* The magic trick here is that we can't use our \
* actual program counter as we're running because \
* we would loop. Instead we use a trick to get the \
* address of where we know we'd like to return to \
* by creating the label 1: and then saving $1f to \
* the saved program counter. \
* \
* It might appear at first that since this is a \
* constant value we would only need to get at that, \
* but even though this is only used once, we could \
* very well be restoring something created by hand \
* or saved by interrupt handling. \
* \
* The next exciting bit is that the FASTCALL() \
* macro actually declares a function to accept its \
* arguments from registers, now since the only \
* register that has been altered is the stack pointer \
* we are as ready as ever to do the call. Now the \
* tricky part of this is that we don't set our program \
* counter directly (using jmp), but rather set up the \
* program counter as the return address for \
* __switch_to()! Then the calling convention that on \
* i386, the return address is on the top of the stack \
* is used so the function can be returned from \
* normally to put us in the new thread, but we can't \
* call it normally, so instead we jmp to the function. \
* -- wli \
*/ \
"movl %%esp,%0\n\t" /* save ESP */ \
"movl %2,%%esp\n\t" /* restore ESP */ \
"movl $1f,%1\n\t" /* save EIP */ \
"pushl %3\n\t" /* restore EIP */ \
\
/* \
* __switch_to() has had a call set up by all the stuff \
* I was talking about above. When we return from it, \
* we are executing in the new task. The handcoded \
* return address setup is the label 1: \
* -- wli \
*/ \
"jmp __switch_to\n" \
"1:\t" \
\
/* \
* This is where we came out in the new thread. Now we \
* have our stack and program counter, we just have to \
* remember to restore our registers from the stack. \
* -- wli \
*/ \
"popl %%ebp\n\t" \
"popl %%edi\n\t" \
"popl %%esi\n\t" \
:"=m" (prev->thread.esp),"=m" (prev->thread.eip) \
:"m" (next->thread.esp),"m" (next->thread.eip), \
"a" (prev), "d" (next)); \
} while (0)
Although it's a little bit obfuscated by some fancy gyrations, I hope I've
made it clear that the whole "control transfer" or "task switch" is really
nothing more than some trickery to use the minimal number of registers so
that compiled C code can have its variables saved and restored, and an
indirect jump to the saved position of the program counter.
> 2. When does the scheduler get control so that it can perform the task
> switch. i.e is the scheduler called from the timer interrupt or something
> like that?
The scheduler gets control during explicit calls to schedule() and other
functions in sched.c
> 4. Does the linux kernel use the facilities provided by the processor ( I
> think x86 has facilities for task switch ) for the task switching?
TSS's are essentially required for SMP operation. However, Linux uses
one TSS per cpu.
> 3. Is it possible to load the linux image inside gdb and execute it.
Operating system kernels generally assume direct hardware access not
available from userspace. User-mode Linux is able to be used with gdb,
with some requirements on how gdb is invoked.
> 4. Is there a port of the User-Mode Linux for windows ?
Not that I am aware of.
Cheers,
Bill
--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive: http://mail.nl.linux.org/kernelnewbies/
IRC Channel: irc.openprojects.net / #kernelnewbies
Web Page: http://www.kernelnewbies.org/