[Cbe-oss-dev] [PATCH 10/10 v2]MARS/modules: Task module implementation

Yuji Mano yuji.mano at am.sony.com
Sat Nov 22 13:11:52 EST 2008


This adds the task module implementation.

Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>

---
v2:
- updated implementation to use new module API to avoid accessing workload bits directly

 modules/task/src/mpu/module/task_module.c |  438 ++++++++++++++++++++++++++++++
 modules/task/src/mpu/module/task_module.h |   83 +++++
 2 files changed, 521 insertions(+)

--- /dev/null
+++ b/modules/task/src/mpu/module/task_module.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright 2008 Sony Corporation of America
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this Library and associated documentation files (the
+ * "Library"), to deal in the Library without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Library, and to
+ * permit persons to whom the Library is furnished to do so, subject to
+ * the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be
+ *  included in all copies or substantial portions of the Library.
+ *
+ *  If you modify the Library, you may copy and distribute your modified
+ *  version of the Library in object code or as an executable provided
+ *  that you also do one of the following:
+ *
+ *   Accompany the modified version of the Library with the complete
+ *   corresponding machine-readable source code for the modified version
+ *   of the Library; or,
+ *
+ *   Accompany the modified version of the Library with a written offer
+ *   for a complete machine-readable copy of the corresponding source
+ *   code of the modified version of the Library.
+ *
+ *
+ * THE LIBRARY IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * LIBRARY OR THE USE OR OTHER DEALINGS IN THE LIBRARY.
+ */
+
+#include "task_module.h"
+
+/* stack pointer storage */
+void *_module_stack;
+void *_task_stack;
+
+/* global task structs */
+static struct mars_task_context *task;
+static struct mars_task_context_save_unit list[MARS_TASK_CONTEXT_SAVE_UNIT_MAX];
+
+/* task entry */
+typedef void (*mars_task_entry)(struct mars_task_args *args,
+	struct mars_task_module_syscalls *task_module_syscalls);
+
+static uint32_t get_kernel_id(void)
+{
+	return mars_module_get_kernel_id();
+}
+
+static struct mars_task_context *get_task(void)
+{
+	return (struct mars_task_context *)mars_module_get_workload();
+}
+
+static struct mars_task_context *get_task_by_id(struct mars_task_id *task_id)
+{
+	return (struct mars_task_context *)
+		mars_module_get_workload_by_id(task_id->workload_id);
+}
+
+static void __attribute__((noinline)) registers_save(void)
+{
+	/* push non-volatile registers on to the workload stack */
+	asm volatile (
+		"lqa	$75, _task_stack;"
+
+		"stqd	$80, -16($75);"
+		"stqd	$81, -32($75);"
+		"stqd	$82, -48($75);"
+		"stqd	$83, -64($75);"
+		"stqd	$84, -80($75);"
+		"stqd	$85, -96($75);"
+		"stqd	$86, -112($75);"
+		"stqd	$87, -128($75);"
+		"stqd	$88, -144($75);"
+		"stqd	$89, -160($75);"
+		"stqd	$90, -176($75);"
+		"stqd	$91, -192($75);"
+		"stqd	$92, -208($75);"
+		"stqd	$93, -224($75);"
+		"stqd	$94, -240($75);"
+		"stqd	$95, -256($75);"
+		"stqd	$96, -272($75);"
+		"stqd	$97, -288($75);"
+		"stqd	$98, -304($75);"
+		"stqd	$99, -320($75);"
+		"stqd	$100, -336($75);"
+		"stqd	$101, -352($75);"
+		"stqd	$102, -368($75);"
+		"stqd	$103, -384($75);"
+		"stqd	$104, -400($75);"
+		"stqd	$105, -416($75);"
+		"stqd	$106, -432($75);"
+		"stqd	$107, -448($75);"
+		"stqd	$108, -464($75);"
+		"stqd	$109, -480($75);"
+		"stqd	$110, -496($75);"
+		"stqd	$111, -512($75);"
+		"stqd	$112, -528($75);"
+		"stqd	$113, -544($75);"
+		"stqd	$114, -560($75);"
+		"stqd	$115, -576($75);"
+		"stqd	$116, -592($75);"
+		"stqd	$117, -608($75);"
+		"stqd	$118, -624($75);"
+		"stqd	$119, -640($75);"
+		"stqd	$120, -656($75);"
+		"stqd	$121, -672($75);"
+		"stqd	$122, -688($75);"
+		"stqd	$123, -704($75);"
+		"stqd	$124, -720($75);"
+		"stqd	$125, -736($75);"
+		"stqd	$126, -752($75);"
+		"stqd	$127, -768($75);"
+	);
+}
+
+static void __attribute__((noinline)) registers_restore(void)
+{
+	/* pop non-volatile registers from saved workload stack */
+	asm volatile (
+		"lqa	$75, _task_stack;"
+
+		"lqd	$80, -16($75);"
+		"lqd	$81, -32($75);"
+		"lqd	$82, -48($75);"
+		"lqd	$83, -64($75);"
+		"lqd	$84, -80($75);"
+		"lqd	$85, -96($75);"
+		"lqd	$86, -112($75);"
+		"lqd	$87, -128($75);"
+		"lqd	$88, -144($75);"
+		"lqd	$89, -160($75);"
+		"lqd	$90, -176($75);"
+		"lqd	$91, -192($75);"
+		"lqd	$92, -208($75);"
+		"lqd	$93, -224($75);"
+		"lqd	$94, -240($75);"
+		"lqd	$95, -256($75);"
+		"lqd	$96, -272($75);"
+		"lqd	$97, -288($75);"
+		"lqd	$98, -304($75);"
+		"lqd	$99, -320($75);"
+		"lqd	$100, -336($75);"
+		"lqd	$101, -352($75);"
+		"lqd	$102, -368($75);"
+		"lqd	$103, -384($75);"
+		"lqd	$104, -400($75);"
+		"lqd	$105, -416($75);"
+		"lqd	$106, -432($75);"
+		"lqd	$107, -448($75);"
+		"lqd	$108, -464($75);"
+		"lqd	$109, -480($75);"
+		"lqd	$110, -496($75);"
+		"lqd	$111, -512($75);"
+		"lqd	$112, -528($75);"
+		"lqd	$113, -544($75);"
+		"lqd	$114, -560($75);"
+		"lqd	$115, -576($75);"
+		"lqd	$116, -592($75);"
+		"lqd	$117, -608($75);"
+		"lqd	$118, -624($75);"
+		"lqd	$119, -640($75);"
+		"lqd	$120, -656($75);"
+		"lqd	$121, -672($75);"
+		"lqd	$122, -688($75);"
+		"lqd	$123, -704($75);"
+		"lqd	$124, -720($75);"
+		"lqd	$125, -736($75);"
+		"lqd	$126, -752($75);"
+		"lqd	$127, -768($75);"
+	);
+}
+
+static void __attribute__((noinline)) context_save(void)
+{
+	int i, offset = 0;
+
+	/* save registers state */
+	registers_save();
+
+	/* save workload stack pointer */
+	task->stack = (uint32_t)_task_stack;
+
+	/* get context save unit list */
+	mars_dma_get_and_wait(list, task->context_save_unit_ea,
+		MARS_TASK_CONTEXT_SAVE_UNIT_SIZE *
+		MARS_TASK_CONTEXT_SAVE_UNIT_MAX, MARS_DMA_TAG);
+
+	/* loop through save unit list */
+	for (i = 0; i < MARS_TASK_CONTEXT_SAVE_UNIT_MAX; i++) {
+		/* list terminator so exit loop */
+		if (!list[i].size)
+			break;
+
+		/* request dma put of the context save unit specified */
+		mars_dma_large_put((void *)(task->vaddr + list[i].addr),
+			task->context_save_area_ea + offset,
+			list[i].size, MARS_DMA_TAG);
+
+		offset += list[i].size;
+	}
+
+	/* wait for all dmas to complete */
+	mars_dma_wait(MARS_DMA_TAG);
+}
+
+static void __attribute__((noinline)) context_restore(void)
+{
+	int i, offset = 0;
+
+	/* get save context save unit list */
+	mars_dma_get_and_wait(list, task->context_save_unit_ea,
+		MARS_TASK_CONTEXT_SAVE_UNIT_SIZE *
+		MARS_TASK_CONTEXT_SAVE_UNIT_MAX, MARS_DMA_TAG);
+
+	/* loop through save unit list */
+	for (i = 0; i < MARS_TASK_CONTEXT_SAVE_UNIT_MAX; i++) {
+		/* list terminator so exit loop */
+		if (!list[i].size)
+			break;
+
+		/* request dma get of the context save unit specified */
+		mars_dma_large_get((void *)(task->vaddr + list[i].addr),
+			task->context_save_area_ea + offset,
+			list[i].size, MARS_DMA_TAG);
+
+		offset += list[i].size;
+	}
+
+	/* wait for all dmas to complete */
+	mars_dma_wait(MARS_DMA_TAG);
+
+	/* restore workload stack pointer */
+	_task_stack = (void *)task->stack;
+
+	/* restore registers state */
+	registers_restore();
+}
+
+static void __attribute__((noinline)) context_yield(void)
+{
+	/* save task stack pointer and restore module stack pointer */
+	asm volatile (
+		"stqa	$sp, _task_stack;"
+		"lqa	$sp, _module_stack;"
+	);
+
+	/* save task context */
+	context_save();
+
+	/* exit workload module */
+	mars_module_exit(MARS_WORKLOAD_STATE_READY);
+}
+
+static void __attribute__((noinline)) context_wait(void)
+{
+	/* save task stack pointer and restore module stack pointer */
+	asm volatile (
+		"stqa	$sp, _task_stack;"
+		"lqa	$sp, _module_stack;"
+	);
+
+	/* save task context */
+	context_save();
+
+	/* exit workload module */
+	mars_module_exit(MARS_WORKLOAD_STATE_WAITING);
+}
+
+static void __attribute__((noinline)) context_resume(void)
+{
+	/* restore task context */
+	context_restore();
+
+	/* restore task stack pointer */
+	asm volatile (
+		"lqa	$sp, _task_stack;"
+	);
+}
+
+static void __attribute__((noinline)) context_exit(void)
+{
+	/* restore module stack pointer */
+	asm volatile (
+		"lqa	$sp, _module_stack;"
+	);
+
+	/* exit workload module */
+	mars_module_exit(MARS_WORKLOAD_STATE_FINISHED);
+}
+
+static void task_exit(void)
+{
+	context_exit();
+}
+
+static void task_yield(void)
+{
+	context_yield();
+}
+
+static int task_schedule(uint16_t workload_id, struct mars_task_args *args,
+	uint8_t priority)
+{
+	int ret;
+	struct mars_task_context *schedule_task;
+	struct mars_workload_context *schedule_workload;
+
+	ret = mars_module_workload_schedule_begin(workload_id, priority,
+		&schedule_workload);
+	if (ret != MARS_SUCCESS)
+		return ret;
+
+	/* cast workload context to task context */
+	schedule_task = (struct mars_task_context *)schedule_workload;
+
+	/* initialize task specific context variables */
+	schedule_task->stack = 0;
+	if (args)
+		memcpy(&schedule_task->args, args,
+			sizeof(struct mars_task_args));
+
+	/* end process to schedule the workload in the workload queue */
+	ret = mars_module_workload_schedule_end(workload_id);
+	if (ret != MARS_SUCCESS)
+		return ret;
+
+	return MARS_SUCCESS;
+}
+
+static int task_wait(uint16_t workload_id)
+{
+	int ret;
+
+	/* make sure workload is initialized */
+	if (mars_module_get_workload_state_by_id(workload_id) ==
+		MARS_WORKLOAD_STATE_NONE)
+		return MARS_ERROR_STATE;
+
+	ret = mars_module_workload_wait_set(workload_id);
+	if (ret != MARS_SUCCESS)
+		return ret;
+
+	context_wait();
+
+	return mars_module_workload_wait_reset();
+}
+
+static int task_try_wait(uint16_t workload_id)
+{
+	/* make sure workload is initialized */
+	if (mars_module_get_workload_state_by_id(workload_id) ==
+		MARS_WORKLOAD_STATE_NONE)
+		return MARS_ERROR_STATE;
+
+	/* if workload not finished return busy */
+	if (mars_module_get_workload_state_by_id(workload_id) ==
+		MARS_WORKLOAD_STATE_FINISHED)
+		return MARS_ERROR_BUSY;
+
+	return mars_module_workload_wait_reset();
+}
+
+static int task_signal_send(uint16_t workload_id)
+{
+	return mars_module_workload_signal_set(workload_id);
+}
+
+static int task_signal_wait(void)
+{
+	context_wait();
+
+	return mars_module_workload_signal_reset();
+}
+
+static int task_signal_try_wait(void)
+{
+	/* if signal not yet received return busy */
+	if (mars_module_get_workload_signal() != MARS_WORKLOAD_SIGNAL_ON)
+		return MARS_ERROR_BUSY;
+
+	return mars_module_workload_signal_reset();
+}
+
+static struct mars_task_module_syscalls task_module_syscalls =
+{
+	get_kernel_id,
+	get_task,
+	get_task_by_id,
+
+	task_exit,
+	task_yield,
+	task_schedule,
+	task_wait,
+	task_try_wait,
+	task_signal_send,
+	task_signal_wait,
+	task_signal_try_wait
+};
+
+void mars_module_main(void)
+{
+	/* get task context */
+	task = get_task();
+
+	/* save module stack pointer */
+	asm volatile (
+		"stqa	$sp, _module_stack;"
+	);
+
+	/* if stack pointer is uninitialized run fresh, otherwise resume */
+	if (!task->stack) {
+		/* dma the exec code into mpu storage from host storage */
+		mars_dma_large_get_and_wait((void *)task->vaddr,
+			task->exec_ea, task->exec_size, MARS_DMA_TAG);
+
+		/* 0 the bss section */
+		memset((void *)task->vaddr + task->exec_size, 0,
+			task->bss_size);
+
+		/* call entry function */
+		((mars_task_entry)task->entry)(
+			&task->args, &task_module_syscalls);
+	} else {
+		context_resume();
+	}
+
+	/* we probably should never reach here */
+	mars_module_exit(MARS_WORKLOAD_STATE_FINISHED);
+}
--- /dev/null
+++ b/modules/task/src/mpu/module/task_module.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2008 Sony Corporation of America
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this Library and associated documentation files (the
+ * "Library"), to deal in the Library without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Library, and to
+ * permit persons to whom the Library is furnished to do so, subject to
+ * the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be
+ *  included in all copies or substantial portions of the Library.
+ *
+ *  If you modify the Library, you may copy and distribute your modified
+ *  version of the Library in object code or as an executable provided
+ *  that you also do one of the following:
+ *
+ *   Accompany the modified version of the Library with the complete
+ *   corresponding machine-readable source code for the modified version
+ *   of the Library; or,
+ *
+ *   Accompany the modified version of the Library with a written offer
+ *   for a complete machine-readable copy of the corresponding source
+ *   code of the modified version of the Library.
+ *
+ *
+ * THE LIBRARY IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * LIBRARY OR THE USE OR OTHER DEALINGS IN THE LIBRARY.
+ */
+
+#ifndef MARS_TASK_MODULE_H
+#define MARS_TASK_MODULE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <mars/dma.h>
+#include <mars/error.h>
+#include <mars/module.h>
+#include <mars/mutex.h>
+
+#include "mars/task_types.h"
+
+#include "task_internal_types.h"
+
+/* mars task module syscalls */
+struct mars_task_module_syscalls {
+	uint32_t			(*get_kernel_id)(void);
+	struct mars_task_context *	(*get_task)(void);
+	struct mars_task_context *	(*get_task_by_id)
+						(struct mars_task_id *task_id);
+
+	void	(*exit)(void);
+	void	(*yield)(void);
+	int	(*schedule)(uint16_t workload_id, struct mars_task_args *args,
+			uint8_t priority);
+	int	(*wait)(uint16_t workload_id);
+	int	(*try_wait)(uint16_t workload_id);
+	int	(*signal_send)(uint16_t workload_id);
+	int	(*signal_wait)(void);
+	int	(*signal_try_wait)(void);
+};
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+extern const struct mars_task_module_syscalls *mars_task_module_syscalls;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif





More information about the cbe-oss-dev mailing list