On 5 April 2017 at 14:50, Maxim Uvarov <maxim.uva...@linaro.org> wrote:
> On 04/05/17 06:57, Honnappa Nagarahalli wrote:
>> This can go into master/api-next as an independent patch. Agree?
>
> agree. If we accept implementation where events can be 'delayed'
Probably all platforms with HW queues.

> than it
> looks like we missed some api to sync queues.
When would those API's be used?

>
> But I do not see why we need this patch. On the same cpu test queue 1
> event and after that dequeue 1 event:
>
>         for (i = 0; i < QUEUE_ROUNDS; i++) {
>                 ev = odp_buffer_to_event(buf);
>
>                 if (odp_queue_enq(queue, ev)) {
>                         LOG_ERR("  [%i] Queue enqueue failed.\n", thr);
>                         odp_buffer_free(buf);
>                         return -1;
>                 }
>
>                 ev = odp_queue_deq(queue);
>
>                 buf = odp_buffer_from_event(ev);
>
>                 if (!odp_buffer_is_valid(buf)) {
>                         LOG_ERR("  [%i] Queue empty.\n", thr);
>                         return -1;
>                 }
>         }
>
> Where this exactly event can be delayed?
In the memory system.

>
> If other threads do the same - then all do enqueue 1 event first and
> then dequeue one event. I can understand problem with queueing on one
> cpu and dequeuing on other cpu. But on the same cpu is has to always
> work. Isn't it?
No.

>
> Maxim.
>
>>
>> On 4 April 2017 at 21:22, Brian Brooks <brian.bro...@arm.com> wrote:
>>> On 04/04 17:26:12, Bill Fischofer wrote:
>>>> On Tue, Apr 4, 2017 at 3:37 PM, Brian Brooks <brian.bro...@arm.com> wrote:
>>>>> On 04/04 21:59:15, Maxim Uvarov wrote:
>>>>>> On 04/04/17 21:47, Brian Brooks wrote:
>>>>>>> Signed-off-by: Ola Liljedahl <ola.liljed...@arm.com>
>>>>>>> Reviewed-by: Brian Brooks <brian.bro...@arm.com>
>>>>>>> Reviewed-by: Honnappa Nagarahalli <honnappa.nagaraha...@arm.com>
>>>>>>> Reviewed-by: Kevin Wang <kevin.w...@arm.com>
>>>>>>> ---
>>>>>>>  test/common_plat/performance/odp_scheduling.c | 12 ++++++++++--
>>>>>>>  1 file changed, 10 insertions(+), 2 deletions(-)
>>>>>>>
>>>>>>> diff --git a/test/common_plat/performance/odp_scheduling.c 
>>>>>>> b/test/common_plat/performance/odp_scheduling.c
>>>>>>> index c74a0713..38e76257 100644
>>>>>>> --- a/test/common_plat/performance/odp_scheduling.c
>>>>>>> +++ b/test/common_plat/performance/odp_scheduling.c
>>>>>>> @@ -273,7 +273,7 @@ static int test_plain_queue(int thr, test_globals_t 
>>>>>>> *globals)
>>>>>>>     test_message_t *t_msg;
>>>>>>>     odp_queue_t queue;
>>>>>>>     uint64_t c1, c2, cycles;
>>>>>>> -   int i;
>>>>>>> +   int i, j;
>>>>>>>
>>>>>>>     /* Alloc test message */
>>>>>>>     buf = odp_buffer_alloc(globals->pool);
>>>>>>> @@ -307,7 +307,15 @@ static int test_plain_queue(int thr, 
>>>>>>> test_globals_t *globals)
>>>>>>>                     return -1;
>>>>>>>             }
>>>>>>>
>>>>>>> -           ev = odp_queue_deq(queue);
>>>>>>> +           /* When enqueue and dequeue are decoupled (e.g. not using a
>>>>>>> +            * common lock), an enqueued event may not be immediately
>>>>>>> +            * visible to dequeue. So we just try again for a while. */
>>>>>>> +           for (j = 0; j < 100; j++) {
>>>>>>
>>>>>> where 100 number comes from?
>>>>>
>>>>> It is the retry count. Perhaps it could be a bit lower, or a bit higher, 
>>>>> but
>>>>> it works well.
>>>>
>>>> Actually, it's incorrect. What happens if all 100 retries fail? You'll
>>>> call odp_buffer_from_event() for ODP_EVENT_INVALID, which is
>>>> undefined.
>>>
>>> Incorrect? :) The point is that an event may not be immediately available
>>> to dequeue after it has been enqueued. This is due to the way that a 
>>> concurrent
>>> ring buffer behaves in a multi-threaded environment. The approach here is
>>> just to retry the dequeue a couple times (100 times actually) before moving
>>> on to the rest of code. Perhaps 100 times is too many times, but some amount
>>> of retry is needed.
>>>
>>> If this is not desirable, then I think it would be more accurate to consider
>>> odp_queue_enq() / odp_queue_deq() as async APIs -or- MT-unsafe (must be 
>>> called
>>> from one thread at a time in order to ensure the behavior that an event is
>>> immediately available for dequeue once it has been enqueued).
>>>
>>>>>
>>>>>> Maxim.
>>>>>>
>>>>>>> +                   ev = odp_queue_deq(queue);
>>>>>>> +                   if (ev != ODP_EVENT_INVALID)
>>>>>>> +                           break;
>>>>>>> +                   odp_cpu_pause();
>>>>>>> +           }
>>>>>>>
>>>>>>>             buf = odp_buffer_from_event(ev);
>>>>>>>
>>>>>>>
>>>>>>
>

Reply via email to