Re: spinlock on uniprocessor systems

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

 



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/



[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