[lttng-dev] [PATCH 01/16] Fix: wfcqueue nonblocking dequeue

Lai Jiangshan laijs at cn.fujitsu.com
Thu Nov 22 03:37:23 EST 2012


On 11/21/2012 10:37 PM, Mathieu Desnoyers wrote:
> * Lai Jiangshan (laijs at cn.fujitsu.com) wrote:
>> On 11/21/2012 03:40 AM, Mathieu Desnoyers wrote:
>>> Failures were not handled in the nonblocking dequeue implementation.
>>>
>>> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers at efficios.com>
>>> ---
>>>  urcu/static/wfcqueue.h |   11 +++++++++++
>>>  1 file changed, 11 insertions(+)
>>>
>>> diff --git a/urcu/static/wfcqueue.h b/urcu/static/wfcqueue.h
>>> index 8733771..a284b58 100644
>>> --- a/urcu/static/wfcqueue.h
>>> +++ b/urcu/static/wfcqueue.h
>>> @@ -312,6 +312,8 @@ ___cds_wfcq_dequeue(struct cds_wfcq_head *head,
>>>  		return NULL;
>>>  
>>>  	node = ___cds_wfcq_node_sync_next(&head->node, blocking);
>>> +	if (!blocking && node == CDS_WFCQ_WOULDBLOCK)
>>> +		return CDS_WFCQ_WOULDBLOCK;
>>>  
>>>  	if ((next = CMM_LOAD_SHARED(node->next)) == NULL) {
>>>  		/*
>>> @@ -332,6 +334,15 @@ ___cds_wfcq_dequeue(struct cds_wfcq_head *head,
>>>  		if (uatomic_cmpxchg(&tail->p, node, &head->node) == node)
>>>  			return node;
>>
>> Is it this simpler?
>> we had just loaded node->next via "if ((next = CMM_LOAD_SHARED(node->next)) == NULL)"
>>
>>
>> +		if (!blocking)
>> +			return CDS_WFCQ_WOULDBLOCK
>>
>>>  		next = ___cds_wfcq_node_sync_next(node, blocking);
>>
>> and remove the following.
> 
> So let's see. We have met the condition
>   "if ((next = CMM_LOAD_SHARED(node->next)) == NULL) {"
> 
> Therefore, it means that it appears, at that point, that the queue has
> only one node. So usually, after this test succeeds, we'll have to set
> the queue state to empty. There is only one case where this will not be
> done: if a concurrent enqueue adds a node between this test and the
> cmpxchg that follows. In that case, we'll notice this because cmpxchg
> fails, and instead of setting the queue to "empty", we'll simply wait
> for enqueue to complete adding the new node, and move head forward.
> 
> The approach you propose is to consider that if cmpxchg fails, we
> will very likely have to block. Well, that would skip a call to
> ___cds_wfcq_node_sync_next, and semantically would be still right,
> because the only way cmpxchg can fail is if the tail pointer is being
> changed concurrently, which would typically make us block.
> 
> However, we'd still need to perform "head->node.next = node;" before we
> return CDS_WFCQ_WOULDBLOCK, because _cds_wfcq_node_init() has already
> set the head next pointer to NULL, and we need to undo that.
> 

You are right,
I just proposed some noise which is not simple as I claimed.
sorry.

Thanks,
Lai

> 
>>
>>> +		/*
>>> +		 * In nonblocking mode, if we would need to block to
>>> +		 * get node's next, set the head next node pointer
>>> +		 * (currently NULL) back to its original value.
>>> +		 */
>>> +		if (!blocking && next == CDS_WFCQ_WOULDBLOCK) {
>>> +			head->node.next = node;
>>> +			return CDS_WFCQ_WOULDBLOCK;
>>> +		}
>>>  	}
>>>  
>>>  	/*
> 




More information about the lttng-dev mailing list