Re: General Question on Scheduler

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux