I think I get it. I'm hitting the scheduling while atomic because I'm calling my function from a struct bio's endio function, which is probably running with a lock held somewhere else, and then my mutex sleeps, while the spin_lock functions do not sleep. Perhaps I need to learn more about the context in which my endio function is being called. On 11/10/2011 11:02 AM, Kai Meyer wrote: > 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 _______________________________________________ Kernelnewbies mailing list Kernelnewbies@xxxxxxxxxxxxxxxxx http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies