lkml.org 
[lkml]   [2003]   [Apr]   [16]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
/
DateTue, 15 Apr 2003 22:54:02 -0700
FromGreg KH <>
SubjectRe: 2.5.67-mm3: Bad: scheduling while atomic with IEEE1394 then hard freeze ( lockup on CPU0)
On Tue, Apr 15, 2003 at 04:34:56PM -0700, Andrew Morton wrote:
> Philippe Gramoullé <philippe.gramoulle@mmania.com> wrote:
> >
> > I'll wait for the fix and will happily try it once it's available.
> 
> Something like this...
> 
> diff -puN lib/kobject.c~kobj_lock-fix lib/kobject.c
> --- 25/lib/kobject.c~kobj_lock-fix	Tue Apr 15 16:31:28 2003
> +++ 25-akpm/lib/kobject.c	Tue Apr 15 16:34:33 2003
> @@ -336,12 +336,14 @@ void kobject_unregister(struct kobject *
>  struct kobject * kobject_get(struct kobject * kobj)
>  {
>  	struct kobject * ret = kobj;
> -	spin_lock(&kobj_lock);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&kobj_lock, flags);
>  	if (kobj && atomic_read(&kobj->refcount) > 0)
>  		atomic_inc(&kobj->refcount);
>  	else
>  		ret = NULL;
> -	spin_unlock(&kobj_lock);
> +	spin_unlock_irqrestore(&kobj_lock, flags);
>  	return ret;
>  }
> 
> @@ -371,10 +373,15 @@ void kobject_cleanup(struct kobject * ko
> 
>  void kobject_put(struct kobject * kobj)
>  {
> -	if (!atomic_dec_and_lock(&kobj->refcount, &kobj_lock))
> -		return;
> -	spin_unlock(&kobj_lock);
> -	kobject_cleanup(kobj);
> +	unsigned long flags;
> +
> +	local_irq_save(flags);
> +	if (atomic_dec_and_lock(&kobj->refcount, &kobj_lock)) {
> +		spin_unlock_irqrestore(&kobj_lock, flags);
> +		kobject_cleanup(kobj);
> +	} else {
> +		local_irq_restore(flags);
> +	}
>  }

CCed Pat, as this is his territory.

Hm yeah, this will fix the problem.  But is there anyway we can do this
without a lock at all?  I think we wouldn't need the lock, if we didn't
test the refcount for > 0, right?  Pat, that just keeps us from getting
a reference count on a kobject that hasn't been initialized, right?
That is a good idea to do, but is it really necessary?
If only atomic_inc_return() was defined for all platforms we might be
able to do the following, dropping the lock entirely:

struct kobject * kobject_get(struct kobject * kobj)
{
	struct kobject * ret = kobj;
	if (kobj)
		if (atomic_inc_return(kobj->refcount) <= 1) {
			atomic_dec(kobj->refcount);
			ret = NULL;
		}
	else
		ret = NULL;
	return ret;
}
void kobject_put(struct kobject * kobj)
{
	if (!atomic_dec(&kobj->refcount))
		return;
	kobject_cleanup(kobj);
}

Or am I missing something?

Anyone know how to whip up a atomic_inc_return() for the platforms
missing it?

thanks,

greg k-h
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 12:34    [from the cache]
©2003-2008