[Cbe-oss-dev] [PATCH 06/10]MARS/core: Workload module split kernel cleanup
Yuji Mano
yuji.mano at am.sony.com
Fri Nov 21 11:06:46 EST 2008
This cleans up the MARS core kernel implementation.
Most of the implementation will be moved into the task module/lib.
The kernel will only be responsible for workload scheduling and loading/running
the appropriate workload module.
Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>
---
core/src/common/kernel_internal_types.h | 18 +
core/src/mpu/kernel/Makefile.am | 12
core/src/mpu/kernel/kernel.c | 326 +++++++++++++++++++++++++-
core/src/mpu/kernel/kernel.h | 126 ----------
core/src/mpu/kernel/kernel_registers.c | 152 ------------
core/src/mpu/kernel/kernel_scheduler.c | 253 --------------------
core/src/mpu/kernel/kernel_syscalls.c | 190 ---------------
core/src/mpu/kernel/kernel_task.c | 137 -----------
core/src/mpu/kernel/kernel_workload.c | 396 --------------------------------
9 files changed, 342 insertions(+), 1268 deletions(-)
--- a/core/src/common/kernel_internal_types.h
+++ b/core/src/common/kernel_internal_types.h
@@ -40,10 +40,25 @@
#include <stdint.h>
+#define MARS_KERNEL_STATUS_BUSY 0x0
+#define MARS_KERNEL_STATUS_IDLE 0x1
+#define MARS_KERNEL_STATUS_EXIT 0x2
#define MARS_KERNEL_TICKS_FLAG_SYNC_BEGIN 0x1
#define MARS_KERNEL_TICKS_FLAG_SYNC_END 0x2
#define MARS_KERNEL_PARAMS_ALIGN 128
+/* mars kernel syscalls */
+struct mars_kernel_syscalls {
+ void (*module_exit)(uint8_t state);
+ uint64_t (*get_mars_context_ea)(void);
+ uint32_t (*get_kernel_id)(void);
+ uint8_t (*get_workload_type)(void);
+ uint16_t (*get_workload_id)(void);
+ struct mars_workload_context * (*get_workload)(void);
+ struct mars_workload_queue_header *(*get_workload_queue_header)(void);
+ struct mars_workload_queue_block * (*get_workload_queue_block)(void);
+};
+
/* mars kernel ticks */
struct mars_kernel_ticks {
uint32_t flag;
@@ -58,4 +73,7 @@ struct mars_kernel_params {
struct mars_kernel_ticks kernel_ticks;
} __attribute__((aligned(MARS_KERNEL_PARAMS_ALIGN)));
+/* mars module entry */
+void mars_module_entry(struct mars_kernel_syscalls *syscalls);
+
#endif
--- a/core/src/mpu/kernel/Makefile.am
+++ b/core/src/mpu/kernel/Makefile.am
@@ -89,16 +89,10 @@ AM_LDFLAGS = \
noinst_PROGRAMS = mars_kernel
-mars_kernel_LDADD = $(builddir)/../lib/libmars.a
-
mars_kernel_SOURCES = \
$(srcdir)/../../../src/common/*.h \
- kernel.c \
- kernel.h \
- kernel_registers.c \
- kernel_scheduler.c \
- kernel_syscalls.c \
- kernel_task.c \
- kernel_workload.c
+ kernel.c
+
+mars_kernel_LDADD = $(builddir)/../lib/libmars_core.la
CLEANFILES = *.map
--- a/core/src/mpu/kernel/kernel.c
+++ b/core/src/mpu/kernel/kernel.c
@@ -35,11 +35,326 @@
* LIBRARY OR THE USE OR OTHER DEALINGS IN THE LIBRARY.
*/
-#include "kernel.h"
+#include <stddef.h>
+#include <stdint.h>
+#include <string.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"
+
+#define MARS_WORKLOAD_RESERVED_NONE 0
+#define MARS_WORKLOAD_RESERVED 1
+
+/* kernel */
+void *_kernel_stack;
+static struct mars_kernel_params kernel_params;
+
+/* workload queue */
+static struct mars_workload_queue_header queue_header;
+static struct mars_workload_queue_block queue_block;
+
+/* workload */
+static struct mars_workload_context workload;
+static uint8_t workload_type;
+static uint8_t workload_state;
+static uint16_t workload_id;
+static uint64_t workload_ea;
+
+/* module entry */
+typedef void (*module_entry)(
+ const struct mars_kernel_syscalls *kernel_syscalls);
-struct mars_kernel_params kernel_params;
+static void module_exit(uint8_t state)
+{
+ workload_state = state;
+
+ /* restore kernel stack pointer and goto to exit label */
+ asm volatile (
+ "lqa $sp, _kernel_stack;"
+ "br _module_exit;"
+ );
+}
+
+static uint64_t get_mars_context_ea(void)
+{
+ return kernel_params.mars_context_ea;
+}
+
+static uint32_t get_kernel_id(void)
+{
+ return kernel_params.kernel_id;
+}
+
+static uint8_t get_workload_type(void)
+{
+ return workload_type;
+}
+
+static uint16_t get_workload_id(void)
+{
+ return workload_id;
+}
+
+static struct mars_workload_context *get_workload(void)
+{
+ return &workload;
+}
+
+static struct mars_workload_queue_header *get_workload_queue_header(void)
+{
+ return &queue_header;
+}
+
+static struct mars_workload_queue_block *get_workload_queue_block(void)
+{
+ return &queue_block;
+}
+
+static struct mars_kernel_syscalls kernel_syscalls =
+{
+ module_exit,
+ get_mars_context_ea,
+ get_kernel_id,
+ get_workload_type,
+ get_workload_id,
+ get_workload,
+ get_workload_queue_header,
+ get_workload_queue_block
+};
+
+static void get_block(int block, struct mars_workload_queue_block *dst)
+{
+ mars_dma_get_and_wait(dst,
+ queue_header.queue_ea +
+ offsetof(struct mars_workload_queue, block) +
+ sizeof(struct mars_workload_queue_block) * block,
+ sizeof(struct mars_workload_queue_block),
+ MARS_DMA_TAG);
+}
+
+static int search_block(int block)
+{
+ int i;
+ int index = -1;
+ uint16_t max_counter = 0;
+ uint16_t max_priority = 0;
+
+ /* search through workload queue for next workload to run
+ * while incrementing wait counter for all waiting workloads
+ * and pick the workload that has been waiting the longest
+ */
+ for (i = 0; i < MARS_WORKLOAD_PER_BLOCK; i++) {
+ uint64_t *bits = &queue_block.bits[i];
+ uint8_t signal = MARS_BITS_GET(bits, SIGNAL);
+ uint8_t priority = MARS_BITS_GET(bits, PRIORITY);
+ uint16_t wait_id = MARS_BITS_GET(bits, WAIT_ID);
+ uint16_t counter = MARS_BITS_GET(bits, COUNTER);
+
+ switch (MARS_BITS_GET(bits, STATE)) {
+ case MARS_WORKLOAD_STATE_READY:
+ /* compare priority and counter with previous ones */
+ if (index < 0 || priority > max_priority ||
+ (priority == max_priority && counter > max_counter)) {
+ index = i;
+ max_counter = counter;
+ max_priority = priority;
+ }
+ /* increment wait counter without overflowing */
+ if (counter < MARS_WORKLOAD_COUNTER_MAX)
+ MARS_BITS_SET(bits, COUNTER, counter + 1);
+ break;
+ case MARS_WORKLOAD_STATE_WAITING:
+ /* waiting for workload to finish so check status */
+ if (wait_id != MARS_WORKLOAD_ID_NONE) {
+ struct mars_workload_queue_block wait_block;
+ struct mars_workload_queue_block *p_wait_block;
+ uint8_t wait_state;
+
+ int bl = wait_id / MARS_WORKLOAD_PER_BLOCK;
+ int id = wait_id % MARS_WORKLOAD_PER_BLOCK;
+
+ /* check if workload id is in the same block */
+ if (block != bl) {
+ /* fetch the necessary block */
+ get_block(bl, &wait_block);
+ /* set pointer to check fetched block */
+ p_wait_block = &wait_block;
+ } else {
+ /* set pointer to check current block */
+ p_wait_block = &queue_block;
+ }
+
+ wait_state =
+ MARS_BITS_GET(&p_wait_block->bits[id],
+ STATE);
+
+ /* check if workload is finished and reset */
+ if (wait_state ==
+ MARS_WORKLOAD_STATE_FINISHED) {
+ MARS_BITS_SET(bits, WAIT_ID,
+ MARS_WORKLOAD_ID_NONE);
+ MARS_BITS_SET(bits, STATE,
+ MARS_WORKLOAD_STATE_READY);
+ }
+ /* waiting for signal so check signal bit and reset */
+ } else if (signal == MARS_WORKLOAD_SIGNAL_ON) {
+ MARS_BITS_SET(bits, SIGNAL,
+ MARS_WORKLOAD_SIGNAL_OFF);
+ MARS_BITS_SET(bits, STATE,
+ MARS_WORKLOAD_STATE_READY);
+ i--;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* returns -1 if no runnable workload found */
+ return index;
+}
+
+static int reserve_block(int block)
+{
+ int index;
+ uint64_t block_ea;
+
+ /* 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);
+
+ /* set the workload index */
+ index = search_block(block);
+ if (index >= 0) {
+ /* update the current state of the workload */
+ MARS_BITS_SET(&queue_block.bits[index], STATE,
+ MARS_WORKLOAD_STATE_RUNNING);
+
+ /* reset the counter for reserved workload */
+ MARS_BITS_SET(&queue_block.bits[index], COUNTER,
+ MARS_WORKLOAD_COUNTER_MIN);
+ }
+
+ mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
+
+ return index;
+}
+
+static void release_block(int block, int index)
+{
+ uint64_t 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);
+
+ /* update current workload state in workload queue block */
+ MARS_BITS_SET(&queue_block.bits[index], STATE, workload_state);
+
+ mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
+}
+
+static int __attribute__((noinline)) reserve_workload(void)
+{
+ int block;
+ int index = -1;
+
+ /* search workload queue blocks until runnable workload reserved */
+ for (block = 0; block < MARS_WORKLOAD_NUM_BLOCKS; block++) {
+ index = reserve_block(block);
+ if (index >= 0)
+ break;
+ }
+
+ /* no runnable workload found */
+ if (index < 0)
+ return MARS_WORKLOAD_RESERVED_NONE;
+
+ /* set global workload info based on workload block and index */
+ workload_type = MARS_BITS_GET(&queue_block.bits[index], TYPE);
+ workload_id = MARS_WORKLOAD_PER_BLOCK * block + index;
+ workload_ea = queue_header.context_ea +
+ workload_id * sizeof(struct mars_workload_context);
+
+ /* get the workload context code from workload queue */
+ mars_dma_get_and_wait(&workload, workload_ea,
+ sizeof(struct mars_workload_context), MARS_DMA_TAG);
+
+ return MARS_WORKLOAD_RESERVED;
+}
+
+static void __attribute__((noinline)) release_workload(void)
+{
+ int block = workload_id / MARS_WORKLOAD_PER_BLOCK;
+ int index = workload_id % MARS_WORKLOAD_PER_BLOCK;
+
+ /* put the workload context into workload queue */
+ mars_dma_put_and_wait(&workload, workload_ea,
+ sizeof(struct mars_workload_context), MARS_DMA_TAG);
+
+ /* release block reservation */
+ release_block(block, index);
+}
+
+static int __attribute__((noinline)) scheduler(void)
+{
+ int status;
+
+ /* get the workload queue header */
+ mars_dma_get_and_wait(&queue_header,
+ kernel_params.workload_queue_ea +
+ offsetof(struct mars_workload_queue, header),
+ sizeof(struct mars_workload_queue_header),
+ MARS_DMA_TAG);
+
+ /* return exit status if exit flag is set from host */
+ if (queue_header.flag == MARS_WORKLOAD_QUEUE_FLAG_EXIT)
+ return MARS_KERNEL_STATUS_EXIT;
+
+ /* reserve next workload to run or return idle status if none found */
+ status = reserve_workload();
+
+ /* return idle status if no workload was reserved */
+ if (status == MARS_WORKLOAD_RESERVED_NONE)
+ return MARS_KERNEL_STATUS_IDLE;
+
+ /* load the exec code into mpu storage from host storage */
+ mars_dma_large_get_and_wait((void *)MARS_WORKLOAD_MODULE_ELF_VADDR,
+ workload.module.exec_ea, workload.module.exec_size,
+ MARS_DMA_TAG);
+
+ /* 0 the bss section */
+ memset((void *)MARS_WORKLOAD_MODULE_ELF_VADDR +
+ workload.module.exec_size, 0, workload.module.bss_size);
+
+ /* save kernel stack pointer */
+ asm volatile (
+ "stqa $sp, _kernel_stack;"
+ );
+
+ /* call module entry function */
+ ((module_entry)workload.module.entry)(&kernel_syscalls);
+
+ /* label so module can jump back here at exit */
+ asm volatile (
+ "_module_exit:"
+ );
+
+ /* release reservation of current workload */
+ release_workload();
+
+ return MARS_KERNEL_STATUS_BUSY;
+}
-static void kernel_get_params(uint64_t kernel_params_ea)
+static void get_params(uint64_t kernel_params_ea)
{
int mask;
@@ -91,13 +406,14 @@ static void kernel_get_params(uint64_t k
spu_write_event_ack(MFC_LLR_LOST_EVENT);
}
-int main(unsigned long long mpu_context_id, unsigned long long kernel_params_ea)
+int main(unsigned long long mpu_context_id,
+ unsigned long long kernel_params_ea)
{
(void)mpu_context_id;
int exit_flag = 0;
- kernel_get_params(kernel_params_ea);
+ get_params(kernel_params_ea);
while (!exit_flag) {
int status = scheduler();
--- a/core/src/mpu/kernel/kernel.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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_KERNEL_H
-#define MARS_KERNEL_H
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <stddef.h>
-
-#include "mars/mutex.h"
-#include "mars/error.h"
-#include "mars/task_types.h"
-
-#include "kernel_internal_types.h"
-#include "mutex_internal_types.h"
-#include "workload_internal_types.h"
-#include "task_internal_types.h"
-#include "syscalls.h"
-#include "dma.h"
-
-#define MARS_KERNEL_STATUS_BUSY 0x0
-#define MARS_KERNEL_STATUS_IDLE 0x1
-#define MARS_KERNEL_STATUS_EXIT 0x2
-
-typedef void (*mars_entry)(void *workload_args, void *kernel_syscalls);
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-void mars_reentry(void);
-
-/* kernel scheduler function */
-int scheduler(void);
-
-/* kernel syscall functions */
-uint32_t syscall_get_ticks(void);
-uint64_t syscall_get_mars_context_ea(void);
-uint32_t syscall_get_kernel_id(void);
-uint16_t syscall_get_workload_id(void);
-uint64_t syscall_get_workload_ea(void);
-struct mars_workload_context *syscall_get_workload(void);
-struct mars_workload_context *syscall_get_workload_by_id(uint16_t workload_id);
-
-void syscall_init(void);
-void syscall_exit(void);
-void syscall_yield(void);
-void syscall_resume(void);
-int syscall_schedule(uint16_t workload_id, void *args, uint8_t priority);
-int syscall_wait(uint16_t workload_id);
-int syscall_try_wait(uint16_t workload_id);
-int syscall_signal_send(uint16_t workload_id);
-void syscall_signal_wait(void);
-int syscall_signal_try_wait(void);
-
-/* register saving / restoring functions */
-void registers_save(void);
-void registers_restore(void);
-
-/* workload specific functions */
-uint16_t workload_get_id(void);
-uint64_t workload_get_ea(void);
-struct mars_workload_context *workload_get(void);
-struct mars_workload_context *workload_get_by_id(uint16_t workload_id);
-
-void workload_exec(void);
-void workload_exit(void);
-void workload_yield(void);
-void workload_resume(void);
-int workload_schedule(uint16_t workload_id, void *args, uint8_t priority);
-int workload_wait(uint16_t workload_id);
-int workload_try_wait(uint16_t workload_id);
-int workload_signal_send(uint16_t workload_id);
-void workload_signal_wait(void);
-int workload_signal_try_wait(void);
-
-/* task specific functions */
-void task_exec(struct mars_task_context *task);
-void task_exit(struct mars_task_context *task);
-void task_yield(struct mars_task_context *task);
-void task_resume(struct mars_task_context *task);
-void task_schedule(struct mars_task_context *task, struct mars_task_args *args);
-
-extern struct mars_kernel_params kernel_params;
-extern struct mars_kernel_syscalls kernel_syscalls;
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif
--- a/core/src/mpu/kernel/kernel_registers.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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 "kernel.h"
-
-void registers_save(void)
-{
- /* push non-volatile registers on to the workload stack */
- asm volatile (
- "lqa $75, workload_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);"
- );
-}
-
-void registers_restore(void)
-{
- /* pop non-volatile registers from saved workload stack */
- asm volatile (
- "lqa $75, workload_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);"
- );
-}
--- a/core/src/mpu/kernel/kernel_scheduler.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * 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 "kernel.h"
-
-#define MARS_WORKLOAD_RESERVED_NONE 0
-#define MARS_WORKLOAD_RESERVED 1
-
-struct mars_workload_queue_header queue_header;
-struct mars_workload_queue_block queue_block;
-struct mars_workload_context workload;
-uint8_t workload_type;
-uint8_t workload_state;
-uint16_t workload_index;
-uint64_t workload_ea;
-
-static inline void get_block(int block, struct mars_workload_queue_block *dst)
-{
- mars_dma_get_and_wait(dst,
- queue_header.queue_ea +
- offsetof(struct mars_workload_queue, block) +
- sizeof(struct mars_workload_queue_block) * block,
- sizeof(struct mars_workload_queue_block),
- MARS_DMA_TAG);
-}
-
-static int search_block(int block)
-{
- int i;
- int index = -1;
- uint16_t max_counter = 0;
- uint16_t max_priority = 0;
-
- /* search through workload queue for next workload to run
- * while incrementing wait counter for all waiting workloads
- * and pick the workload that has been waiting the longest
- */
- for (i = 0; i < MARS_WORKLOAD_PER_BLOCK; i++) {
- uint64_t *bits = &queue_block.bits[i];
- uint8_t signal = MARS_BITS_GET(bits, SIGNAL);
- uint8_t priority = MARS_BITS_GET(bits, PRIORITY);
- uint16_t wait_id = MARS_BITS_GET(bits, WAIT_ID);
- uint16_t counter = MARS_BITS_GET(bits, COUNTER);
-
- switch (MARS_BITS_GET(bits, STATE)) {
- case MARS_WORKLOAD_STATE_READY:
- /* compare priority and counter with previous ones */
- if (index < 0 || priority > max_priority ||
- (priority == max_priority && counter > max_counter)) {
- index = i;
- max_counter = counter;
- max_priority = priority;
- }
- /* increment wait counter without overflowing */
- if (counter < MARS_WORKLOAD_COUNTER_MAX)
- MARS_BITS_SET(bits, COUNTER, counter + 1);
- break;
- case MARS_WORKLOAD_STATE_WAITING:
- /* waiting for workload to finish so check status */
- if (wait_id != MARS_WORKLOAD_ID_NONE) {
- struct mars_workload_queue_block wait_block;
- struct mars_workload_queue_block *p_wait_block;
- uint8_t wait_state;
-
- int bl = wait_id / MARS_WORKLOAD_PER_BLOCK;
- int id = wait_id % MARS_WORKLOAD_PER_BLOCK;
-
- /* check if workload id is in the same block */
- if (block != bl) {
- /* fetch the necessary block */
- get_block(bl, &wait_block);
- /* set pointer to check fetched block */
- p_wait_block = &wait_block;
- } else {
- /* set pointer to check current block */
- p_wait_block = &queue_block;
- }
-
- wait_state =
- MARS_BITS_GET(&p_wait_block->bits[id],
- STATE);
-
- /* check if workload is finished and reset */
- if (wait_state ==
- MARS_WORKLOAD_STATE_FINISHED) {
- MARS_BITS_SET(bits, WAIT_ID,
- MARS_WORKLOAD_ID_NONE);
- MARS_BITS_SET(bits, STATE,
- MARS_WORKLOAD_STATE_READY);
- }
- /* waiting for signal so check signal bit and reset */
- } else if (signal == MARS_WORKLOAD_SIGNAL_ON) {
- MARS_BITS_SET(bits, SIGNAL,
- MARS_WORKLOAD_SIGNAL_OFF);
- MARS_BITS_SET(bits, STATE,
- MARS_WORKLOAD_STATE_READY);
- i--;
- }
- break;
- default:
- break;
- }
- }
-
- /* returns -1 if no runnable workload found */
- return index;
-}
-
-static int reserve_block(int block)
-{
- int index;
- uint64_t 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);
-
- /* set the workload index */
- index = search_block(block);
- if (index >= 0) {
- /* update the current state of the workload */
- MARS_BITS_SET(&queue_block.bits[index], STATE,
- MARS_WORKLOAD_STATE_RUNNING);
-
- /* reset the counter for reserved workload */
- MARS_BITS_SET(&queue_block.bits[index], COUNTER,
- MARS_WORKLOAD_COUNTER_MIN);
- }
-
- mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
-
- return index;
-}
-
-static void release_block(int block, int index)
-{
- uint64_t 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);
-
- /* update current workload state in workload queue block */
- MARS_BITS_SET(&queue_block.bits[index], STATE, workload_state);
-
- mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
-}
-
-static int __attribute__((noinline)) reserve_workload(void)
-{
- int block;
- int index = -1;
-
- /* search workload queue blocks until runnable workload reserved */
- for (block = 0; block < MARS_WORKLOAD_NUM_BLOCKS; block++) {
- index = reserve_block(block);
- if (index >= 0)
- break;
- }
-
- /* no runnable workload found */
- if (index < 0)
- return MARS_WORKLOAD_RESERVED_NONE;
-
- /* set global workload info based on workload block and index */
- workload_index = MARS_WORKLOAD_PER_BLOCK * block + index;
- workload_type = MARS_BITS_GET(&queue_block.bits[index], TYPE);
- workload_ea = queue_header.context_ea +
- workload_index * sizeof(struct mars_workload_context);
-
- /* dma the workload context code into LS from main memory */
- mars_dma_get_and_wait(&workload, workload_ea,
- sizeof(struct mars_workload_context), MARS_DMA_TAG);
-
- return MARS_WORKLOAD_RESERVED;
-}
-
-static void __attribute__((noinline)) release_workload(void)
-{
- int block = workload_index / MARS_WORKLOAD_PER_BLOCK;
- int index = workload_index % MARS_WORKLOAD_PER_BLOCK;
-
- mars_dma_put_and_wait(&workload, workload_ea,
- sizeof(struct mars_workload_context), MARS_DMA_TAG);
-
- /* release block reservation */
- release_block(block, index);
-}
-
-int scheduler(void)
-{
- int status;
-
- /* dma in queue header */
- mars_dma_get_and_wait(&queue_header,
- kernel_params.workload_queue_ea +
- offsetof(struct mars_workload_queue, header),
- sizeof(struct mars_workload_queue_header),
- MARS_DMA_TAG);
-
- /* return exit status if exit flag is set from host */
- if (queue_header.flag == MARS_WORKLOAD_QUEUE_FLAG_EXIT)
- return MARS_KERNEL_STATUS_EXIT;
-
- /* reserve next workload to run or return idle status if none found */
- status = reserve_workload();
-
- /* return idle status if no workload was reserved */
- if (status == MARS_WORKLOAD_RESERVED_NONE)
- return MARS_KERNEL_STATUS_IDLE;
-
- /* execute the reserved workload */
- workload_exec();
-
- /* release reservation of current workload */
- release_workload();
-
- return MARS_KERNEL_STATUS_BUSY;
-}
--- a/core/src/mpu/kernel/kernel_syscalls.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * 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 "kernel.h"
-
-void *kernel_stack;
-void *workload_stack;
-
-struct mars_kernel_syscalls kernel_syscalls =
-{
- syscall_get_ticks,
- syscall_get_mars_context_ea,
- syscall_get_kernel_id,
- syscall_get_workload_id,
- syscall_get_workload_ea,
- syscall_get_workload,
- syscall_get_workload_by_id,
- syscall_init,
- syscall_exit,
- syscall_yield,
- syscall_schedule,
- syscall_wait,
- syscall_try_wait,
- syscall_signal_send,
- syscall_signal_wait,
- syscall_signal_try_wait
-};
-
-void mars_reentry(void)
-{
- syscall_resume();
-}
-
-uint32_t syscall_get_ticks(void)
-{
- return kernel_params.kernel_ticks.offset - spu_read_decrementer();
-}
-
-uint64_t syscall_get_mars_context_ea(void)
-{
- return kernel_params.mars_context_ea;
-}
-
-uint32_t syscall_get_kernel_id(void)
-{
- return kernel_params.kernel_id;
-}
-
-uint16_t syscall_get_workload_id(void)
-{
- return workload_get_id();
-}
-
-uint64_t syscall_get_workload_ea(void)
-{
- return workload_get_ea();
-}
-
-struct mars_workload_context *syscall_get_workload(void)
-{
- return workload_get();
-}
-
-struct mars_workload_context *syscall_get_workload_by_id(uint16_t workload_id)
-{
- return workload_get_by_id(workload_id);
-}
-
-void syscall_init(void)
-{
- /* save the kernel stack
- **
- ** We need to offset the stack pointer we want to save so that we
- ** return back to the caller of mars_entry and not the caller of
- ** the syscall mars_init and when mars_exit is called and pops the
- ** stack. But we don't want to modify the stack pointer directly
- ** just yet so we can return back to the current caller (mars_entry)
- ** so use a volatile register to do the offset.
- ** NO FUNCTION CALLS OR STACK PUSHES ALLOWED IN HERE.
- */
- asm volatile (
- "ai $75, $sp, 32;"
- "stqa $75, kernel_stack;"
- );
-}
-
-void syscall_exit(void)
-{
- /* restore kernel stack */
- asm volatile (
- "lqa $sp, kernel_stack;"
- );
-
- /* exit current workload */
- workload_exit();
-}
-
-void syscall_yield(void)
-{
- /* save workload stack and restore kernel stack */
- asm volatile (
- "stqa $sp, workload_stack;"
- "lqa $sp, kernel_stack;"
- );
-
- /* yield current workload */
- workload_yield();
-}
-
-void syscall_resume(void)
-{
- /* resume current workload */
- workload_resume();
-
- /* save kernel stack and restore workload stack */
- asm volatile (
- "stqa $sp, kernel_stack;"
- "lqa $sp, workload_stack;"
- );
-}
-
-int syscall_schedule(uint16_t workload_id, void *args, uint8_t priority)
-{
- return workload_schedule(workload_id, args, priority);
-}
-
-int syscall_wait(uint16_t workload_id)
-{
- return workload_wait(workload_id);
-}
-
-int syscall_try_wait(uint16_t workload_id)
-{
- return workload_try_wait(workload_id);
-}
-
-int syscall_signal_send(uint16_t workload_id)
-{
- return workload_signal_send(workload_id);
-}
-
-void syscall_signal_wait(void)
-{
- /* save workload stack and restore kernel stack */
- asm volatile (
- "stqa $sp, workload_stack;"
- "lqa $sp, kernel_stack;"
- );
-
- workload_signal_wait();
-}
-
-int syscall_signal_try_wait(void)
-{
- return workload_signal_try_wait();
-}
--- a/core/src/mpu/kernel/kernel_task.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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 <string.h>
-
-#include "kernel.h"
-
-extern void *workload_stack;
-
-void task_exec(struct mars_task_context *task)
-{
- 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_entry)task->entry)(&task->args, &kernel_syscalls);
- } else {
- mars_reentry();
- }
-}
-
-void task_exit(struct mars_task_context *task)
-{
- (void)task;
-}
-
-void task_yield(struct mars_task_context *task)
-{
- struct mars_task_context_save_unit
- list[MARS_TASK_CONTEXT_SAVE_UNIT_MAX];
- int i, offset = 0;
-
- /* save workload stack pointer */
- task->stack = (uint32_t)workload_stack;
-
- /* dma 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);
-}
-
-void task_resume(struct mars_task_context *task)
-{
- struct mars_task_context_save_unit
- list[MARS_TASK_CONTEXT_SAVE_UNIT_MAX];
- int i, offset = 0;
-
- /* restore workload stack pointer */
- workload_stack = (void *)task->stack;
-
- /* dma save 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 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);
-}
-
-void task_schedule(struct mars_task_context *task, struct mars_task_args *args)
-{
- /* initialize task specific context variables */
- task->stack = 0;
- if (args)
- memcpy(&task->args, args, sizeof(struct mars_task_args));
-}
--- a/core/src/mpu/kernel/kernel_workload.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * 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 "kernel.h"
-
-extern struct mars_workload_queue_header queue_header;
-extern struct mars_workload_queue_block queue_block;
-extern struct mars_workload_context workload;
-extern uint8_t workload_type;
-extern uint8_t workload_state;
-extern uint16_t workload_index;
-extern uint64_t workload_ea;
-
-uint16_t workload_get_id(void)
-{
- return workload_index;
-}
-
-uint64_t workload_get_ea(void)
-{
- return workload_ea;
-}
-
-struct mars_workload_context *workload_get(void)
-{
- return &workload;
-}
-
-struct mars_workload_context *workload_get_by_id(uint16_t workload_id)
-{
- static struct mars_workload_context requested_workload;
- uint64_t requested_workload_ea;
-
- /* check function params */
- if (workload_id >= MARS_WORKLOAD_MAX)
- return NULL;
-
- /* workload id is same as current workload so return local copy */
- if (workload_id == workload_index)
- return &workload;
-
- /* get ea of workload to get */
- requested_workload_ea = queue_header.context_ea +
- workload_id * sizeof(struct mars_workload_context);
-
- /* dma the workload context code into LS from main memory */
- mars_dma_get_and_wait((void *)&requested_workload,
- requested_workload_ea, sizeof(struct mars_workload_context),
- MARS_DMA_TAG);
-
- return &requested_workload;
-}
-
-void workload_exec(void)
-{
- /* set current workload state to running */
- workload_state = MARS_WORKLOAD_STATE_RUNNING;
-
- /* workload type specific handling */
- switch (workload_type) {
- case MARS_WORKLOAD_TYPE_TASK:
- task_exec((struct mars_task_context *)&workload);
- break;
- }
-}
-
-void workload_exit(void)
-{
- /* set current workload state to finished */
- workload_state = MARS_WORKLOAD_STATE_FINISHED;
-
- /* workload type specific handling */
- switch (workload_type) {
- case MARS_WORKLOAD_TYPE_TASK:
- task_exit((struct mars_task_context *)&workload);
- break;
- }
-}
-
-void workload_yield(void)
-{
- /* set current workload state to ready */
- workload_state = MARS_WORKLOAD_STATE_READY;
-
- /* workload type specific handling */
- switch (workload_type) {
- case MARS_WORKLOAD_TYPE_TASK:
- /* save non-volatile registers */
- registers_save();
-
- /* yield the task context */
- task_yield((struct mars_task_context *)&workload);
- break;
- }
-}
-
-void workload_resume(void)
-{
- /* set current workload state to running */
- workload_state = MARS_WORKLOAD_STATE_RUNNING;
-
- /* workload type specific handling */
- switch (workload_type) {
- case MARS_WORKLOAD_TYPE_TASK:
- /* resume the task context */
- task_resume((struct mars_task_context *)&workload);
-
- /* restore non-volatile registers */
- registers_restore();
- break;
- }
-}
-
-int workload_schedule(uint16_t workload_id, void *args, uint8_t priority)
-{
- struct mars_workload_context schedule_workload;
- uint8_t schedule_workload_type;
- uint64_t schedule_workload_ea;
- uint64_t block_ea;
- int block;
- int index;
-
- /* check function params */
- if (workload_id >= MARS_WORKLOAD_MAX)
- return MARS_ERROR_PARAMS;
- if (workload_id == workload_index)
- return MARS_ERROR_PARAMS;
-
- /* calculate block/index from id */
- block = workload_id / MARS_WORKLOAD_PER_BLOCK;
- index = 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;
-
- mars_mutex_lock_get(block_ea, (struct mars_mutex *)&queue_block);
-
- /* make sure workload is in the correct 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_type = MARS_BITS_GET(&queue_block.bits[index], TYPE);
- schedule_workload_ea = queue_header.context_ea +
- workload_id * sizeof(struct mars_workload_context);
-
- /* dma the workload context code into LS from main memory */
- mars_dma_get_and_wait((void *)&schedule_workload,
- schedule_workload_ea, sizeof(struct mars_workload_context),
- MARS_DMA_TAG);
-
- /* workload type specific handling */
- switch (schedule_workload_type) {
- case MARS_WORKLOAD_TYPE_TASK:
- task_schedule((struct mars_task_context *)&schedule_workload,
- (struct mars_task_args *)args);
- break;
- }
-
- /* dma the workload context code into main memory from LS */
- mars_dma_put_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_READY);
- 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);
-
- return MARS_SUCCESS;
-}
-
-int workload_wait(uint16_t workload_id)
-{
- uint64_t block_ea;
- int block;
- int index;
-
- /* check function params */
- if (workload_id >= MARS_WORKLOAD_MAX)
- return MARS_ERROR_PARAMS;
- if (workload_id == workload_index)
- return MARS_ERROR_PARAMS;
-
- /* calculate block/index from id */
- block = workload_index / MARS_WORKLOAD_PER_BLOCK;
- index = workload_index % 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);
-
- /* make sure workload is initialized */
- if (MARS_BITS_GET(&queue_block.bits[index], STATE) ==
- MARS_WORKLOAD_STATE_NONE) {
- mars_mutex_unlock_put(block_ea,
- (struct mars_mutex *)&queue_block);
- return MARS_ERROR_STATE;
- }
-
- /* set the workload id to wait for */
- MARS_BITS_SET(&queue_block.bits[index], WAIT_ID, workload_id);
-
- mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
-
- return MARS_SUCCESS;
-}
-
-int workload_try_wait(uint16_t workload_id)
-{
- uint64_t block_ea;
- int block;
- int index;
-
- /* check function params */
- if (workload_id >= MARS_WORKLOAD_MAX)
- return MARS_ERROR_PARAMS;
- if (workload_id == workload_index)
- return MARS_ERROR_PARAMS;
-
- /* calculate block/index from id */
- block = workload_id / MARS_WORKLOAD_PER_BLOCK;
- index = 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;
-
- 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_NONE) {
- mars_mutex_unlock_put(block_ea,
- (struct mars_mutex *)&queue_block);
- return MARS_ERROR_STATE;
- }
-
- mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
-
- /* check if workload is finished */
- if (MARS_BITS_GET(&queue_block.bits[index], STATE) !=
- MARS_WORKLOAD_STATE_FINISHED)
- return MARS_ERROR_BUSY;
-
- return MARS_SUCCESS;
-}
-
-int workload_signal_send(uint16_t workload_id)
-{
- uint64_t block_ea;
- int block;
- int index;
-
- /* check function params */
- if (workload_id >= MARS_WORKLOAD_MAX)
- return MARS_ERROR_PARAMS;
- if (workload_id == workload_index)
- return MARS_ERROR_PARAMS;
-
- /* calculate block/index from id */
- block = workload_id / MARS_WORKLOAD_PER_BLOCK;
- index = 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;
-
- mars_mutex_lock_get(block_ea, (struct mars_mutex *)&queue_block);
-
- /* make sure workload is initialized */
- if (MARS_BITS_GET(&queue_block.bits[index], STATE) ==
- MARS_WORKLOAD_STATE_NONE) {
- mars_mutex_unlock_put(block_ea,
- (struct mars_mutex *)&queue_block);
- return MARS_ERROR_STATE;
- }
-
- /* set the workload signal */
- MARS_BITS_SET(&queue_block.bits[index], SIGNAL,
- MARS_WORKLOAD_SIGNAL_ON);
-
- mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
-
- return MARS_SUCCESS;
-}
-
-void workload_signal_wait(void)
-{
- /* set current workload state to waiting */
- workload_state = MARS_WORKLOAD_STATE_WAITING;
-
- /* workload type specific handling */
- switch (workload_type) {
- case MARS_WORKLOAD_TYPE_TASK:
- /* save non-volatile registers */
- registers_save();
-
- /* yield the task context */
- task_yield((struct mars_task_context *)&workload);
- break;
- }
-}
-
-int workload_signal_try_wait(void)
-{
- uint64_t block_ea;
- int block;
- int index;
-
- /* check function params */
- if (workload_index >= MARS_WORKLOAD_MAX)
- return MARS_ERROR_PARAMS;
-
- /* calculate block/index from id */
- block = workload_index / MARS_WORKLOAD_PER_BLOCK;
- index = workload_index % 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_NONE) {
- mars_mutex_unlock_put(block_ea,
- (struct mars_mutex *)&queue_block);
- return MARS_ERROR_STATE;
- }
-
- mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
-
- /* return busy if task has not received signal */
- if (MARS_BITS_GET(&queue_block.bits[index], SIGNAL) !=
- MARS_WORKLOAD_SIGNAL_ON)
- return MARS_ERROR_BUSY;
-
- return MARS_SUCCESS;
-}
More information about the cbe-oss-dev
mailing list