hi, could you tell me the role of "last" in the switch_to macro. schedule() sends 'prev' as this parameter to so it could be used by schedule_tail(). I would like to know how 'prev' (i.e 'last' in switch_to) is different from 'current', and how last is used in switch_to. -Anurekh On Tuesday 05 March 2002 12:35, William Lee Irwin III wrote: > 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/