[Cbe-oss-dev] [PATCH 04/10 v3]MARS/core: Workload module split add module api
Yuji Mano
yuji.mano at am.sony.com
Wed Nov 26 09:47:44 EST 2008
This adds the public module API provided by MARS core library.
The module API will provide the necessary functions to implement a custom
workload module.
Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>
---
v2:
- remove api that returns the workload bits as that is now handled internally in the kernel
- add additional api to allow modules to manipulate the workload state and signal bits
v3:
- replace api that returns the now internally kept workload states and signal values
- provide mars_module_workload_wait/yield/finish API to replace mars_module_exit(state)
core/include/mpu/mars/module.h | 87 +++++++
core/src/mpu/lib/module.c | 466 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 553 insertions(+)
--- /dev/null
+++ b/core/include/mpu/mars/module.h
@@ -0,0 +1,87 @@
+/*
+ * 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_MODULE_H
+#define MARS_MODULE_H
+
+/**
+ * \file
+ * \ingroup group_mars_task
+ * \brief [MPU] MARS Module API
+ */
+
+#include <stdint.h>
+
+#include <mars/workload_types.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void mars_module_main(void);
+
+uint64_t mars_module_get_mars_context_ea(void);
+uint32_t mars_module_get_kernel_id(void);
+uint16_t mars_module_get_workload_id(void);
+struct mars_workload_context *mars_module_get_workload(void);
+struct mars_workload_context *mars_module_get_workload_by_id(uint16_t id);
+
+int mars_module_workload_is_initialized(uint16_t id);
+int mars_module_workload_is_ready(uint16_t id);
+int mars_module_workload_is_waiting(uint16_t id);
+int mars_module_workload_is_running(uint16_t id);
+int mars_module_workload_is_finished(uint16_t id);
+int mars_module_workload_is_signal_set(uint16_t id);
+
+int mars_module_workload_wait_set(uint16_t id);
+int mars_module_workload_wait_reset(void);
+int mars_module_workload_signal_set(uint16_t id);
+int mars_module_workload_signal_reset(void);
+int mars_module_workload_schedule_begin(uint16_t id, uint8_t priority,
+ struct mars_workload_context **workload);
+int mars_module_workload_schedule_end(uint16_t id);
+int mars_module_workload_schedule_cancel(uint16_t id);
+
+void mars_module_workload_wait(void);
+void mars_module_workload_yield(void);
+void mars_module_workload_finish(void);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
--- /dev/null
+++ b/core/src/mpu/lib/module.c
@@ -0,0 +1,466 @@
+/*
+ * 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 <stddef.h>
+
+#include "mars/dma.h"
+#include "mars/error.h"
+#include "mars/module.h"
+#include "mars/mutex.h"
+
+#include "kernel_internal_types.h"
+#include "workload_internal_types.h"
+
+static struct mars_kernel_syscalls *kernel_syscalls;
+static struct mars_workload_queue_header *queue_header;
+static struct mars_workload_queue_block *queue_block;
+static struct mars_workload_context schedule_workload;
+static uint16_t schedule_workload_id;
+
+void mars_module_entry(struct mars_kernel_syscalls *syscalls)
+{
+ kernel_syscalls = syscalls;
+
+ queue_header = (*kernel_syscalls->get_workload_queue_header)();
+ queue_block = (*kernel_syscalls->get_workload_queue_block)();
+
+ asm volatile (
+ /* switch to module stack */
+ "ila $sp, __stack;"
+
+ /* set module link register to NULL */
+ "il $lr, 0;"
+
+ /* initialize back chain to NULL */
+ "stqd $lr, 0($sp);"
+
+ /* initialize module stack frame */
+ "stqd $sp, -32($sp);"
+ "ai $sp, $sp, -32;"
+
+ /* save link register in link register save area */
+ "stqd $lr, 16($sp);"
+
+ /* call _init function */
+ "brsl $lr, _init;"
+ );
+
+ mars_module_main();
+
+ (*kernel_syscalls->module_exit)(MARS_WORKLOAD_STATE_FINISHED);
+}
+
+uint64_t mars_module_get_mars_context_ea(void)
+{
+ return (*kernel_syscalls->get_mars_context_ea)();
+}
+
+uint32_t mars_module_get_kernel_id(void)
+{
+ return (*kernel_syscalls->get_kernel_id)();
+}
+
+uint16_t mars_module_get_workload_id(void)
+{
+ return (*kernel_syscalls->get_workload_id)();
+}
+
+struct mars_workload_context *mars_module_get_workload(void)
+{
+ return (*kernel_syscalls->get_workload)();
+}
+
+struct mars_workload_context *mars_module_get_workload_by_id(uint16_t id)
+{
+ static struct mars_workload_context workload;
+ uint64_t workload_ea;
+ uint16_t caller_id;
+
+ /* get the id of the caller workload */
+ caller_id = mars_module_get_workload_id();
+
+ /* id is caller workload's id so return current workload */
+ if (id == caller_id)
+ return mars_module_get_workload();
+
+ /* calculate workload ea */
+ workload_ea = queue_header->context_ea +
+ id * sizeof(struct mars_workload_context);
+
+ /* get the workload context from workload queue */
+ mars_dma_get_and_wait((void *)&workload, workload_ea,
+ sizeof(struct mars_workload_context), MARS_DMA_TAG);
+
+ return &workload;
+}
+
+static uint64_t get_workload_bits(uint16_t id)
+{
+ int block;
+ int index;
+ uint64_t block_ea;
+ uint64_t workload_bits;
+
+ /* check function params */
+ if (id >= MARS_WORKLOAD_MAX)
+ return 0;
+
+ /* calculate block/index from id */
+ block = id / MARS_WORKLOAD_PER_BLOCK;
+ index = id % MARS_WORKLOAD_PER_BLOCK;
+
+ /* calculate block ea */
+ block_ea = queue_header->queue_ea +
+ offsetof(struct mars_workload_queue, block) +
+ sizeof(struct mars_workload_queue_block) * block;
+
+ /* lock the queue block */
+ mars_mutex_lock_get(block_ea, (struct mars_mutex *)queue_block);
+
+ workload_bits = queue_block->bits[index];
+
+ /* unlock the queue block */
+ mars_mutex_unlock_put(block_ea, (struct mars_mutex *)queue_block);
+
+ return workload_bits;
+}
+
+int mars_module_workload_is_initialized(uint16_t id)
+{
+ uint64_t bits = get_workload_bits(id);
+
+ return (MARS_BITS_GET(&bits, STATE) != MARS_WORKLOAD_STATE_NONE);
+}
+
+int mars_module_workload_is_ready(uint16_t id)
+{
+ uint64_t bits = get_workload_bits(id);
+
+ return (MARS_BITS_GET(&bits, STATE) == MARS_WORKLOAD_STATE_READY);
+}
+
+int mars_module_workload_is_waiting(uint16_t id)
+{
+ uint64_t bits = get_workload_bits(id);
+
+ return (MARS_BITS_GET(&bits, STATE) == MARS_WORKLOAD_STATE_WAITING);
+}
+
+int mars_module_workload_is_running(uint16_t id)
+{
+ uint64_t bits = get_workload_bits(id);
+
+ return (MARS_BITS_GET(&bits, STATE) == MARS_WORKLOAD_STATE_RUNNING);
+}
+
+int mars_module_workload_is_finished(uint16_t id)
+{
+ uint64_t bits = get_workload_bits(id);
+
+ return (MARS_BITS_GET(&bits, STATE) == MARS_WORKLOAD_STATE_FINISHED);
+}
+
+int mars_module_workload_is_signal_set(uint16_t id)
+{
+ uint64_t bits = get_workload_bits(id);
+
+ return (MARS_BITS_GET(&bits, SIGNAL) == MARS_WORKLOAD_SIGNAL_ON);
+}
+
+static void workload_wait_set(uint16_t id)
+{
+ int block;
+ int index;
+ uint64_t block_ea;
+
+ /* calculate block/index from id */
+ block = mars_module_get_workload_id() / MARS_WORKLOAD_PER_BLOCK;
+ index = mars_module_get_workload_id() % MARS_WORKLOAD_PER_BLOCK;
+
+ /* calculate block ea */
+ block_ea = queue_header->queue_ea +
+ offsetof(struct mars_workload_queue, block) +
+ sizeof(struct mars_workload_queue_block) * block;
+
+ /* lock the queue block */
+ mars_mutex_lock_get(block_ea, (struct mars_mutex *)queue_block);
+
+ /* set the workload id to wait for */
+ MARS_BITS_SET(&queue_block->bits[index], WAIT_ID, id);
+
+ /* unlock the queue block */
+ mars_mutex_unlock_put(block_ea, (struct mars_mutex *)queue_block);
+}
+
+int mars_module_workload_wait_set(uint16_t id)
+{
+ /* check function params */
+ if (id >= MARS_WORKLOAD_MAX)
+ return MARS_ERROR_PARAMS;
+ if (id == mars_module_get_workload_id())
+ return MARS_ERROR_PARAMS;
+
+ workload_wait_set(id);
+
+ return MARS_SUCCESS;
+}
+
+int mars_module_workload_wait_reset(void)
+{
+ workload_wait_set(MARS_WORKLOAD_ID_NONE);
+
+ return MARS_SUCCESS;
+}
+
+static void workload_signal_set(uint16_t id, uint8_t signal)
+{
+ int block;
+ int index;
+ uint64_t block_ea;
+
+ /* calculate block/index from id */
+ block = id / MARS_WORKLOAD_PER_BLOCK;
+ index = id % MARS_WORKLOAD_PER_BLOCK;
+
+ /* calculate block ea */
+ block_ea = queue_header->queue_ea +
+ offsetof(struct mars_workload_queue, block) +
+ sizeof(struct mars_workload_queue_block) * block;
+
+ /* lock the queue block */
+ mars_mutex_lock_get(block_ea, (struct mars_mutex *)queue_block);
+
+ /* set the workload signal */
+ MARS_BITS_SET(&queue_block->bits[index], SIGNAL, signal);
+
+ /* unlock the queue block */
+ mars_mutex_unlock_put(block_ea, (struct mars_mutex *)queue_block);
+}
+
+int mars_module_workload_signal_set(uint16_t id)
+{
+ uint16_t caller_id;
+
+ /* get the id of the caller workload */
+ caller_id = mars_module_get_workload_id();
+
+ /* check function params */
+ if (id >= MARS_WORKLOAD_MAX)
+ return MARS_ERROR_PARAMS;
+ if (id == caller_id)
+ return MARS_ERROR_PARAMS;
+
+ workload_signal_set(id, MARS_WORKLOAD_SIGNAL_ON);
+
+ return MARS_SUCCESS;
+}
+
+int mars_module_workload_signal_reset(void)
+{
+ workload_signal_set(mars_module_get_workload_id(),
+ MARS_WORKLOAD_SIGNAL_OFF);
+
+ return MARS_SUCCESS;
+}
+
+int mars_module_workload_schedule_begin(uint16_t id, uint8_t priority,
+ struct mars_workload_context **workload)
+{
+ int block;
+ int index;
+ uint64_t block_ea;
+ uint64_t schedule_workload_ea;
+ uint16_t caller_id;
+
+ /* get the id of the caller workload */
+ caller_id = mars_module_get_workload_id();
+
+ /* check function params */
+ if (id >= MARS_WORKLOAD_MAX)
+ return MARS_ERROR_PARAMS;
+ if (id == caller_id)
+ return MARS_ERROR_PARAMS;
+
+ /* calculate block/index from id */
+ block = id / MARS_WORKLOAD_PER_BLOCK;
+ index = id % MARS_WORKLOAD_PER_BLOCK;
+
+ /* calculate block ea */
+ block_ea = queue_header->queue_ea +
+ offsetof(struct mars_workload_queue, block) +
+ sizeof(struct mars_workload_queue_block) * block;
+
+ mars_mutex_lock_get(block_ea, (struct mars_mutex *)queue_block);
+
+ /* check for valid state */
+ if (MARS_BITS_GET(&queue_block->bits[index], STATE) !=
+ MARS_WORKLOAD_STATE_FINISHED) {
+ mars_mutex_unlock_put(block_ea,
+ (struct mars_mutex *)queue_block);
+ return MARS_ERROR_STATE;
+ }
+
+ /* get information of workload to schedule */
+ schedule_workload_id = id;
+ schedule_workload_ea = queue_header->context_ea +
+ id * sizeof(struct mars_workload_context);
+
+ /* get the workload context from workload queue */
+ mars_dma_get_and_wait((void *)&schedule_workload, schedule_workload_ea,
+ sizeof(struct mars_workload_context), MARS_DMA_TAG);
+
+ /* initialize queue block bits */
+ MARS_BITS_SET(&queue_block->bits[index], STATE,
+ MARS_WORKLOAD_STATE_SCHEDULING);
+ MARS_BITS_SET(&queue_block->bits[index], PRIORITY,
+ priority);
+ MARS_BITS_SET(&queue_block->bits[index], COUNTER,
+ MARS_WORKLOAD_COUNTER_MIN);
+ MARS_BITS_SET(&queue_block->bits[index], SIGNAL,
+ MARS_WORKLOAD_SIGNAL_OFF);
+ MARS_BITS_SET(&queue_block->bits[index], WAIT_ID,
+ MARS_WORKLOAD_ID_NONE);
+
+ mars_mutex_unlock_put(block_ea, (struct mars_mutex *)queue_block);
+
+ /* if requested set workload context pointer to return */
+ if (workload)
+ *workload = &schedule_workload;
+
+ return MARS_SUCCESS;
+}
+
+int mars_module_workload_schedule_end(uint16_t id)
+{
+ int block;
+ int index;
+ uint64_t block_ea;
+ uint64_t schedule_workload_ea;
+
+ /* check function params */
+ if (id != schedule_workload_id)
+ return MARS_ERROR_PARAMS;
+
+ /* calculate block/index from id */
+ block = id / MARS_WORKLOAD_PER_BLOCK;
+ index = id % MARS_WORKLOAD_PER_BLOCK;
+
+ /* calculate block ea */
+ block_ea = queue_header->queue_ea +
+ offsetof(struct mars_workload_queue, block) +
+ sizeof(struct mars_workload_queue_block) * block;
+
+ mars_mutex_lock_get(block_ea, (struct mars_mutex *)queue_block);
+
+ /* check for valid state */
+ if (MARS_BITS_GET(&queue_block->bits[index], STATE) !=
+ MARS_WORKLOAD_STATE_SCHEDULING) {
+ mars_mutex_unlock_put(block_ea,
+ (struct mars_mutex *)queue_block);
+ return MARS_ERROR_STATE;
+ }
+
+ /* get information of workload to schedule */
+ schedule_workload_id = MARS_WORKLOAD_ID_NONE;
+ schedule_workload_ea = queue_header->context_ea +
+ id * sizeof(struct mars_workload_context);
+
+ /* put the workload context into workload queue */
+ mars_dma_put_and_wait((void *)&schedule_workload, schedule_workload_ea,
+ sizeof(struct mars_workload_context), MARS_DMA_TAG);
+
+ /* set state to ready */
+ MARS_BITS_SET(&queue_block->bits[index], STATE,
+ MARS_WORKLOAD_STATE_READY);
+
+ mars_mutex_unlock_put(block_ea, (struct mars_mutex *)queue_block);
+
+ return MARS_SUCCESS;
+}
+
+int mars_module_workload_schedule_cancel(uint16_t id)
+{
+ int block;
+ int index;
+ uint64_t block_ea;
+
+ /* check function params */
+ if (id != schedule_workload_id)
+ return MARS_ERROR_PARAMS;
+
+ /* calculate block/index from id */
+ block = id / MARS_WORKLOAD_PER_BLOCK;
+ index = id % MARS_WORKLOAD_PER_BLOCK;
+
+ /* calculate block ea */
+ block_ea = queue_header->queue_ea +
+ offsetof(struct mars_workload_queue, block) +
+ sizeof(struct mars_workload_queue_block) * block;
+
+ mars_mutex_lock_get(block_ea, (struct mars_mutex *)queue_block);
+
+ /* check for valid state */
+ if (MARS_BITS_GET(&queue_block->bits[index], STATE) !=
+ MARS_WORKLOAD_STATE_SCHEDULING) {
+ mars_mutex_unlock_put(block_ea,
+ (struct mars_mutex *)queue_block);
+ return MARS_ERROR_STATE;
+ }
+
+ /* set state back to finished */
+ MARS_BITS_SET(&queue_block->bits[index], STATE,
+ MARS_WORKLOAD_STATE_FINISHED);
+
+ mars_mutex_unlock_put(block_ea, (struct mars_mutex *)queue_block);
+
+ return MARS_SUCCESS;
+}
+
+void mars_module_workload_wait(void)
+{
+ (*kernel_syscalls->module_exit)(MARS_WORKLOAD_STATE_WAITING);
+}
+
+void mars_module_workload_yield(void)
+{
+ (*kernel_syscalls->module_exit)(MARS_WORKLOAD_STATE_READY);
+}
+
+void mars_module_workload_finish(void)
+{
+ (*kernel_syscalls->module_exit)(MARS_WORKLOAD_STATE_FINISHED);
+}
More information about the cbe-oss-dev
mailing list