In order to robustly drain all queues when the benchmark has ended, we enqueue a special event on every queue and invoke the scheduler until all such events have been received.
Signed-off-by: Ola Liljedahl <[email protected]> Reviewed-by: Brian Brooks <[email protected]> Reviewed-by: Honnappa Nagarahalli <[email protected]> --- v2: - Call odp_schedule() after draining to ensure ODP_EVENT_INVALID is returned and thus any scheduler context is released - Abort if failure to allocate or enqueue cool_down event - Use only one cool_down event, reuse for all queues test/common_plat/performance/odp_sched_latency.c | 59 ++++++++++++++++++------ 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/test/common_plat/performance/odp_sched_latency.c b/test/common_plat/performance/odp_sched_latency.c index 2b28cd7b..b4018687 100644 --- a/test/common_plat/performance/odp_sched_latency.c +++ b/test/common_plat/performance/odp_sched_latency.c @@ -57,9 +57,10 @@ ODP_STATIC_ASSERT(LO_PRIO_QUEUES <= MAX_QUEUES, "Too many LO priority queues"); /** Test event types */ typedef enum { - WARM_UP, /**< Warm up event */ - TRAFFIC, /**< Event used only as traffic load */ - SAMPLE /**< Event used to measure latency */ + WARM_UP, /**< Warm up event */ + COOL_DOWN,/**< Last event on queue */ + TRAFFIC, /**< Event used only as traffic load */ + SAMPLE /**< Event used to measure latency */ } event_type_t; /** Test event */ @@ -112,20 +113,52 @@ typedef struct { /** * Clear all scheduled queues. * - * Retry to be sure that all buffers have been scheduled. + * Use special cool_down event to guarantee that queue is drained. */ -static void clear_sched_queues(void) +static void clear_sched_queues(test_globals_t *globals) { odp_event_t ev; + odp_buffer_t buf; + test_event_t *event; + int i, j; + odp_queue_t fromq; - while (1) { - ev = odp_schedule(NULL, ODP_SCHED_NO_WAIT); + /* Allocate the cool_down event. */ + buf = odp_buffer_alloc(globals->pool); + if (buf == ODP_BUFFER_INVALID) + LOG_ABORT("Buffer alloc failed.\n"); - if (ev == ODP_EVENT_INVALID) - break; + event = odp_buffer_addr(buf); + event->type = COOL_DOWN; + ev = odp_buffer_to_event(buf); - odp_event_free(ev); + for (i = 0; i < NUM_PRIOS; i++) { + for (j = 0; j < globals->args.prio[i].queues; j++) { + /* Enqueue cool_down event on each queue. */ + if (odp_queue_enq(globals->queue[i][j], ev)) + LOG_ABORT("Queue enqueue failed.\n"); + + /* Invoke scheduler until cool_down event has been + * received. */ + while (1) { + ev = odp_schedule(NULL, ODP_SCHED_WAIT); + buf = odp_buffer_from_event(ev); + event = odp_buffer_addr(buf); + if (event->type == COOL_DOWN) + break; + odp_event_free(ev); + } + } } + + /* Free the cool_down event. */ + odp_event_free(ev); + + /* Call odp_schedule() to trigger a release of any scheduler context. */ + ev = odp_schedule(&fromq, ODP_SCHED_NO_WAIT); + if (ev != ODP_EVENT_INVALID) + LOG_ABORT("Queue %" PRIu64 " not empty.\n", + odp_queue_to_u64(fromq)); } /** @@ -394,10 +427,10 @@ static int test_schedule(int thr, test_globals_t *globals) odp_barrier_wait(&globals->barrier); - clear_sched_queues(); - - if (thr == MAIN_THREAD) + if (thr == MAIN_THREAD) { + clear_sched_queues(globals); print_results(globals); + } return 0; } -- 2.12.2
