[Click] NotifierQueue on multi-threaded Click problem.

Eddie Kohler kohler at cs.ucla.edu
Fri Sep 7 14:58:47 EDT 2007


P.S. Do you still see a problem without the ToHosts?


Joonwoo Park wrote:
> Hi Eddie,
> 
> 2007/9/7, Eddie Kohler <kohler at cs.ucla.edu>:
>> Hi Joonwoo,
>>
>> I'm really glad that we are making progress!!
>>
>> Now, for the Queue.  I agree that a simple test should be sufficient to
>> test race conditions.
>>
>> Can you verify that in your configuration, there are *never* two threads
>> pushing into a Queue at the same time, and there are *never* two threads
>> pulling from a Queue at the same time?  NotifierQueue and FullNoteQueue
>> are designed for *at most one* pushing thread and *at most one* pulling
>> thread at a time.  The pushing thread can be different from the pulling
>> thread, but NotifierQueue and FullNoteQueue don't support multiple
>> threads pushing at once (or pulling at once).  Send your configuration
>> to the list for us to check.
> 
> I posted it already, please check the link.
> https://pdos.csail.mit.edu/pipermail/click/attachments/20070708/8b2abbd9/infinitereply.obj
> 
>> If you are sure that there aren't multiple pushing threads (or pulling
>> threads), then take a look at the code.  What do you think the race
>> condition is?  Locking the full bodies of those push and pull functions
>> is not required.  Can you help me figure it out?
> 
> I think the enq() and deq() has problem.
> As you said, one enq() and one deq() can be run concurrently.
> But operation of the code, '_tail = next' of enq() and '_head =
> next_i(_head)' is not atomic (I mean the equalizer)
> because of _tail and _head is INT.
> Therefore the code 'if (next != _head) {' of push() and 'if (_head !=
> _tail)' of pull() cannot be worked correctly.
> So I think these are should be atomic.
> I am attaching patch and It made another process on my test.
> 
> -
> Signed-off-by: Joonwoo Park <joonwpark81 at gmail.com>
> 
> diff --git a/elements/standard/simplequeue.hh b/elements/standard/simplequeue.hh
> index 975c062..bee9e1c 100644
> --- a/elements/standard/simplequeue.hh
> +++ b/elements/standard/simplequeue.hh
> @@ -119,6 +119,7 @@ SimpleQueue::enq(Packet *p)
>      int next = next_i(_tail);
>      if (next != _head) {
>  	_q[_tail] = p;
> +	// While doing '_tail = X' pull() can see polluted _tail if it is not atomic
>  	_tail = next;
>  	int s = size();
>  	if (s > _highwater_length)
> @@ -150,6 +151,7 @@ SimpleQueue::deq()
>      if (_head != _tail) {
>  	Packet *p = _q[_head];
>  	assert(p);
> +	// While doing '_head = X' push() can see polluted _head if it is not atomic
>  	_head = next_i(_head);
>  	return p;
>      } else
> diff --git a/include/click/standard/storage.hh
> b/include/click/standard/storage.hh
> index 9b05a08..70da9c6 100644
> --- a/include/click/standard/storage.hh
> +++ b/include/click/standard/storage.hh
> @@ -1,11 +1,12 @@
>  // -*- c-basic-offset: 4 -*-
>   #ifndef CLICK_STORAGE_HH
>  #define CLICK_STORAGE_HH
> +#include <click/atomic.hh>
>  CLICK_DECLS
> 
>  class Storage { public:
> 
> -    Storage()				: _head(0), _tail(0) { }
> +    Storage()	{ }
> 
>      operator bool() const		{ return _head != _tail; }
>      bool empty() const			{ return _head == _tail; }
> @@ -26,8 +27,8 @@ class Storage { public:
>    protected:
> 
>      int _capacity;
> -    int _head;
> -    int _tail;
> +    atomic_uint32_t _head;
> +    atomic_uint32_t _tail;
> 
>  };
> 
> -
> 
> Jason Park (Joonwoo Park)
> 
>> Eddie
>>
>>


More information about the click mailing list