[Cbe-oss-dev] [PATCH 7/10] MARS: workload queue api fix
Kazunori Asayama
asayama at sm.sony.co.jp
Thu Aug 28 19:04:17 EST 2008
Yuji Mano wrote:
> This modifies the internal workload queue API in the host-side library. When
> scheduling a new workload, the workload model may need to initialize parts of
> the workload context once it has been reserved in an available slot of the
> workload queue.
>
> Previously a separate call that returns the pointer to the
> workload context was provided. However, that may cause simultaneous access
> problems since the workload queue will not be locked during the whole
> scheduling call.
>
> This patch removes the separate API call, and instead adds a callback interface
> to allow for the workload model to modify the workload context within the
> mutex protected 'workload_queue_schedule' call.
Or alternative solution is to introduce another state such as
'MARS_WORKLOAD_STATE_SCHEDULING' for intermediate state between
workload_queue_context() and workload_queue_schedule().
>
> The workload wait calls now also return a copy of the workload context if
> requested.
>
> Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>
>
> ---
> include/host/mars/mars_workload_queue.h | 14 ++++++----
> src/host/lib/mars_task.c | 37 ++++++++++++++++------------
> src/host/lib/mars_workload_queue.c | 42 ++++++++++++++++----------------
> 3 files changed, 52 insertions(+), 41 deletions(-)
>
> --- a/include/host/mars/mars_workload_queue.h
> +++ b/include/host/mars/mars_workload_queue.h
> @@ -44,18 +44,22 @@ extern "C" {
>
> #include "mars/mars_workload_types.h"
>
> +typedef void (*workload_schedule_callback)
> + (struct mars_workload_context *workload, void *args);
> +
> int workload_queue_initialize(struct mars_workload_queue *queue);
> int workload_queue_finalize(struct mars_workload_queue *queue);
> int workload_queue_add(struct mars_workload_queue *queue, uint16_t *id,
> struct mars_workload_context *workload, uint8_t type);
> int workload_queue_remove(struct mars_workload_queue *queue, uint16_t id,
> struct mars_workload_context *workload);
> -int workload_queue_context(struct mars_workload_queue *queue, uint16_t id,
> - struct mars_workload_context **workload);
> int workload_queue_schedule(struct mars_workload_queue *queue, uint16_t id,
> - uint8_t priority);
> -int workload_queue_wait(struct mars_workload_queue *queue, uint16_t id);
> -int workload_queue_try_wait(struct mars_workload_queue *queue, uint16_t id);
> + uint8_t priority, workload_schedule_callback callback,
> + void *callback_args);
> +int workload_queue_wait(struct mars_workload_queue *queue, uint16_t id,
> + struct mars_workload_context *workload);
> +int workload_queue_try_wait(struct mars_workload_queue *queue, uint16_t id,
> + struct mars_workload_context *workload);
> int workload_queue_signal_send(struct mars_workload_queue *queue, uint16_t id);
>
> #if defined(__cplusplus)
> --- a/src/host/lib/mars_task.c
> +++ b/src/host/lib/mars_task.c
> @@ -115,8 +115,8 @@ int mars_task_finalize(struct mars_task_
> MARS_CHECK_RET(id->workload_id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
>
> int ret;
> - struct mars_context *mars = (struct mars_context *)id->mars_context_ea;
> struct mars_task_context task;
> + struct mars_context *mars = (struct mars_context *)id->mars_context_ea;
>
> mars_mutex_lock(mars->mutex);
>
> @@ -136,6 +136,17 @@ int mars_task_finalize(struct mars_task_
> return MARS_SUCCESS;
> }
>
> +static void callback(struct mars_workload_context *workload, void *args)
> +{
> + struct mars_task_context *task = (struct mars_task_context *)workload;
> + struct mars_task_args *task_args = (struct mars_task_args *)args;
> +
> + /* initialize task specific context variables */
> + task->stack = 0;
> + if (task_args)
> + memcpy(&task->args, task_args, sizeof(struct mars_task_args));
> +}
> +
> int mars_task_schedule(struct mars_task_id *id,
> struct mars_task_args *args,
> uint8_t priority)
> @@ -145,24 +156,14 @@ int mars_task_schedule(struct mars_task_
> MARS_CHECK_RET(id->workload_id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
>
> int ret;
> - struct mars_context *mars = (struct mars_context *)id->mars_context_ea;
> struct mars_task_context *task = NULL;
> + struct mars_context *mars = (struct mars_context *)id->mars_context_ea;
>
> mars_mutex_lock(mars->mutex);
>
> - /* get workload context pointer from the workload queue */
> - ret = workload_queue_context(mars->workload_queue, id->workload_id,
> - (struct mars_workload_context **)&task);
> - MARS_CHECK_RET(ret == MARS_SUCCESS, ret);
> -
> - /* initialize task specific context variables */
> - task->stack = 0;
> - if (args)
> - memcpy(&task->args, args, sizeof(struct mars_task_args));
> -
> /* schedule the workload in the workload queue */
> ret = workload_queue_schedule(mars->workload_queue, id->workload_id,
> - priority);
> + priority, callback, args);
> MARS_CHECK_RET(ret == MARS_SUCCESS, ret);
>
> mars_mutex_unlock(mars->mutex);
> @@ -179,9 +180,12 @@ int mars_task_wait(struct mars_task_id *
> MARS_CHECK_RET(id->workload_id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
>
> int ret;
> + struct mars_task_context task;
> struct mars_context *mars = (struct mars_context *)id->mars_context_ea;
>
> - ret = workload_queue_wait(mars->workload_queue, id->workload_id);
> + /* blocking wait for workload completion */
> + ret = workload_queue_wait(mars->workload_queue, id->workload_id,
> + (struct mars_workload_context *)&task);
> MARS_CHECK_RET(ret == MARS_SUCCESS, ret);
>
> return MARS_SUCCESS;
> @@ -194,9 +198,12 @@ int mars_task_try_wait(struct mars_task_
> MARS_CHECK_RET(id->workload_id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
>
> int ret;
> + struct mars_task_context task;
> struct mars_context *mars = (struct mars_context *)id->mars_context_ea;
>
> - ret = workload_queue_try_wait(mars->workload_queue, id->workload_id);
> + /* non-blocking wait for workload completion */
> + ret = workload_queue_try_wait(mars->workload_queue, id->workload_id,
> + (struct mars_workload_context *)&task);
> MARS_CHECK_RET(ret == MARS_SUCCESS, ret);
>
> return MARS_SUCCESS;
> --- a/src/host/lib/mars_workload_queue.c
> +++ b/src/host/lib/mars_workload_queue.c
> @@ -147,26 +147,9 @@ int workload_queue_remove(struct mars_wo
> return MARS_SUCCESS;
> }
>
> -int workload_queue_context(struct mars_workload_queue *queue, uint16_t id,
> - struct mars_workload_context **workload)
> -{
> - MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> - MARS_CHECK_RET(workload, MARS_ERROR_NULL);
> - MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
> -
> - int block = id / MARS_WORKLOAD_PER_BLOCK;
> - int index = id % MARS_WORKLOAD_PER_BLOCK;
> -
> - MARS_CHECK_RET(queue->block[block].bits[index].state !=
> - MARS_WORKLOAD_STATE_NONE, MARS_ERROR_STATE);
> -
> - *workload = &queue->context[id];
> -
> - return MARS_SUCCESS;
> -}
> -
> int workload_queue_schedule(struct mars_workload_queue *queue, uint16_t id,
> - uint8_t priority)
> + uint8_t priority, workload_schedule_callback callback,
> + void *callback_args)
> {
> MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
> @@ -177,6 +160,11 @@ int workload_queue_schedule(struct mars_
> MARS_CHECK_RET(queue->block[block].bits[index].state ==
> MARS_WORKLOAD_STATE_FINISHED, MARS_ERROR_STATE);
>
> + /* if provided call the callback with the workload context pointer */
> + if (callback)
> + (*callback)(&queue->context[id], callback_args);
> +
> + /* update workload queue info */
> queue->block[block].bits[index].state = MARS_WORKLOAD_STATE_READY;
> queue->block[block].bits[index].priority = priority;
> queue->block[block].bits[index].counter = MARS_WORKLOAD_COUNTER_MIN;
> @@ -186,9 +174,11 @@ int workload_queue_schedule(struct mars_
> return MARS_SUCCESS;
> }
>
> -int workload_queue_wait(struct mars_workload_queue *queue, uint16_t id)
> +int workload_queue_wait(struct mars_workload_queue *queue, uint16_t id,
> + struct mars_workload_context *workload)
> {
> MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> + MARS_CHECK_RET(workload, MARS_ERROR_NULL);
> MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
>
> int block = id / MARS_WORKLOAD_PER_BLOCK;
> @@ -201,12 +191,18 @@ int workload_queue_wait(struct mars_work
> MARS_WORKLOAD_STATE_FINISHED)
> sched_yield();
>
> + /* copy workload context out from workload queue */
> + memcpy(workload, &queue->context[id],
> + sizeof(struct mars_workload_context));
> +
> return MARS_SUCCESS;
> }
>
> -int workload_queue_try_wait(struct mars_workload_queue *queue, uint16_t id)
> +int workload_queue_try_wait(struct mars_workload_queue *queue, uint16_t id,
> + struct mars_workload_context *workload)
> {
> MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> + MARS_CHECK_RET(workload, MARS_ERROR_NULL);
> MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
>
> int block = id / MARS_WORKLOAD_PER_BLOCK;
> @@ -219,6 +215,10 @@ int workload_queue_try_wait(struct mars_
> MARS_WORKLOAD_STATE_FINISHED)
> return MARS_ERROR_BUSY;
>
> + /* copy workload context out from workload queue */
> + memcpy(workload, &queue->context[id],
> + sizeof(struct mars_workload_context));
> +
> return MARS_SUCCESS;
> }
>
>
>
>
--
(ASAYAMA Kazunori
(asayama at sm.sony.co.jp))
t
More information about the cbe-oss-dev
mailing list