Re: Spinlocks and interrupts

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

 



Well, I changed my code to use a mutex instead of a spinlock, and now I get:
BUG: scheduling while atomic: swapper/0/0x10010000
All I changed was the spinlock_t to a struct mutex, and call mutex_init, 
mutex_lock, and mutex_unlock where I was previously calling the 
spin_lock variations. I'm confused. What does mutex_lock do besides set 
values in an atomic_t?

-Kai Meyer

On 11/10/2011 10:02 AM, Kai Meyer wrote:
>
> On 11/09/2011 08:38 PM, Dave Hylands wrote:
>> Hi Kai,
>>
>> On Wed, Nov 9, 2011 at 3:12 PM, Kai Meyer<kai@xxxxxxxxxx>   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
>
> _______________________________________________
> Kernelnewbies mailing list
> Kernelnewbies@xxxxxxxxxxxxxxxxx
> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@xxxxxxxxxxxxxxxxx
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies


[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