Scheduling from thread in kernel space
I wrote a netfilter module, in which I had to write an extra thread to clean up a data structure in regular basis. I used schedule()
function after each round of clean up was done from the thread. Before using semaphore locks it was working just fine except "General Protection Fault"
was occurring. So I used semaphores to lock and unlock the data structure during both insert
and delete
operation. Now it is showing a bug telling "BUG: Scheduling while atomic"
. After searching in Google I got that it is showing because of explicit call of schedule()
function where it should not be called.
What are the ways to resolve it? Is there any other way in which the thread will yield the CPU to other threads?
So a basic summary (can't give a detailed answer for the reasons specified in the other comments):
A semaphore or mutex will attempt to grab a lock, and if it is unattainable, it will allow something else to run while it is waiting (this is done through the schedule()
call). A spinlock, on the other hand, is a locking mechanism that constantly tries to grab a lock until and does not relinquish control until it is succesful (note: there are also spinlock_irq_save, etc, which prevent you from being interrupted by an isr as well. You can look these up).
As far as atomic goes, that means that the kernel is unable to allow another process to run in the background. If you are in an interrupt for example, the kernel cannot allow someone else to run due to stack management. If you are within a spinlock, the kernel cannot allow someone else to run, because if it it schedules another process waiting on the spinlock, you could get in a deadlock situation. You can tell if you're atomic by using the in_atomic()
macro.
For your case, you mention an insert and delete function which are obviously called (at least some of the time) from atomic context. If these are only being called from an atomic context, then you can use a spinlock and be done with it. If these are being called from both, you can use spinlock_irq_save (which prevents interrupts from interrupting the spinlocked-area). Again, be careful about disabling interrupts for to long a time.
It is also possible to defer the freeing until later if there is something in the freeing, which you don't want to do from atomic context. In this case, create a spin-lock-protected linked list which is poulated by your delete. Then in your thread, you pop items off the list, and free them there. For insertion, do the malloc before locking the list.
Hope this helps.
John
链接地址: http://www.djcxy.com/p/14852.html上一篇: 为什么我们在CFS中定义Scheduler时间片?
下一篇: 从内核空间中的线程调度