[Cbe-oss-dev] [PATCH 8/10] MARS: workload queue mutex protection

Yuji Mano Yuji.Mano at am.sony.com
Thu Aug 28 05:39:46 EST 2008


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>

---
 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)





More information about the cbe-oss-dev mailing list