diff mbox

[PATCHv2,3/3] linux-generic: schedule: make sure SCHED queues get freed by the scheduler

Message ID 1426586009-21519-4-git-send-email-ciprian.barbu@linaro.org
State New
Headers show

Commit Message

Ciprian Barbu March 17, 2015, 9:53 a.m. UTC
ODP_QUEUE_TYPE_SCHED queues only get marked as destroyed, they need to be
removed from the pri_queues of the linux-generic scheduler

Signed-off-by: Ciprian Barbu <ciprian.barbu@linaro.org>
---
v2:
- removed #if 1 and trailing whitespaces

 platform/linux-generic/odp_schedule.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

Comments

Maxim Uvarov March 18, 2015, 9:17 a.m. UTC | #1
On 03/17/15 12:53, Ciprian Barbu wrote:
> ODP_QUEUE_TYPE_SCHED queues only get marked as destroyed, they need to be
> removed from the pri_queues of the linux-generic scheduler
>
> Signed-off-by: Ciprian Barbu <ciprian.barbu@linaro.org>
> ---
> v2:
> - removed #if 1 and trailing whitespaces
>
>   platform/linux-generic/odp_schedule.c | 22 ++++++++++++++++++++++
>   1 file changed, 22 insertions(+)
>
> diff --git a/platform/linux-generic/odp_schedule.c b/platform/linux-generic/odp_schedule.c
> index dd65168..18513da 100644
> --- a/platform/linux-generic/odp_schedule.c
> +++ b/platform/linux-generic/odp_schedule.c
> @@ -153,6 +153,28 @@ int odp_schedule_term_global(void)
>   
>   	for (i = 0; i < ODP_CONFIG_SCHED_PRIOS; i++) {
>   		for (j = 0; j < QUEUES_PER_PRIO; j++) {
> +			odp_queue_t pri_q = sched->pri_queue[i][j];
> +
> +			for (;;) {
> +				odp_event_t ev = odp_queue_deq(pri_q);
> +				odp_buffer_t desc_buf;
> +				queue_desc_t *desc;
> +				odp_queue_t queue;
> +
> +				desc_buf = odp_buffer_from_event(ev);
> +				if (desc_buf == ODP_BUFFER_INVALID)
> +					break;

It looks like we did not check return of odp_buffer_from_event() 
anywhere. But we check that event is not ODP_EVENT_INVALID.

That is not performance critical function so I think it's ok to use 
odp_queue_deq(), not odp_queue_deq_multi().

> +
> +				desc  = odp_buffer_addr(desc_buf);
> +				queue = desc->queue;
> +				/* Let deq_multi_destroy do the job */
> +				if (queue_is_destroyed(queue)) {
> +					odp_queue_deq_multi(queue,
> +							    sched_local.ev,
> +							    MAX_DEQ);
> +				}
> +			}
> +
>   			if (odp_queue_destroy(sched->pri_queue[i][j])) {
if you set above it to pri_q var, please use pri_q here also.

Maxim.
>   				ODP_ERR("Sched term: Queue destroy fail.\n");
>   				rc = -1;
Ciprian Barbu March 18, 2015, 10:07 a.m. UTC | #2
On Wed, Mar 18, 2015 at 11:17 AM, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:
> On 03/17/15 12:53, Ciprian Barbu wrote:
>>
>> ODP_QUEUE_TYPE_SCHED queues only get marked as destroyed, they need to be
>> removed from the pri_queues of the linux-generic scheduler
>>
>> Signed-off-by: Ciprian Barbu <ciprian.barbu@linaro.org>
>> ---
>> v2:
>> - removed #if 1 and trailing whitespaces
>>
>>   platform/linux-generic/odp_schedule.c | 22 ++++++++++++++++++++++
>>   1 file changed, 22 insertions(+)
>>
>> diff --git a/platform/linux-generic/odp_schedule.c
>> b/platform/linux-generic/odp_schedule.c
>> index dd65168..18513da 100644
>> --- a/platform/linux-generic/odp_schedule.c
>> +++ b/platform/linux-generic/odp_schedule.c
>> @@ -153,6 +153,28 @@ int odp_schedule_term_global(void)
>>         for (i = 0; i < ODP_CONFIG_SCHED_PRIOS; i++) {
>>                 for (j = 0; j < QUEUES_PER_PRIO; j++) {
>> +                       odp_queue_t pri_q = sched->pri_queue[i][j];
>> +
>> +                       for (;;) {
>> +                               odp_event_t ev = odp_queue_deq(pri_q);
>> +                               odp_buffer_t desc_buf;
>> +                               queue_desc_t *desc;
>> +                               odp_queue_t queue;
>> +
>> +                               desc_buf = odp_buffer_from_event(ev);
>> +                               if (desc_buf == ODP_BUFFER_INVALID)
>> +                                       break;
>
>
> It looks like we did not check return of odp_buffer_from_event() anywhere.
> But we check that event is not ODP_EVENT_INVALID.
>
> That is not performance critical function so I think it's ok to use
> odp_queue_deq(), not odp_queue_deq_multi().

It's actually not. The problem here is that odp_queu_destroy does not
actually destroy SCHED queues. For a queue to be destroyed it's status
must be set to QUEUE_STATUS_FREE. For ODP_QUEUE_TYPE_SCHED queues,
odp_queue_destroy sets the status to QUEUE_STATUS_DESTROYED, which is
not enough for odp_queue_term_global to finish the job, the status
must be QUEUE_STATUS_FREE.

This sounds like crazy at first, but it is necessary so that the
internal priority queues are drained, there are some desc_bufs for
each scheduled queues, simply marking the scheduled queue as free is
not enough, the desc_buf must be freed too. For that the scheduler
code relies on schedule() to process the priority queues, and that
code uses queue_deq_multi:
https://git.linaro.org/lng/odp.git/blob/df9cacd8cd46629ae74173461f4af7187cfbb670:/platform/linux-generic/odp_schedule.c#l330

>
>> +
>> +                               desc  = odp_buffer_addr(desc_buf);
>> +                               queue = desc->queue;
>> +                               /* Let deq_multi_destroy do the job */
>> +                               if (queue_is_destroyed(queue)) {
>> +                                       odp_queue_deq_multi(queue,
>> +
>> sched_local.ev,
>> +                                                           MAX_DEQ);
>> +                               }
>> +                       }
>> +
>>                         if (odp_queue_destroy(sched->pri_queue[i][j])) {
>
> if you set above it to pri_q var, please use pri_q here also.

Ok, I didn't notice this.

>
> Maxim.
>>
>>                                 ODP_ERR("Sched term: Queue destroy
>> fail.\n");
>>                                 rc = -1;
>
>
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/lng-odp
Ola Liljedahl March 18, 2015, 4:13 p.m. UTC | #3
On 18 March 2015 at 11:07, Ciprian Barbu <ciprian.barbu@linaro.org> wrote:

> On Wed, Mar 18, 2015 at 11:17 AM, Maxim Uvarov <maxim.uvarov@linaro.org>
> wrote:
> > On 03/17/15 12:53, Ciprian Barbu wrote:
> >>
> >> ODP_QUEUE_TYPE_SCHED queues only get marked as destroyed, they need to
> be
> >> removed from the pri_queues of the linux-generic scheduler
> >>
> >> Signed-off-by: Ciprian Barbu <ciprian.barbu@linaro.org>
> >> ---
> >> v2:
> >> - removed #if 1 and trailing whitespaces
> >>
> >>   platform/linux-generic/odp_schedule.c | 22 ++++++++++++++++++++++
> >>   1 file changed, 22 insertions(+)
> >>
> >> diff --git a/platform/linux-generic/odp_schedule.c
> >> b/platform/linux-generic/odp_schedule.c
> >> index dd65168..18513da 100644
> >> --- a/platform/linux-generic/odp_schedule.c
> >> +++ b/platform/linux-generic/odp_schedule.c
> >> @@ -153,6 +153,28 @@ int odp_schedule_term_global(void)
> >>         for (i = 0; i < ODP_CONFIG_SCHED_PRIOS; i++) {
> >>                 for (j = 0; j < QUEUES_PER_PRIO; j++) {
> >> +                       odp_queue_t pri_q = sched->pri_queue[i][j];
> >> +
> >> +                       for (;;) {
> >> +                               odp_event_t ev = odp_queue_deq(pri_q);
> >> +                               odp_buffer_t desc_buf;
> >> +                               queue_desc_t *desc;
> >> +                               odp_queue_t queue;
> >> +
> >> +                               desc_buf = odp_buffer_from_event(ev);
> >> +                               if (desc_buf == ODP_BUFFER_INVALID)
> >> +                                       break;
> >
> >
> > It looks like we did not check return of odp_buffer_from_event()
> anywhere.
> > But we check that event is not ODP_EVENT_INVALID.
> >
> > That is not performance critical function so I think it's ok to use
> > odp_queue_deq(), not odp_queue_deq_multi().
>
> It's actually not. The problem here is that odp_queu_destroy does not
> actually destroy SCHED queues. For a queue to be destroyed it's status
> must be set to QUEUE_STATUS_FREE. For ODP_QUEUE_TYPE_SCHED queues,
> odp_queue_destroy sets the status to QUEUE_STATUS_DESTROYED, which is
> not enough for odp_queue_term_global to finish the job, the status
> must be QUEUE_STATUS_FREE.
>
> This sounds like crazy at first, but it is necessary so that the
> internal priority queues are drained, there are some desc_bufs for
> each scheduled queues, simply marking the scheduled queue as free is
> not enough, the desc_buf must be freed too. For that the scheduler
> code relies on schedule() to process the priority queues, and that
> code uses queue_deq_multi:
>
> https://git.linaro.org/lng/odp.git/blob/df9cacd8cd46629ae74173461f4af7187cfbb670:/platform/linux-generic/odp_schedule.c#l330
>
>  Good description. Why isn't it in the code? Who will read this email in
one month/year/decade's time?

>
> >> +
> >> +                               desc  = odp_buffer_addr(desc_buf);
> >> +                               queue = desc->queue;
> >> +                               /* Let deq_multi_destroy do the job */
> >> +                               if (queue_is_destroyed(queue)) {
> >> +                                       odp_queue_deq_multi(queue,
> >> +
> >> sched_local.ev,
> >> +                                                           MAX_DEQ);
> >> +                               }
> >> +                       }
> >> +
> >>                         if (odp_queue_destroy(sched->pri_queue[i][j])) {
> >
> > if you set above it to pri_q var, please use pri_q here also.
>
> Ok, I didn't notice this.
>
> >
> > Maxim.
> >>
> >>                                 ODP_ERR("Sched term: Queue destroy
> >> fail.\n");
> >>                                 rc = -1;
> >
> >
> >
> > _______________________________________________
> > lng-odp mailing list
> > lng-odp@lists.linaro.org
> > http://lists.linaro.org/mailman/listinfo/lng-odp
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/lng-odp
>
Ciprian Barbu March 19, 2015, 9:10 a.m. UTC | #4
On Wed, Mar 18, 2015 at 6:13 PM, Ola Liljedahl <ola.liljedahl@linaro.org> wrote:
> On 18 March 2015 at 11:07, Ciprian Barbu <ciprian.barbu@linaro.org> wrote:
>>
>> On Wed, Mar 18, 2015 at 11:17 AM, Maxim Uvarov <maxim.uvarov@linaro.org>
>> wrote:
>> > On 03/17/15 12:53, Ciprian Barbu wrote:
>> >>
>> >> ODP_QUEUE_TYPE_SCHED queues only get marked as destroyed, they need to
>> >> be
>> >> removed from the pri_queues of the linux-generic scheduler
>> >>
>> >> Signed-off-by: Ciprian Barbu <ciprian.barbu@linaro.org>
>> >> ---
>> >> v2:
>> >> - removed #if 1 and trailing whitespaces
>> >>
>> >>   platform/linux-generic/odp_schedule.c | 22 ++++++++++++++++++++++
>> >>   1 file changed, 22 insertions(+)
>> >>
>> >> diff --git a/platform/linux-generic/odp_schedule.c
>> >> b/platform/linux-generic/odp_schedule.c
>> >> index dd65168..18513da 100644
>> >> --- a/platform/linux-generic/odp_schedule.c
>> >> +++ b/platform/linux-generic/odp_schedule.c
>> >> @@ -153,6 +153,28 @@ int odp_schedule_term_global(void)
>> >>         for (i = 0; i < ODP_CONFIG_SCHED_PRIOS; i++) {
>> >>                 for (j = 0; j < QUEUES_PER_PRIO; j++) {
>> >> +                       odp_queue_t pri_q = sched->pri_queue[i][j];
>> >> +
>> >> +                       for (;;) {
>> >> +                               odp_event_t ev = odp_queue_deq(pri_q);
>> >> +                               odp_buffer_t desc_buf;
>> >> +                               queue_desc_t *desc;
>> >> +                               odp_queue_t queue;
>> >> +
>> >> +                               desc_buf = odp_buffer_from_event(ev);
>> >> +                               if (desc_buf == ODP_BUFFER_INVALID)
>> >> +                                       break;
>> >
>> >
>> > It looks like we did not check return of odp_buffer_from_event()
>> > anywhere.
>> > But we check that event is not ODP_EVENT_INVALID.
>> >
>> > That is not performance critical function so I think it's ok to use
>> > odp_queue_deq(), not odp_queue_deq_multi().
>>
>> It's actually not. The problem here is that odp_queu_destroy does not
>> actually destroy SCHED queues. For a queue to be destroyed it's status
>> must be set to QUEUE_STATUS_FREE. For ODP_QUEUE_TYPE_SCHED queues,
>> odp_queue_destroy sets the status to QUEUE_STATUS_DESTROYED, which is
>> not enough for odp_queue_term_global to finish the job, the status
>> must be QUEUE_STATUS_FREE.
>>
>> This sounds like crazy at first, but it is necessary so that the
>> internal priority queues are drained, there are some desc_bufs for
>> each scheduled queues, simply marking the scheduled queue as free is
>> not enough, the desc_buf must be freed too. For that the scheduler
>> code relies on schedule() to process the priority queues, and that
>> code uses queue_deq_multi:
>>
>> https://git.linaro.org/lng/odp.git/blob/df9cacd8cd46629ae74173461f4af7187cfbb670:/platform/linux-generic/odp_schedule.c#l330
>>
>  Good description. Why isn't it in the code? Who will read this email in one
> month/year/decade's time?

I generally saw reluctance towards having long comments in the code,
maybe I just misinterpreted. But it wont matter anyway, Petri wants to
rework the scheduler so that tricks like this will not be necessary.
This was discussed in yesterday's ODP ARCH meeting. Maxim will only
apply the first patch of this series, which implements proper queue
termination in the schedule validation test.

>
>> >
>> >> +
>> >> +                               desc  = odp_buffer_addr(desc_buf);
>> >> +                               queue = desc->queue;
>> >> +                               /* Let deq_multi_destroy do the job */
>> >> +                               if (queue_is_destroyed(queue)) {
>> >> +                                       odp_queue_deq_multi(queue,
>> >> +
>> >> sched_local.ev,
>> >> +                                                           MAX_DEQ);
>> >> +                               }
>> >> +                       }
>> >> +
>> >>                         if (odp_queue_destroy(sched->pri_queue[i][j]))
>> >> {
>> >
>> > if you set above it to pri_q var, please use pri_q here also.
>>
>> Ok, I didn't notice this.
>>
>> >
>> > Maxim.
>> >>
>> >>                                 ODP_ERR("Sched term: Queue destroy
>> >> fail.\n");
>> >>                                 rc = -1;
>> >
>> >
>> >
>> > _______________________________________________
>> > lng-odp mailing list
>> > lng-odp@lists.linaro.org
>> > http://lists.linaro.org/mailman/listinfo/lng-odp
>>
>> _______________________________________________
>> lng-odp mailing list
>> lng-odp@lists.linaro.org
>> http://lists.linaro.org/mailman/listinfo/lng-odp
>
>
diff mbox

Patch

diff --git a/platform/linux-generic/odp_schedule.c b/platform/linux-generic/odp_schedule.c
index dd65168..18513da 100644
--- a/platform/linux-generic/odp_schedule.c
+++ b/platform/linux-generic/odp_schedule.c
@@ -153,6 +153,28 @@  int odp_schedule_term_global(void)
 
 	for (i = 0; i < ODP_CONFIG_SCHED_PRIOS; i++) {
 		for (j = 0; j < QUEUES_PER_PRIO; j++) {
+			odp_queue_t pri_q = sched->pri_queue[i][j];
+
+			for (;;) {
+				odp_event_t ev = odp_queue_deq(pri_q);
+				odp_buffer_t desc_buf;
+				queue_desc_t *desc;
+				odp_queue_t queue;
+
+				desc_buf = odp_buffer_from_event(ev);
+				if (desc_buf == ODP_BUFFER_INVALID)
+					break;
+
+				desc  = odp_buffer_addr(desc_buf);
+				queue = desc->queue;
+				/* Let deq_multi_destroy do the job */
+				if (queue_is_destroyed(queue)) {
+					odp_queue_deq_multi(queue,
+							    sched_local.ev,
+							    MAX_DEQ);
+				}
+			}
+
 			if (odp_queue_destroy(sched->pri_queue[i][j])) {
 				ODP_ERR("Sched term: Queue destroy fail.\n");
 				rc = -1;