[Cbe-oss-dev] [PATCH 8/10] MARS: workload queue mutex protection
Kazunori Asayama
asayama at sm.sony.co.jp
Fri Aug 29 14:51:17 EST 2008
Yuji Mano wrote:
> This adds mutex protection when accessing the shared workload queue.
>
> Prior to this patch the kernel scheduler accessed the whole queue block
> atomically. Now the kernel scheduler atomically locks the queue block when it
> needs to access it.
>
> Host-side access of the queue block now also uses the mutex locks to keep the
> workload queue functions thread-safe.
>
> This also replaces the previously used MARS context mutex. The workload queue
> handles its own mutex without the workload model APIs needing to manage the
> MARS context mutex.
>
> Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>
Acked-by: Kazunori Asayama <asayama at sm.sony.co.jp>
>
> ---
> include/common/mars/mars_workload_types.h | 11 -
> include/host/mars/mars.h | 2
> include/mpu/mars/mars_kernel.h | 3
> src/host/lib/mars.c | 11 -
> src/host/lib/mars_task.c | 12 -
> src/host/lib/mars_workload_queue.c | 97 +++++++++++--
> src/mpu/kernel/Makefile.am | 3
> src/mpu/kernel/mars_kernel_scheduler.c | 73 ++--------
> src/mpu/kernel/mars_kernel_workload.c | 218 ++++++++++++------------------
> 9 files changed, 202 insertions(+), 228 deletions(-)
>
> --- a/include/common/mars/mars_workload_types.h
> +++ b/include/common/mars/mars_workload_types.h
> @@ -64,9 +64,9 @@ extern "C" {
> #define MARS_WORKLOAD_SIGNAL_ON 0x1 /* signal set on */
> #define MARS_WORKLOAD_SIGNAL_OFF 0x0 /* signal set off */
>
> -#define MARS_WORKLOAD_MAX 1024 /* wl max */
> -#define MARS_WORKLOAD_PER_BLOCK 16 /* wl per block */
> -#define MARS_WORKLOAD_NUM_BLOCKS 64 /* wl max / per block */
> +#define MARS_WORKLOAD_PER_BLOCK 15 /* wl/block */
> +#define MARS_WORKLOAD_NUM_BLOCKS 100 /* total blocks */
> +#define MARS_WORKLOAD_MAX 1500 /* blocks * wl/block */
>
> #define MARS_WORKLOAD_CONTEXT_SIZE 128 /* size of 128 bytes */
> #define MARS_WORKLOAD_CONTEXT_ALIGN 128 /* align to 128 bytes */
> @@ -82,9 +82,10 @@ struct mars_workload_context {
>
> /* 128 byte workload queue header structure */
> struct mars_workload_queue_header {
> + uint32_t lock;
> + uint32_t count;
> uint64_t queue_ea;
> uint64_t context_ea;
> - uint32_t count;
> uint8_t flag;
> } __attribute__((aligned(MARS_WORKLOAD_QUEUE_HEADER_ALIGN)));
>
> @@ -100,6 +101,8 @@ struct mars_workload_queue_block_bits {
>
> /* 128 byte workload queue block structure */
> struct mars_workload_queue_block {
> + uint32_t lock;
> + uint32_t pad;
> struct mars_workload_queue_block_bits bits[MARS_WORKLOAD_PER_BLOCK];
> } __attribute__((aligned(MARS_WORKLOAD_QUEUE_BLOCK_ALIGN)));
>
> --- a/include/host/mars/mars.h
> +++ b/include/host/mars/mars.h
> @@ -79,8 +79,6 @@ struct mars_context {
> struct mars_params *params;
> /* parameters for the MARS kernel */
> struct mars_kernel_params *kernel_params;
> - /* mutex for the MARS context */
> - struct mars_mutex *mutex;
> /* process queue where process requests are added */
> struct mars_workload_queue *workload_queue;
> /* array of mpu context threads */
> --- a/include/mpu/mars/mars_kernel.h
> +++ b/include/mpu/mars/mars_kernel.h
> @@ -43,9 +43,10 @@ extern "C" {
> #endif
>
> #include <stdint.h>
> +
> #include "mars/mars_dma.h"
> +#include "mars/mars_mutex.h"
> #include "mars/mars_timer.h"
> -#include "mars/mars_atomic.h"
> #include "mars/mars_error.h"
> #include "mars/mars_kernel_types.h"
> #include "mars/mars_workload_types.h"
> --- a/src/host/lib/mars.c
> +++ b/src/host/lib/mars.c
> @@ -156,16 +156,6 @@ int mars_initialize(struct mars_context
> MARS_CHECK_CLEANUP_RET(mars->kernel_params, mars_finalize(mars),
> MARS_ERROR_MEMORY);
>
> - /* allocate mutex */
> - mars->mutex = (struct mars_mutex *)
> - memalign(MARS_MUTEX_ALIGN, sizeof(struct mars_mutex));
> - MARS_CHECK_CLEANUP_RET(mars->mutex, mars_finalize(mars),
> - MARS_ERROR_MEMORY);
> -
> - /* initialize mutex */
> - ret = mars_mutex_initialize(mars->mutex);
> - MARS_CHECK_CLEANUP_RET(ret == MARS_SUCCESS, mars_finalize(mars), ret);
> -
> /* allocate workload queue */
> mars->workload_queue = (struct mars_workload_queue *)
> memalign(MARS_WORKLOAD_QUEUE_ALIGN,
> @@ -211,7 +201,6 @@ int mars_finalize(struct mars_context *m
> /* free allocated memory */
> free(mars->params);
> free(mars->kernel_params);
> - free(mars->mutex);
> free(mars->workload_queue);
> free(mars->mpu_context_threads);
>
> --- a/src/host/lib/mars_task.c
> +++ b/src/host/lib/mars_task.c
> @@ -88,8 +88,6 @@ int mars_task_initialize(struct mars_con
> task.context_save_area = 0;
> }
>
> - mars_mutex_lock(mars->mutex);
> -
> /* add the task to the workload queue */
> ret = workload_queue_add(mars->workload_queue, &task.id.workload_id,
> (struct mars_workload_context *)&task,
> @@ -101,8 +99,6 @@ int mars_task_initialize(struct mars_con
> /* copy the task id into return id */
> *id = task.id;
>
> - mars_mutex_unlock(mars->mutex);
> -
> MARS_PRINT("Initialize Task Context %d\n", task->id.workload_id);
>
> return MARS_SUCCESS;
> @@ -118,8 +114,6 @@ int mars_task_finalize(struct mars_task_
> struct mars_task_context task;
> struct mars_context *mars = (struct mars_context *)id->mars_context_ea;
>
> - mars_mutex_lock(mars->mutex);
> -
> /* remove the task from the workload queue */
> ret = workload_queue_remove(mars->workload_queue, id->workload_id,
> (struct mars_workload_context *)&task);
> @@ -129,8 +123,6 @@ int mars_task_finalize(struct mars_task_
> if (task.context_save_size)
> free((void *)task.context_save_area);
>
> - mars_mutex_unlock(mars->mutex);
> -
> MARS_PRINT("Finalize Task Context %d\n", task.id.workload_id);
>
> return MARS_SUCCESS;
> @@ -159,15 +151,11 @@ int mars_task_schedule(struct mars_task_
> struct mars_task_context *task = NULL;
> struct mars_context *mars = (struct mars_context *)id->mars_context_ea;
>
> - mars_mutex_lock(mars->mutex);
> -
> /* schedule the workload in the workload queue */
> ret = workload_queue_schedule(mars->workload_queue, id->workload_id,
> priority, callback, args);
> MARS_CHECK_RET(ret == MARS_SUCCESS, ret);
>
> - mars_mutex_unlock(mars->mutex);
> -
> MARS_PRINT("Schedule Task Context %d\n", task->id.workload_id);
>
> return MARS_SUCCESS;
> --- a/src/host/lib/mars_workload_queue.c
> +++ b/src/host/lib/mars_workload_queue.c
> @@ -48,13 +48,38 @@ int workload_queue_initialize(struct mar
> {
> MARS_CHECK_RET(queue, MARS_ERROR_NULL);
>
> - memset(queue, 0, sizeof(struct mars_workload_queue));
> + int block;
> + int index;
> +
> + mars_mutex_initialize((struct mars_mutex *)&queue->header);
> + mars_mutex_lock((struct mars_mutex *)&queue->header);
>
> queue->header.queue_ea = (uint64_t)(uintptr_t)queue;
> queue->header.context_ea = (uint64_t)(uintptr_t)&queue->context;
> queue->header.count = 0;
> queue->header.flag = MARS_FLAG_NONE;
>
> + /* initialize workload queue blocks */
> + for (block = 0; block < MARS_WORKLOAD_NUM_BLOCKS; block++) {
> + struct mars_workload_queue_block *p = &queue->block[block];
> +
> + mars_mutex_initialize((struct mars_mutex *)p);
> + mars_mutex_lock((struct mars_mutex *)p);
> +
> + for (index = 0; index < MARS_WORKLOAD_PER_BLOCK; index++) {
> + p->bits[index].type = MARS_WORKLOAD_TYPE_NONE;
> + p->bits[index].state = MARS_WORKLOAD_STATE_NONE;
> + p->bits[index].priority = MARS_WORKLOAD_PRIORITY_MIN;
> + p->bits[index].counter = MARS_WORKLOAD_COUNTER_MIN;
> + p->bits[index].signal = MARS_WORKLOAD_SIGNAL_OFF;
> + p->bits[index].wait = MARS_WORKLOAD_ID_NONE;
> + }
> +
> + mars_mutex_unlock((struct mars_mutex *)p);
> + }
> +
> + mars_mutex_unlock((struct mars_mutex *)&queue->header);
> +
> return MARS_SUCCESS;
> }
>
> @@ -63,8 +88,12 @@ int workload_queue_finalize(struct mars_
> MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> MARS_CHECK_RET(!queue->header.count, MARS_ERROR_STATE);
>
> + mars_mutex_lock((struct mars_mutex *)&queue->header);
> +
> queue->header.flag = MARS_FLAG_EXIT;
>
> + mars_mutex_unlock((struct mars_mutex *)&queue->header);
> +
> return MARS_SUCCESS;
> }
>
> @@ -81,6 +110,8 @@ int workload_queue_add(struct mars_workl
> int block = 0;
> int index = 0;
>
> + mars_mutex_lock((struct mars_mutex *)&queue->header);
> +
> /* search through workload queue for open slot */
> if (queue->header.count) {
> int i;
> @@ -106,15 +137,22 @@ int workload_queue_add(struct mars_workl
> memcpy(&queue->context[*id], workload,
> sizeof(struct mars_workload_context));
>
> - /* update workload queue header info */
> + /* update workload queue block info */
> + mars_mutex_lock((struct mars_mutex *)&queue->block[block]);
> +
> queue->block[block].bits[index].type = type;
> queue->block[block].bits[index].state = MARS_WORKLOAD_STATE_FINISHED;
> queue->block[block].bits[index].priority = MARS_WORKLOAD_PRIORITY_MIN;
> queue->block[block].bits[index].counter = MARS_WORKLOAD_COUNTER_MIN;
> queue->block[block].bits[index].signal = MARS_WORKLOAD_SIGNAL_OFF;
> queue->block[block].bits[index].wait = MARS_WORKLOAD_ID_NONE;
> +
> + mars_mutex_unlock((struct mars_mutex *)&queue->block[block]);
> +
> queue->header.count++;
>
> + mars_mutex_unlock((struct mars_mutex *)&queue->header);
> +
> return MARS_SUCCESS;
> }
>
> @@ -128,22 +166,33 @@ int workload_queue_remove(struct mars_wo
> int block = id / MARS_WORKLOAD_PER_BLOCK;
> int index = id % MARS_WORKLOAD_PER_BLOCK;
>
> - MARS_CHECK_RET(queue->block[block].bits[index].state ==
> - MARS_WORKLOAD_STATE_FINISHED, MARS_ERROR_STATE);
> + mars_mutex_lock((struct mars_mutex *)&queue->header.lock);
> + mars_mutex_lock((struct mars_mutex *)&queue->block[block].lock);
>
> - /* copy workload context out from workload queue */
> - memcpy(workload, &queue->context[id],
> - sizeof(struct mars_workload_context));
> + MARS_CHECK_CLEANUP_RET(queue->block[block].bits[index].state ==
> + MARS_WORKLOAD_STATE_FINISHED,
> + mars_mutex_unlock((struct mars_mutex *)&queue->block[block]);
> + mars_mutex_unlock((struct mars_mutex *)&queue->header),
> + MARS_ERROR_STATE);
>
> - /* update workload queue info */
> + /* update workload queue block info */
> queue->block[block].bits[index].type = MARS_WORKLOAD_TYPE_NONE;
> queue->block[block].bits[index].state = MARS_WORKLOAD_STATE_NONE;
> queue->block[block].bits[index].priority = MARS_WORKLOAD_PRIORITY_MIN;
> queue->block[block].bits[index].counter = MARS_WORKLOAD_COUNTER_MIN;
> queue->block[block].bits[index].signal = MARS_WORKLOAD_SIGNAL_OFF;
> queue->block[block].bits[index].wait = MARS_WORKLOAD_ID_NONE;
> +
> + mars_mutex_unlock((struct mars_mutex *)&queue->block[block]);
> +
> + /* copy workload context out from workload queue */
> + memcpy(workload, &queue->context[id],
> + sizeof(struct mars_workload_context));
> +
> queue->header.count--;
>
> + mars_mutex_unlock((struct mars_mutex *)&queue->header);
> +
> return MARS_SUCCESS;
> }
>
> @@ -157,8 +206,12 @@ int workload_queue_schedule(struct mars_
> int block = id / MARS_WORKLOAD_PER_BLOCK;
> int index = id % MARS_WORKLOAD_PER_BLOCK;
>
> - MARS_CHECK_RET(queue->block[block].bits[index].state ==
> - MARS_WORKLOAD_STATE_FINISHED, MARS_ERROR_STATE);
> + mars_mutex_lock((struct mars_mutex *)&queue->block[block]);
> +
> + MARS_CHECK_CLEANUP_RET(queue->block[block].bits[index].state ==
> + MARS_WORKLOAD_STATE_FINISHED,
> + mars_mutex_unlock((struct mars_mutex *)&queue->block[block]),
> + MARS_ERROR_STATE);
>
> /* if provided call the callback with the workload context pointer */
> if (callback)
> @@ -171,6 +224,8 @@ int workload_queue_schedule(struct mars_
> queue->block[block].bits[index].signal = MARS_WORKLOAD_SIGNAL_OFF;
> queue->block[block].bits[index].wait = MARS_WORKLOAD_ID_NONE;
>
> + mars_mutex_unlock((struct mars_mutex *)&queue->block[block]);
> +
> return MARS_SUCCESS;
> }
>
> @@ -184,12 +239,13 @@ int workload_queue_wait(struct mars_work
> int block = id / MARS_WORKLOAD_PER_BLOCK;
> int index = id % MARS_WORKLOAD_PER_BLOCK;
>
> - MARS_CHECK_RET(queue->block[block].bits[index].state !=
> - MARS_WORKLOAD_STATE_NONE, MARS_ERROR_STATE);
> -
> while (queue->block[block].bits[index].state !=
> - MARS_WORKLOAD_STATE_FINISHED)
> + MARS_WORKLOAD_STATE_FINISHED) {
> + MARS_CHECK_RET(queue->block[block].bits[index].state !=
> + MARS_WORKLOAD_STATE_NONE,
> + MARS_ERROR_STATE);
> sched_yield();
> + }
>
> /* copy workload context out from workload queue */
> memcpy(workload, &queue->context[id],
> @@ -209,7 +265,8 @@ int workload_queue_try_wait(struct mars_
> int index = id % MARS_WORKLOAD_PER_BLOCK;
>
> MARS_CHECK_RET(queue->block[block].bits[index].state !=
> - MARS_WORKLOAD_STATE_NONE, MARS_ERROR_STATE);
> + MARS_WORKLOAD_STATE_NONE,
> + MARS_ERROR_STATE);
>
> if (queue->block[block].bits[index].state !=
> MARS_WORKLOAD_STATE_FINISHED)
> @@ -230,10 +287,16 @@ int workload_queue_signal_send(struct ma
> int block = id / MARS_WORKLOAD_PER_BLOCK;
> int index = id % MARS_WORKLOAD_PER_BLOCK;
>
> - MARS_CHECK_RET(queue->block[block].bits[index].state !=
> - MARS_WORKLOAD_STATE_NONE, MARS_ERROR_STATE);
> + mars_mutex_lock((struct mars_mutex *)&queue->block[block]);
> +
> + MARS_CHECK_CLEANUP_RET(queue->block[block].bits[index].state !=
> + MARS_WORKLOAD_STATE_NONE,
> + mars_mutex_unlock((struct mars_mutex *)&queue->block[block]),
> + MARS_ERROR_STATE);
>
> queue->block[block].bits[index].signal = MARS_WORKLOAD_SIGNAL_ON;
>
> + mars_mutex_unlock((struct mars_mutex *)&queue->block[block]);
> +
> return MARS_SUCCESS;
> }
> --- a/src/mpu/kernel/Makefile.am
> +++ b/src/mpu/kernel/Makefile.am
> @@ -54,11 +54,14 @@ mars_kernel_CFLAGS = \
> -Wmissing-declarations
>
> mars_kernel_LDFLAGS = \
> + -L../lib \
> -Wl,--defsym=__stack=0x0fff0 \
> -Wl,-gc-sections \
> -Wl,-N \
> -Wl,-s
>
> +mars_kernel_LDADD = -lmars
> +
> mars_kernel_SOURCES = \
> mars_kernel.c \
> mars_kernel_registers.c \
> --- a/src/mpu/kernel/mars_kernel_scheduler.c
> +++ b/src/mpu/kernel/mars_kernel_scheduler.c
> @@ -137,75 +137,40 @@ static int search_block(int block)
>
> static int reserve_block(int block)
> {
> - int status;
> int index;
> -
> - atomic_event_setup();
> -
> - /* attempt to reserve workload block until successful */
> - do {
> - /* reserve cache line of workload queue block */
> - atomic_get(&queue_block,
> - queue_header.queue_ea +
> + uint64_t block_ea = queue_header.queue_ea +
> offsetof(struct mars_workload_queue, block) +
> - sizeof(struct mars_workload_queue_block) * block);
> + sizeof(struct mars_workload_queue_block) * block;
>
> - /* set the workload index */
> - index = search_block(block);
> - if (index >= 0) {
> - /* update the current state of the workload */
> - queue_block.bits[index].state =
> - MARS_WORKLOAD_STATE_RUNNING;
> -
> - /* reset the counter for reserved workload */
> - queue_block.bits[index].counter =
> - MARS_WORKLOAD_COUNTER_MIN;
> - }
> -
> - /* attempt to write back workload queue block to cache line */
> - status = atomic_put(&queue_block,
> - 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 */
> + queue_block.bits[index].state = MARS_WORKLOAD_STATE_RUNNING;
>
> - /* write back failed so wait until reservation is lost */
> - if (status)
> - atomic_event_wait();
> - } while (status);
> + /* reset the counter for reserved workload */
> + queue_block.bits[index].counter = MARS_WORKLOAD_COUNTER_MIN;
> + }
>
> - atomic_event_restore();
> + mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
>
> return index;
> }
>
> static void release_block(int block, int index)
> {
> - int status;
> -
> - atomic_event_setup();
> -
> - do {
> - /* reserve cache line of workload queue block */
> - atomic_get(&queue_block,
> - queue_header.queue_ea +
> + uint64_t block_ea = queue_header.queue_ea +
> offsetof(struct mars_workload_queue, block) +
> - sizeof(struct mars_workload_queue_block) * block);
> + sizeof(struct mars_workload_queue_block) * block;
>
> - /* update current workload state in workload queue block */
> - queue_block.bits[index].state = workload_state;
> -
> - /* attempt to write back workload queue block to cache line */
> - status = atomic_put(&queue_block,
> - 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);
>
> - /* write back failed so wait until reservation is lost */
> - if (status)
> - atomic_event_wait();
> - } while (status);
> + /* update current workload state in workload queue block */
> + queue_block.bits[index].state = workload_state;
>
> - atomic_event_restore();
> + mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
> }
>
> int reserve_workload(void)
> --- a/src/mpu/kernel/mars_kernel_workload.c
> +++ b/src/mpu/kernel/mars_kernel_workload.c
> @@ -131,69 +131,52 @@ int workload_schedule(uint16_t workload_
>
> int block = workload_id / MARS_WORKLOAD_PER_BLOCK;
> int index = workload_id % MARS_WORKLOAD_PER_BLOCK;
> - int status;
>
> - atomic_event_setup();
> -
> - /* attempt to schedule workload until successful */
> - do {
> - /* reserve cache line of workload queue block */
> - atomic_get(&queue_block,
> - queue_header.queue_ea +
> + uint64_t block_ea = queue_header.queue_ea +
> offsetof(struct mars_workload_queue, block) +
> - sizeof(struct mars_workload_queue_block) * 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 (queue_block.bits[index].state != MARS_WORKLOAD_STATE_FINISHED) {
> + mars_mutex_unlock_put(block_ea,
> + (struct mars_mutex *)&queue_block);
> + return MARS_ERROR_STATE;
> + }
>
> - /* make sure workload is in the correct state */
> - if (queue_block.bits[index].state !=
> - MARS_WORKLOAD_STATE_FINISHED) {
> - atomic_event_restore();
> - return MARS_ERROR_STATE;
> - }
> -
> - /* get information of workload to schedule */
> - schedule_workload_type = queue_block.bits[index].type;
> - schedule_workload_ea = queue_header.context_ea +
> + /* get information of workload to schedule */
> + schedule_workload_type = 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);
> -
> - queue_block.bits[index].state = MARS_WORKLOAD_STATE_READY;
> - queue_block.bits[index].priority = priority;
> - queue_block.bits[index].counter = MARS_WORKLOAD_COUNTER_MIN;
> - queue_block.bits[index].signal = MARS_WORKLOAD_SIGNAL_OFF;
> - queue_block.bits[index].wait = MARS_WORKLOAD_ID_NONE;
> -
> - /* attempt to write back workload queue block to cache line */
> - status = atomic_put(&queue_block,
> - queue_header.queue_ea +
> - offsetof(struct mars_workload_queue, block) +
> - sizeof(struct mars_workload_queue_block) * block);
> + /* 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);
>
> - /* write back failed so wait until reservation is lost */
> - if (status)
> - atomic_event_wait();
> - } while (status);
> + /* 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);
> +
> + queue_block.bits[index].state = MARS_WORKLOAD_STATE_READY;
> + queue_block.bits[index].priority = priority;
> + queue_block.bits[index].counter = MARS_WORKLOAD_COUNTER_MIN;
> + queue_block.bits[index].signal = MARS_WORKLOAD_SIGNAL_OFF;
> + queue_block.bits[index].wait = MARS_WORKLOAD_ID_NONE;
>
> - atomic_event_restore();
> + mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
>
> return MARS_SUCCESS;
> }
> @@ -205,38 +188,24 @@ int workload_wait(uint16_t workload_id)
>
> int block = workload_index / MARS_WORKLOAD_PER_BLOCK;
> int index = workload_index % MARS_WORKLOAD_PER_BLOCK;
> - int status;
>
> - atomic_event_setup();
> -
> - /* attempt to update workload queue block until successful */
> - do {
> - atomic_get(&queue_block,
> - queue_header.queue_ea +
> + uint64_t block_ea = queue_header.queue_ea +
> offsetof(struct mars_workload_queue, block) +
> - sizeof(struct mars_workload_queue_block) * block);
> + sizeof(struct mars_workload_queue_block) * block;
>
> - /* make sure workload is initialized */
> - if (queue_block.bits[index].state == MARS_WORKLOAD_STATE_NONE) {
> - atomic_event_restore();
> - return MARS_ERROR_STATE;
> - }
> -
> - /* set the workload id to wait for */
> - queue_block.bits[index].wait = workload_id;
> -
> - /* attempt to write back workload queue block to cache line */
> - status = atomic_put(&queue_block,
> - 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 (queue_block.bits[index].state == MARS_WORKLOAD_STATE_NONE) {
> + mars_mutex_unlock_put(block_ea,
> + (struct mars_mutex *)&queue_block);
> + return MARS_ERROR_STATE;
> + }
>
> - /* write back failed so wait until reservation is lost */
> - if (status)
> - atomic_event_wait();
> - } while (status);
> + /* set the workload id to wait for */
> + queue_block.bits[index].wait = workload_id;
>
> - atomic_event_restore();
> + mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
>
> return MARS_SUCCESS;
> }
> @@ -249,14 +218,19 @@ int workload_try_wait(uint16_t workload_
> int block = workload_id / MARS_WORKLOAD_PER_BLOCK;
> int index = workload_id % MARS_WORKLOAD_PER_BLOCK;
>
> - atomic_get(&queue_block,
> - queue_header.queue_ea +
> - offsetof(struct mars_workload_queue, block) +
> - sizeof(struct mars_workload_queue_block) * block);
> -
> - MARS_CHECK_RET(queue_block.bits[index].state !=
> - MARS_WORKLOAD_STATE_NONE,
> - MARS_ERROR_STATE);
> + 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);
> +
> + MARS_CHECK_CLEANUP_RET(queue_block.bits[index].state !=
> + MARS_WORKLOAD_STATE_NONE,
> + mars_mutex_unlock_put(block_ea,
> + (struct mars_mutex *)&queue_block),
> + MARS_ERROR_STATE);
> +
> + mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
>
> if (queue_block.bits[index].state != MARS_WORKLOAD_STATE_FINISHED)
> return MARS_ERROR_BUSY;
> @@ -271,39 +245,24 @@ int workload_signal_send(uint16_t worklo
>
> int block = workload_id / MARS_WORKLOAD_PER_BLOCK;
> int index = workload_id % MARS_WORKLOAD_PER_BLOCK;
> - int status;
> -
> - atomic_event_setup();
>
> - /* attempt to update workload queue block until successful */
> - do {
> - /* reserve cache line of workload queue block */
> - atomic_get(&queue_block,
> - queue_header.queue_ea +
> + uint64_t block_ea = queue_header.queue_ea +
> offsetof(struct mars_workload_queue, block) +
> - sizeof(struct mars_workload_queue_block) * block);
> + sizeof(struct mars_workload_queue_block) * block;
>
> - /* make sure workload is initialized */
> - if (queue_block.bits[index].state == MARS_WORKLOAD_STATE_NONE) {
> - atomic_event_restore();
> - return MARS_ERROR_STATE;
> - }
> -
> - /* set the workload signal */
> - queue_block.bits[index].signal = MARS_WORKLOAD_SIGNAL_ON;
> -
> - /* attempt to write back workload queue block to cache line */
> - status = atomic_put(&queue_block,
> - 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);
>
> - /* write back failed so wait until reservation is lost */
> - if (status)
> - atomic_event_wait();
> - } while (status);
> + /* make sure workload is initialized */
> + if (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 */
> + queue_block.bits[index].signal = MARS_WORKLOAD_SIGNAL_ON;
>
> - atomic_event_restore();
> + mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
>
> return MARS_SUCCESS;
> }
> @@ -330,14 +289,19 @@ int workload_signal_try_wait(void)
> int block = workload_index / MARS_WORKLOAD_PER_BLOCK;
> int index = workload_index % MARS_WORKLOAD_PER_BLOCK;
>
> - atomic_get(&queue_block,
> - queue_header.queue_ea +
> - offsetof(struct mars_workload_queue, block) +
> - sizeof(struct mars_workload_queue_block) * block);
> -
> - MARS_CHECK_RET(queue_block.bits[index].state !=
> - MARS_WORKLOAD_STATE_NONE,
> - MARS_ERROR_STATE);
> + 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);
> +
> + MARS_CHECK_CLEANUP_RET(queue_block.bits[index].state !=
> + MARS_WORKLOAD_STATE_NONE,
> + mars_mutex_unlock_put(block_ea,
> + (struct mars_mutex *)&queue_block),
> + MARS_ERROR_STATE);
> +
> + mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
>
> /* return busy if task has not received signal */
> if (queue_block.bits[index].signal != MARS_WORKLOAD_SIGNAL_ON)
>
>
--
(ASAYAMA Kazunori
(asayama at sm.sony.co.jp))
t
More information about the cbe-oss-dev
mailing list