From: Artem Bityutskiy <dedekind@yandex.ru>
To: David Miller <davem@davemloft.net>
Cc: Lennert Buytenhek <buytenh@wantstofly.org>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: Re: bad example in Documentation/atomic_ops.txt ?
Date: Wed, 28 May 2008 08:28:58 +0300 [thread overview]
Message-ID: <483CED9A.4070102@yandex.ru> (raw)
In-Reply-To: <4836DC57.1020101@yandex.ru>
David,
do you have any comments on this? I paste the example below for
convenience.
Artem Bityutskiy wrote:
> I it looks like the example in the Documentation/atomic_ops.txt
> file at line 232 is not quite right. The obj->active = 0 will
> be delayed, but not further than spin_unlock() in obj_timeout().
> Becaus spin_unlock() has a memory barrier.
>
> I guess you would need to move spin_lock(&global_list_lock) to
> obj_list_del() to make the example valid.
>
> This confused me when I read the file.
static void obj_list_add(struct obj *obj)
{
obj->active = 1;
list_add(&obj->list);
}
static void obj_list_del(struct obj *obj)
{
list_del(&obj->list);
obj->active = 0;
}
static void obj_destroy(struct obj *obj)
{
BUG_ON(obj->active);
kfree(obj);
}
struct obj *obj_list_peek(struct list_head *head)
{
if (!list_empty(head)) {
struct obj *obj;
obj = list_entry(head->next, struct obj, list);
atomic_inc(&obj->refcnt);
return obj;
}
return NULL;
}
void obj_poke(void)
{
struct obj *obj;
spin_lock(&global_list_lock);
obj = obj_list_peek(&global_list);
spin_unlock(&global_list_lock);
if (obj) {
obj->ops->poke(obj);
if (atomic_dec_and_test(&obj->refcnt))
obj_destroy(obj);
}
}
void obj_timeout(struct obj *obj)
{
spin_lock(&global_list_lock);
obj_list_del(obj);
spin_unlock(&global_list_lock);
if (atomic_dec_and_test(&obj->refcnt))
obj_destroy(obj);
}
(This is a simplification of the ARP queue management in the
generic neighbour discover code of the networking. Olaf Kirch
found a bug wrt. memory barriers in kfree_skb() that exposed
the atomic_t memory barrier requirements quite clearly.)
Given the above scheme, it must be the case that the obj->active
update done by the obj list deletion be visible to other processors
before the atomic counter decrement is performed.
Otherwise, the counter could fall to zero, yet obj->active would still
be set, thus triggering the assertion in obj_destroy(). The error
sequence looks like this:
cpu 0 cpu 1
obj_poke() obj_timeout()
obj = obj_list_peek();
... gains ref to obj, refcnt=2
obj_list_del(obj);
obj->active = 0 ...
... visibility delayed ...
atomic_dec_and_test()
... refcnt drops to 1 ...
atomic_dec_and_test()
... refcount drops to 0 ...
obj_destroy()
BUG() triggers since obj->active
still seen as one
obj->active update visibility occurs
With the memory barrier semantics required of the atomic_t operations
which return values, the above sequence of memory visibility can never
happen. Specifically, in the above case the atomic_dec_and_test()
counter decrement would not become globally visible until the
obj->active update does.
--
Best Regards,
Artem Bityutskiy (Артём Битюцкий)
prev parent reply other threads:[~2008-05-28 5:26 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-05-23 15:01 bad example in Documentation/atomic_ops.txt ? Artem Bityutskiy
2008-05-28 5:28 ` Artem Bityutskiy [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=483CED9A.4070102@yandex.ru \
--to=dedekind@yandex.ru \
--cc=buytenh@wantstofly.org \
--cc=davem@davemloft.net \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.