[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