[Cbe-oss-dev] [PATCH 5/5]task: add unschedule api

Yuji Mano yuji.mano at am.sony.com
Wed Mar 25 12:48:28 EST 2009


This patch adds the task unschedule API.

The unschedule API will allow for unscheduling of scheduled tasks that might
become necessary in certain situations such as handling errors that might cause
tasks to get stuck in a state that prevents it from finishing.

Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>
---
 task/include/host/mars/task.h     |    5 ++++
 task/include/mpu/mars/task.h      |   40 ++++++++++++++++++++++++++++++++
 task/src/host/lib/task.c          |   47 ++++++++++++++++++++++++++++++++------
 task/src/mpu/lib/task.c           |    9 +++++++
 task/src/mpu/module/task_module.c |   21 ++++++++++++++++
 task/src/mpu/module/task_module.h |    7 +++++
 6 files changed, 122 insertions(+), 7 deletions(-)

--- a/task/include/host/mars/task.h
+++ b/task/include/host/mars/task.h
@@ -151,6 +151,11 @@ int mars_task_schedule(const struct mars
 /**
  * \ingroup group_mars_task
  */
+int mars_task_unschedule(const struct mars_task_id *id, int32_t exit_code);
+
+/**
+ * \ingroup group_mars_task
+ */
 int mars_task_wait(const struct mars_task_id *id, int32_t *exit_code);
 
 /**
--- a/task/include/mpu/mars/task.h
+++ b/task/include/mpu/mars/task.h
@@ -168,6 +168,46 @@ int mars_task_schedule(const struct mars
 
 /**
  * \ingroup group_mars_task
+ * \brief <b>[host/MPU]</b> Unschedules a MARS task from being executed.
+ *
+ * This function unschedules a previously scheduled task.
+ *
+ * When a task is unscheduled, it will behave as if the task has completed
+ * execution. The user is responsible for specifying a unique exit code when
+ * unscheduling tasks to handle the condition accordingly.
+ *
+ * If a scheduled task is unscheduled before execution, the workload will
+ * not be executed until a subsequent scheduling request is made.
+ *
+ * If the task is currently in a waiting state, calling unschedule will
+ * finish the workload and will not be resumed from the waiting state.
+ *
+ * If the task is currently in a running state, calling unschedule will
+ * immediately put the task into a finished state. However, execution of the
+ * task will only be suspended when the workload yields, waits, or finishes.
+ *
+ * \note
+ * Trying to unschedule a task that has not yet been scheduled, or has
+ * already finished a previously scheduled execution will return an error.
+ *
+ * <b>Key Parameters</b>:
+ * \n \n
+ * \e exit_code
+ * - The value passed into here can be obtained when calling \ref mars_task_wait
+ * or \ref mars_task_try_wait.
+ *
+ * \param[in] id		- pointer to task id to abort
+ * \param[out] exit_code	- value to be returned to the task wait call
+ * \return
+ *	MARS_SUCCESS		- successfully scheduled MARS task for execution
+ * \n	MARS_ERROR_NULL		- null pointer specified
+ * \n	MARS_ERROR_PARAMS	- bad task id specified
+ * \n	MARS_ERROR_STATE	- task is in an invalid state
+ */
+int mars_task_unschedule(const struct mars_task_id *id, int32_t exit_code);
+
+/**
+ * \ingroup group_mars_task
  * \brief <b>[host/MPU]</b> Waits for task completion.
  * <b>(Task Switch Call)</b>
  *
--- a/task/src/host/lib/task.c
+++ b/task/src/host/lib/task.c
@@ -273,11 +273,7 @@ int mars_task_destroy(const struct mars_
 	mars_ea_unmap(task->data_ea, task->data_size);
 
 	/* end process to remove the task from the workload queue */
-	ret = mars_workload_queue_remove_end(mars, id->workload_id, 0);
-	if (ret != MARS_SUCCESS)
-		return ret;
-
-	return MARS_SUCCESS;
+	return mars_workload_queue_remove_end(mars, id->workload_id, 0);
 }
 
 int mars_task_schedule(const struct mars_task_id *id,
@@ -323,11 +319,48 @@ int mars_task_schedule(const struct mars
 	mars_ea_sync();
 
 	/* end process to schedule the workload in the workload queue */
-	ret = mars_workload_queue_schedule_end(mars, id->workload_id, 0);
+	return mars_workload_queue_schedule_end(mars, id->workload_id, 0);
+}
+
+int mars_task_unschedule(const struct mars_task_id *id, int32_t exit_code)
+{
+	int ret;
+	struct mars_context *mars;
+	struct mars_task_context *task;
+	uint64_t workload_ea;
+
+	/* check function params */
+	if (!id)
+		return MARS_ERROR_NULL;
+	if (!id->mars_context_ea)
+		return MARS_ERROR_PARAMS;
+
+	/* get mars context pointer from task id */
+	mars = mars_ea_to_ptr(id->mars_context_ea);
+
+	/* begin process to schedule the workload in the workload queue */
+	ret = mars_workload_queue_unschedule_begin(mars, id->workload_id,
+						   &workload_ea);
 	if (ret != MARS_SUCCESS)
 		return ret;
 
-	return MARS_SUCCESS;
+	/* prepare work area for task context */
+	task = mars_ea_work_area_get(workload_ea,
+				     MARS_TASK_CONTEXT_ALIGN,
+				     MARS_TASK_CONTEXT_SIZE);
+
+	/* get task context from EA */
+	mars_ea_get(workload_ea, task, MARS_TASK_CONTEXT_SIZE);
+
+	/* store exit code in task context */
+	task->exit_code = exit_code;
+
+	/* update task context on EA */
+	mars_ea_put(workload_ea, task, MARS_TASK_CONTEXT_SIZE);
+	mars_ea_sync();
+
+	/* end process to unschedule the workload in the workload queue */
+	return mars_workload_queue_unschedule_end(mars, id->workload_id);
 }
 
 int mars_task_wait(const struct mars_task_id *id, int32_t *exit_code)
--- a/task/src/mpu/lib/task.c
+++ b/task/src/mpu/lib/task.c
@@ -108,6 +108,15 @@ int mars_task_schedule(const struct mars
 	return mars_task_module_schedule(id->workload_id, args, priority);
 }
 
+int mars_task_unschedule(const struct mars_task_id *id, int32_t exit_code)
+{
+	/* check function params */
+	if (!id)
+		return MARS_ERROR_NULL;
+
+	return mars_task_module_unschedule(id->workload_id, exit_code);
+}
+
 int mars_task_wait(const struct mars_task_id *id, int32_t *exit_code)
 {
 	struct mars_task_context *task;
--- a/task/src/mpu/module/task_module.c
+++ b/task/src/mpu/module/task_module.c
@@ -203,6 +203,26 @@ static int task_schedule(uint16_t worklo
 	return mars_module_workload_schedule_end(workload_id, 0);
 }
 
+static int task_unschedule(uint16_t workload_id, int32_t exit_code)
+{
+	int ret;
+	struct mars_task_context *unschedule_task;
+	struct mars_workload_context *unschedule_workload;
+
+	ret = mars_module_workload_unschedule_begin(workload_id,
+						    &unschedule_workload);
+	if (ret != MARS_SUCCESS)
+		return ret;
+
+	/* cast workload context to task context */
+	unschedule_task = (struct mars_task_context *)unschedule_workload;
+
+	unschedule_task->exit_code = exit_code;
+
+	/* end process to unschedule the workload in the workload queue */
+	return mars_module_workload_unschedule_end(workload_id);
+}
+
 static int task_wait(uint16_t workload_id, void *task_heap)
 {
 	int ret;
@@ -285,6 +305,7 @@ static struct mars_task_module_syscalls 
 	task_exit,
 	task_yield,
 	task_schedule,
+	task_unschedule,
 	task_wait,
 	task_try_wait,
 	task_signal_host,
--- a/task/src/mpu/module/task_module.h
+++ b/task/src/mpu/module/task_module.h
@@ -63,6 +63,7 @@ struct mars_task_module_syscalls {
 	int	(*schedule)(uint16_t workload_id,
 			    const struct mars_task_args *args,
 			    uint8_t priority);
+	int	(*unschedule)(uint16_t workload_id, int32_t exit_code);
 	int	(*wait)(uint16_t workload_id, void *heap);
 	int	(*try_wait)(uint16_t workload_id);
 	int	(*signal_host)(uint64_t watch_point_ea);
@@ -134,6 +135,12 @@ static inline int mars_task_module_sched
 						      priority);
 }
 
+static inline int mars_task_module_unschedule(uint16_t workload_id,
+					      int32_t exit_code)
+{
+	return (*mars_task_module_syscalls->unschedule)(workload_id, exit_code);
+}
+
 static inline int mars_task_module_wait(uint16_t workload_id, void *task_heap)
 {
 	return (*mars_task_module_syscalls->wait)(workload_id, task_heap);






More information about the cbe-oss-dev mailing list