[Cbe-oss-dev] [PATCH 10/10 v3]MARS/modules: Task module implementation
Yuji Mano
yuji.mano at am.sony.com
Wed Nov 26 09:56:41 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
v3:
- remove usage of internal defines and use new API
- replace mars_module_exit(state) calls with new replacement API
modules/task/src/mpu/module/task_module.c | 434 ++++++++++++++++++++++++++++++
modules/task/src/mpu/module/task_module.h | 83 +++++
2 files changed, 517 insertions(+)
--- /dev/null
+++ b/modules/task/src/mpu/module/task_module.c
@@ -0,0 +1,434 @@
+/*
+ * 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();
+
+ /* yield workload and put into ready state */
+ mars_module_workload_yield();
+}
+
+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();
+
+ /* put workload into waiting state */
+ mars_module_workload_wait();
+}
+
+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_finish(void)
+{
+ /* restore module stack pointer */
+ asm volatile (
+ "lqa $sp, _module_stack;"
+ );
+
+ /* put workload into finished state */
+ mars_module_workload_finish();
+}
+
+static void task_exit(void)
+{
+ context_finish();
+}
+
+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_workload_is_initialized(workload_id))
+ 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_workload_is_initialized(workload_id))
+ return MARS_ERROR_STATE;
+
+ /* if workload not finished return busy */
+ if (!mars_module_workload_is_finished(workload_id))
+ 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_workload_is_signal_set(mars_module_get_workload_id()))
+ 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 should never reach here */
+}
--- /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