[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