Spinlocks and interrupts
Kai Meyer
kai at gnukai.com
Thu Nov 10 12:02:02 EST 2011
On 11/09/2011 08:38 PM, Dave Hylands wrote:
> Hi Kai,
>
> On Wed, Nov 9, 2011 at 3:12 PM, Kai Meyer<kai at gnukai.com> wrote:
>> Ok, I need mutual exclusion on a data structure regardless of interrupts
>> and core. It sounds like it can be done by using a spinlock and
>> disabling interrupts, but you mention that "spinlocks are intended to
>> provide mutual exclsion between interrupt context and non-interrupt
>> context." Should I be using a semaphore (mutex) instead?
> It depends. If the function is only called from thread context, then
> you probably want to use a mutex. If there is a possibility that it
> might be called from interrupt context, then you can't use a mutex.
>
> Also, remember that spin-locks are no-ops on a single processor
> machine, so as coded, you have no protection on a single-processor
> machine if you're calling from thread context.
>
To make sure I understand you, it sounds like there's two contexts I
need to be concerned about, thread context and interrupt context. As far
as I can be sure, this code will only run in thread context. If you
could verify for me that a block device's make request function is only
reached in thread context, then that would make me doubly sure.
>> Perhaps I could explain my problem with some code:
>> struct my_struct *get_data(spinlock_t *mylock, int ALLOC_DATA)
>> {
>> struct my_struct *mydata = NULL;
>> spin_lock(mylock);
>> if (test_bit(index, mybitmap))
>> mydata = retrieve_data();
>> if (!mydata&& ALLOC_DATA) {
>> mydata = alloc_data();
>> set_bit(index, mybitmap);
>> }
>> spin_unlock(mylock);
>> return mydata;
>> }
>>
>> I need to prevent retrieve_data from being called if the index bit is
>> set in mybitmap and alloc_data has not completed, so I use a bitmap to
>> indicate that alloc_data has completed. I also need to protect
>> alloc_data from being run multiple times, so I use the spin_lock to
>> ensure that test_bit (and possibly retrieve_data) is not run while
>> alloc_data is being run (because it runs while the bit is cleared).
> If alloc_data might block, then you can't disable interrupts and you
> definitely shouldn't be using spinlocks.
>
alloc_data will call kmalloc(size, GFP_KERNEL), which I think may block,
so disabling irqs is out.
Between thread context and kmalloc with GFP_KERNEL, it sounds like your
suggestion would be to use a mutex. Is that correct?
-Kai Meyer
More information about the Kernelnewbies
mailing list