[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