[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: General Question on Scheduler
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/