[Cbe-oss-dev] [PATCH 7/10] MARS: workload queue api fix

Yuji Mano Yuji.Mano at am.sony.com
Thu Aug 28 05:32:39 EST 2008


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.

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;
 }
 






More information about the cbe-oss-dev mailing list