On 11/03/2015 10:21 AM, Nicolas Morey-Chaisemartin wrote:
>
> On 11/02/2015 06:11 PM, Bill Fischofer wrote:
>> Enqueueing to ordered queues requires two locks (source and target
>> queues). Since any queue can be either source or target, queues do not
>> have a natural locking hierarchy. Create one by using the address of
>> the qentry as the lock order.
>>
>> This addresses the aspect of Bug
>> https://bugs.linaro.org/show_bug.cgi?id=1879
>> relating to deadlock in unicore systems.
>>
>> Suggested-by: Nicolas Morey-Chaisemartin <nmo...@kalray.eu>
>> Signed-off-by: Bill Fischofer <bill.fischo...@linaro.org>
>> ---
>>  platform/linux-generic/odp_queue.c | 39 
>> +++++++++++++++++++++++++++++---------
>>  1 file changed, 30 insertions(+), 9 deletions(-)
>>
>> diff --git a/platform/linux-generic/odp_queue.c 
>> b/platform/linux-generic/odp_queue.c
>> index a27af0b..1c15e17 100644
>> --- a/platform/linux-generic/odp_queue.c
>> +++ b/platform/linux-generic/odp_queue.c
>> @@ -48,6 +48,28 @@ typedef struct queue_table_t {
>>  static queue_table_t *queue_tbl;
>>  
>>  
>> +static inline void get_qe_locks(queue_entry_t *qe1, queue_entry_t *qe2)
>> +{
>> +    /* Special case: enq to self */
>> +    if (qe1 == qe2) {
>> +            LOCK(&qe1->s.lock);
>> +            return;
>> +    }
>> +
>> +       /* Since any queue can be either a source or target, queues do not 
>> have
>> +    * a natural locking hierarchy.  Create one by using the qentry address
>> +    * as the ordering mechanism.
>> +    */
>> +
>> +    if (qe1 < qe2) {
>> +            LOCK(&qe1->s.lock);
>> +            LOCK(&qe2->s.lock);
>> +    } else {
>> +            LOCK(&qe2->s.lock);
>> +            LOCK(&qe1->s.lock);
>> +    }
>> +}
>> +
>>  queue_entry_t *get_qentry(uint32_t queue_id)
>>  {
>>      return &queue_tbl->queue[queue_id];
>> @@ -370,14 +392,11 @@ int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t 
>> *buf_hdr, int sustain)
>>  
>>      /* Need two locks for enq operations from ordered queues */
>>      if (origin_qe) {
>> -            LOCK(&origin_qe->s.lock);
>> -            while (!LOCK_TRY(&queue->s.lock)) {
>> -                    UNLOCK(&origin_qe->s.lock);
>> -                    LOCK(&origin_qe->s.lock);
>> -            }
>> +            get_qe_locks(origin_qe, queue);
>>              if (odp_unlikely(origin_qe->s.status < QUEUE_STATUS_READY)) {
>>                      UNLOCK(&queue->s.lock);
>> -                    UNLOCK(&origin_qe->s.lock);
>> +                    if (origin_qe != queue)
> This test is unneeded as we are already in a if(origin_qe) branch
Agreed.
This patch is actually fixing 2 issues (if I read it right):
 * Actual deadlock issues if qe == origin_qe
 * Linux scheduling issues

It would be nice to split the patch or update the log accordingly.
Other than that, it looks good.

Nicolas
_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to