On 2/3/06, Rajaram Suryanarayanan <rajaram_linux@xxxxxxxxx> wrote: > > > Gaurav Dhiman <gauravd.chd@xxxxxxxxx> wrote: > On 2/1/06, Fawad Lateef wrote: > > > On 2/1/06, Mukund JB. wrote: > > > Dear Fawad, > > > > > > What I can understand from the following description given by you is: > > > > > > The spinlock if implemented on a Uniprocessor non-preemptable kernel > > > will lead to kernel crash. > > > REASON: > > > The second process will be in busy loop not allowing the Scheduler to > > > schedule the task. It will hang. > > > > > > My questions: > > > scheduler_tick() is a called at regular system routine that the kernel > > > periodically calls and marks processes as needing rescheduling. This > > > call occurs in the timer interrupt context. > > > > > > Now, Lets say that the second process (B) called the spinlock_lock() and > > > is waiting for the first process (A) to unlock. In the mean time, it is > > > sure that scheduler_tick()will be invoked in timer interrupt context. > > > This should take care of the rescheduling the task with this new Process > > > B. Then where is the case of system getting hanged completely. > > > > > > Pleas help me get more clarity on this. > > > > > > > AFAIK in kernel without preemption and no SMP the process (kernel > > process) will never be rescheduled until unless it voluntarily call > > schedule or releases CPU. You can see this behaviour by just inserting > > while(1); (infinite loop) with-in your module and your system will > > hang ! (CMIIW) > > > > You are right fawad ..... > > Mukund, actually when we have kernel without preemption and SMP, > preemption is not done while returning from interrupt or exception to > to kernel execution thread. > > In this case, when we are in kernel mode and timer interrupt occurs, > kernel execution flow (in this case busy looping on spinlock) will be > interrupted and the interrupted state will be saved on the kernel > stack and interrupt will be serviced. Lets say, interrupt service > routine identifies that the current process need to be rescheduled and > sets the need_resched in current process task_struct. After servicing > the interrupt, when we return back, they is a check to know is we are > returning to user mode or to kernel mode. In case we are returing to > user mode, we do check the need_resched flag and and call the > schedule() function to schedule another process. In case we are > returing to kernel mode (this is our case, as we were interrupted in > kernel mode) and the kernel is compiled with preemption disabled, we > simply restore the interrupted execution context, which is what we > were doing before interrupt occured, so we keep on looping on > spinlock. > > But in case the kernel is compiled with preemption enabled and we are > returing to kernel mode, we do the following thress checks: > > If we cannot preempt (preempt count not equal to 0) > restore the interrupted context > if we need not to reschedule (need_resched is clear) > restore the interrupted context > if the interrupts were off before we entered the interrupt (dont know > how this condition can be fullfilled, also dont know the idea behind > checking this condition here, anyone can help out here !! ) > restore the interrupted context > try to reschedule > > > So in above flow will can see that we reschedule only if all three > checks are passed, else we simply restore the interrupted contexet > (kernel execution flow) and keep on doing what we were doing before > interrupt occured. > > Hope this helps out in clearing your doubt. > > -Gaurav > > > > > -- > > Fawad Lateef > > > > -- > > Kernelnewbies: Help each other learn about the Linux kernel. > > Archive: http://mail.nl.linux.org/kernelnewbies/ > > FAQ: http://kernelnewbies.org/faq/ > > > > > > -- > Kernelnewbies: Help each other learn about the Linux kernel. > Archive: http://mail.nl.linux.org/kernelnewbies/ > FAQ: http://kernelnewbies.org/faq/ > > > > Thanks Gaurav for a very good explanation. > btw..I read in Robert Love's book that "locking a spinlock disables kernel > preemption". > Is it like that ? yes, when we acquire the spinlock, preemption is disabled. > Is this the reason why he also says a process should not sleep after > acquiring a lock ? yes, we can not afford to sleep (which eventually reschedules other process on this CPU) or make a call to schedule() function or do something which eventually calls schedule() function, while we are holding a spinlock. The preemption is disabled when we are holding a spinlock and the reason for this is that preemption simply reschedules the new process (if needed) on CPU, which we never intend or ever think of while holding the spinlock. Lets say the if the preemption is not disabled while we are holding a spinlock and an interrupt ot exception occurs, in that case while returning from interrupt or exception our CPU can be rescheduled to another process if needed because we have not disabled the preemption. If our CPU get rescheduled to other process, our process which was running on it will be put on hold with spinlock held till its next turn. Along with this, there might be other processes running on other CPUs waiting for this spinlock to be release, so those CPUs will simply busy loop till our process does not get another chance to run and release the spinlock eventually, this have a major effect on system performance. Well there are different types of spinlock available in kernel, few of them are as follows. You can see here that before making a call to _raw_spin_lock() (which actaully busy loop, till we acquire the spinlock), we do call preempt_disable() function which actually increment the preempt_count for current running process and hence disabling the preemption. 253 #define _spin_lock(lock) \ 254 do { \ 255 preempt_disable(); \ 256 _raw_spin_lock(lock); \ 257 __acquire(lock); \ 258 } while(0) 295 #define _spin_lock_irqsave(lock, flags) \ 296 do { \ 297 local_irq_save(flags); \ 298 preempt_disable(); \ 299 _raw_spin_lock(lock); \ 300 __acquire(lock); \ 301 } while (0) 303 #define _spin_lock_irq(lock) \ 304 do { \ 305 local_irq_disable(); \ 306 preempt_disable(); \ 307 _raw_spin_lock(lock); \ 308 __acquire(lock); \ 309 } while (0) First version mentioned above, does not disable the interrupts so disabling preemption is definitely required there. You might be thinking, in 2nd and 3rd version, we do disable the interrupts on local CPU, and in that case there can not be any chance of current flow being interrupted on CPU. Well it can still be interrupted if an exception occurs while you are in critical section and holding a spinlock, this is the reason that we disable the preemption even if we have interrupts disabled because exception can occur anytime. Hope it make things more clear. regards, -Gaurav > > Thanks, > Rajaram. > > > > > > > > > > ________________________________ > Yahoo! Autos. Looking for a sweet ride? Get pricing, reviews, & more on new > and used cars. > > -- Kernelnewbies: Help each other learn about the Linux kernel. Archive: http://mail.nl.linux.org/kernelnewbies/ FAQ: http://kernelnewbies.org/faq/