Re: spinlock protection on data question

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

 



On Wed, Aug 07, 2002 at 03:30:14PM -0400, anton wilson wrote:
> I have a array of data that is used globally and an array of locks to protect 
> them.
> 
> struct context_data data[10];
> spinlock_t locks[10];

Where does the length of the array come from? Shouln't it be a linked
list, tree, hash table... ? (That has nothing to do with locking)

> The problem I'm having is that to find out which spinlock to use to lock any 
> struct in that array, I have to first access the data like this:
> 
> num = mydata->num;
> spin_lock_irqaave( &locks[num], &flags);

then why not spin_lock(&mydata->lock)? Are the locks shared between more
structures? Then it would still be mydata->lock->lock (the first one
must be a structure holding a lock and refcount).

> but one of my driver functions frees that same data:
> 
> static void disconnect_rasid(struct usb_device *dev, void *drv_context)
> {
>    num = ((context_data *) drv_context)->num;
>    spin_lock_irqaave( &locks[num], &flags);
> 
>    kfree(drv_context);
> 
>    /* ....  */
> 
> }

Then you must have a lock protecting the array. Just the way there is
inode_lock and dcache_lock and.... Make a generic global

DECLARE_SPINLOCK(data_lock);

and then you have to:
access as:
spin_lock(&data_lock);
num=mydata->num;
spin_lock_irqaave( &locks[num], &flags);
spin_unlock(&data_lock);
/* You can release here immediately - ordering (locks[n] is always taken
 * under data_lock) is sufficient to avoid dead-lock, locking and then
 * unlocking is enough to serialize. */

And you must free undef data_lock and lock of given object. Like this:
spin_lock(&data_lock);
num = ((context_data *) drv_context)->num;
spin_lock_irqaave( &locks[num], &flags);
spin_unlock_irqrestore( &locks[num], &flags);
/* Noone new can aquire it while we hold data_lock! */
/* however here you MUST: */
data[num] = NULL;
/* or anything else that will tell users there is no such data */
spin_unlock(&data_lock);
kfree(drv_context);
...

> so i think that any other function that uses that data is going to have 
> problems if it is called at the same time as disconnect because, before it 
> can lock the data structure, it has to access the data structure to find out 
> where in the array of locks the spinlock is .. . if disconnect has freed that 
> data structure, it no longer exists and you're accessing a null pointer.
> 
> Any suggestions?
> 
> Anton 

Anyway. I would still prefer refcounting. When a user needs the data, it
increments counter on the data and drop the data_lock. Only data with
zero counter can be freed. That way you can make operations on the data
concurrent to some extent (you still need to lock when changing the
data).

-------------------------------------------------------------------------------
						 Jan 'Bulb' Hudec <bulb@ucw.cz>
--
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