[Cbe-oss-dev] [PATCH 14/28 v2]MARS/base: change mutex to kernel syscall

Yuji Mano yuji.mano at am.sony.com
Tue Feb 10 06:54:46 EST 2009


This moves the mutex implementation into the kernel and the kernel provides
syscalls for the mutex routines. Workload modules can use the mutex routines
through the module API.

The purpose of this change is to remove unnecessary duplicate code in the
workload (task) code to keep code size to a minimum.

Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>
---
v2:
 - move kernel mutex implementation out into separate mutex.c

 base/include/host/mars/mutex.h          |   18 +--
 base/include/mpu/mars/mars.h            |    1 
 base/include/mpu/mars/module.h          |   35 ++++++
 base/include/mpu/mars/mutex.h           |   68 -------------
 base/src/common/kernel_internal_types.h |   45 +++++---
 base/src/mpu/kernel/kernel.c            |   58 +++++------
 base/src/mpu/kernel/mutex.c             |  164 ++++++++++++++++++++++++++++++++
 base/src/mpu/lib/Makefile.am            |    6 -
 base/src/mpu/lib/module.c               |   10 +
 base/src/mpu/lib/mutex.c                |  163 -------------------------------
 10 files changed, 275 insertions(+), 293 deletions(-)

--- a/base/include/host/mars/mutex.h
+++ b/base/include/host/mars/mutex.h
@@ -125,16 +125,15 @@ int mars_mutex_unlock(uint64_t mutex_ea)
 
 /**
  * \ingroup group_mars_mutex
- * \brief <b>[host/MPU]</b> Locks a mutex.
+ * \brief <b>[host]</b> Locks a mutex.
  *
  * This function locks a mutex and blocks other requests to lock it.
  * It also loads the mutex instance from the effective address specified
  * into the local mutex instance.
  *
- * \note The <b>[host]</b> call should only be used when
- * MARS_ENABLE_DISCRETE_SHARED_MEMORY is enabled. Otherwise, the mutex
- * parameter is ignored and the function behaves the same as
- * \ref mars_mutex_lock.
+ * \note This call should only be used when MARS_ENABLE_DISCRETE_SHARED_MEMORY
+ * is enabled. Otherwise, the mutex parameter is ignored and the function
+ * behaves the same as \ref mars_mutex_lock.
  *
  * \param[in] mutex_ea		- ea of mutex instance to lock
  * \param[in] mutex		- pointer to local mutex instance
@@ -147,15 +146,14 @@ int mars_mutex_lock_get(uint64_t mutex_e
 
 /**
  * \ingroup group_mars_mutex
- * \brief <b>[host/MPU]</b> Unlocks a mutex.
+ * \brief <b>[host]</b> Unlocks a mutex.
  *
  * This function unlocks a previously locked mutex to allow other lock requests.
  * It also stores the local mutex instance into the effective address specified.
  *
- * \note The <b>[host]</b> call should only be used when
- * MARS_ENABLE_DISCRETE_SHARED_MEMORY is enabled. Otherwise, the mutex
- * parameter is ignored and the function behaves the same as
- * \ref mars_mutex_unlock.
+ * \note This call should only be used when MARS_ENABLE_DISCRETE_SHARED_MEMORY
+ * is enabled. Otherwise, the mutex parameter is ignored and the function
+ * behaves the same as \ref mars_mutex_unlock.
  *
  * \param[in] mutex_ea		- ea of mutex instance to unlock
  * \param[in] mutex		- pointer to local mutex instance
--- a/base/include/mpu/mars/mars.h
+++ b/base/include/mpu/mars/mars.h
@@ -46,7 +46,6 @@
 
 #include <mars/base_features.h>
 #include <mars/error.h>
-#include <mars/mutex.h>
 #include <mars/task.h>
 
 #endif
--- a/base/include/mpu/mars/module.h
+++ b/base/include/mpu/mars/module.h
@@ -46,6 +46,7 @@
 
 #include <stdint.h>
 
+#include <mars/mutex_types.h>
 #include <mars/workload_types.h>
 
 #if defined(__cplusplus)
@@ -291,6 +292,40 @@ void mars_module_workload_finish(void);
 
 /**
  * \ingroup group_mars_workload_module
+ * \brief <b>[MPU]</b> Locks a mutex.
+ *
+ * This function locks a mutex and blocks other requests to lock it.
+ * It also loads the mutex instance from the effective address specified
+ * into the local mutex instance.
+ *
+ * \param[in] mutex_ea		- ea of mutex instance to lock
+ * \param[in] mutex		- pointer to local mutex instance
+ * \return
+ *	MARS_SUCCESS		- successfully locked mutex
+ * \n	MARS_ERROR_NULL		- ea is 0 or mutex is NULL
+ * \n	MARS_ERROR_ALIGN	- ea or mutex not aligned properly
+ */
+int mars_module_mutex_lock_get(uint64_t mutex_ea, struct mars_mutex *mutex);
+
+/**
+ * \ingroup group_mars_workload_module
+ * \brief <b>[MPU]</b> Unlocks a mutex.
+ *
+ * This function unlocks a previously locked mutex to allow other lock requests.
+ * It also stores the local mutex instance into the effective address specified.
+ *
+ * \param[in] mutex_ea		- ea of mutex instance to unlock
+ * \param[in] mutex		- pointer to local mutex instance
+ * \return
+ *	MARS_SUCCESS		- successfully unlocked mutex
+ * \n	MARS_ERROR_NULL		- ea is 0 or mutex is NULL
+ * \n	MARS_ERROR_ALIGN	- ea or mutex not aligned properly
+ * \n	MARS_ERROR_STATE	- instance not in locked state
+ */
+int mars_module_mutex_unlock_put(uint64_t mutex_ea, struct mars_mutex *mutex);
+
+/**
+ * \ingroup group_mars_workload_module
  * \brief <b>[MPU]</b> Notify host a particular 32-bit area is modified.
  *
  * \param[in] watch_point_ea	- ea of modified area
--- a/base/include/mpu/mars/mutex.h
+++ /dev/null
@@ -1,68 +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_MUTEX_H
-#define MARS_MUTEX_H
-
-/**
- * \file
- * \ingroup group_mars_mutex
- * \brief <b>[MPU]</b> MARS Mutex API
- */
-
-#include <stdint.h>
-#include <mars/mutex_types.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/**
- * \ingroup group_mars_mutex
- */
-int mars_mutex_lock_get(uint64_t mutex_ea, struct mars_mutex *mutex);
-
-/**
- * \ingroup group_mars_mutex
- */
-int mars_mutex_unlock_put(uint64_t mutex_ea, struct mars_mutex *mutex);
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif
--- a/base/src/common/kernel_internal_types.h
+++ b/base/src/common/kernel_internal_types.h
@@ -40,6 +40,8 @@
 
 #include <stdint.h>
 
+#include "mars/mutex_types.h"
+
 #define MARS_KERNEL_STATUS_BUSY			0x0
 #define MARS_KERNEL_STATUS_IDLE			0x1
 #define MARS_KERNEL_STATUS_EXIT			0x2
@@ -54,25 +56,28 @@
 
 /* mars kernel syscalls */
 struct mars_kernel_syscalls {
-	uint32_t			(*get_ticks)(void);
-	uint64_t			(*get_mars_context_ea)(void);
-	uint32_t			(*get_kernel_id)(void);
-	uint16_t			(*get_workload_id)(void);
-	struct mars_workload_context *	(*get_workload)(void);
-	struct mars_workload_context *	(*get_workload_by_id)(uint16_t id);
-
-	void	(*workload_exit)(uint8_t state);
-	int	(*workload_query)(uint16_t id, int query);
-	int	(*workload_wait_set)(uint16_t id);
-	int	(*workload_wait_reset)(void);
-	int	(*workload_signal_set)(uint16_t id);
-	int	(*workload_signal_reset)(void);
-	int	(*workload_schedule_begin)(uint16_t id, uint8_t priority,
-				struct mars_workload_context **workload);
-	int	(*workload_schedule_end)(uint16_t id);
-	int	(*workload_schedule_cancel)(uint16_t id);
+	uint32_t                       (*get_ticks)(void);
+	uint64_t                       (*get_mars_context_ea)(void);
+	uint32_t                       (*get_kernel_id)(void);
+	uint16_t                       (*get_workload_id)(void);
+	struct mars_workload_context * (*get_workload)(void);
+	struct mars_workload_context * (*get_workload_by_id)(uint16_t id);
+
+	void (*workload_exit)(uint8_t state);
+	int  (*workload_query)(uint16_t id, int query);
+	int  (*workload_wait_set)(uint16_t id);
+	int  (*workload_wait_reset)(void);
+	int  (*workload_signal_set)(uint16_t id);
+	int  (*workload_signal_reset)(void);
+	int  (*workload_schedule_begin)(uint16_t id, uint8_t priority,
+	 				struct mars_workload_context **workload);
+	int  (*workload_schedule_end)(uint16_t id);
+	int  (*workload_schedule_cancel)(uint16_t id);
+
+	int  (*mutex_lock_get)(uint64_t mutex_ea, struct mars_mutex *mutex);
+	int  (*mutex_unlock_put)(uint64_t mutex_ea, struct mars_mutex *mutex);
 
-	int	(*host_signal_send)(uint64_t watch_point_ea);
+	int  (*host_signal_send)(uint64_t watch_point_ea);
 };
 
 /* mars kernel ticks */
@@ -91,6 +96,10 @@ struct mars_kernel_params {
 	uint8_t pad2[MARS_KERNEL_PARAMS_SIZE - 32];
 } __attribute__((aligned(MARS_KERNEL_PARAMS_ALIGN)));
 
+/* mars kernel mutex */
+int mutex_lock_get(uint64_t mutex_ea, struct mars_mutex *mutex);
+int mutex_unlock_put(uint64_t mutex_ea, struct mars_mutex *mutex);
+
 /* mars module entry */
 void mars_module_entry(struct mars_kernel_syscalls *syscalls);
 
--- a/base/src/mpu/kernel/kernel.c
+++ b/base/src/mpu/kernel/kernel.c
@@ -43,7 +43,6 @@
 
 #include "mars/error.h"
 #include "mars/module.h"
-#include "mars/mutex.h"
 
 #include "kernel_internal_types.h"
 #include "workload_internal_types.h"
@@ -118,6 +117,16 @@ static void dma_put(void *ls, uint64_t e
 	mfc_read_tag_status();
 }
 
+static int host_signal_send(uint64_t watch_point_ea)
+{
+#ifdef ENABLE_COND_WAIT_FUTEX
+	spu_write_out_mbox((uint32_t)(watch_point_ea >> 32));
+	spu_write_out_intr_mbox((uint32_t)(watch_point_ea & 0xffffffff));
+#endif
+
+	return MARS_SUCCESS;
+}
+
 static uint32_t get_ticks(void)
 {
 	return kernel_params.kernel_ticks.offset - spu_read_decrementer();
@@ -205,12 +214,12 @@ static uint64_t get_block_bits(uint16_t 
 	block_ea = get_block_ea(block);
 
 	/* lock the queue block */
-	mars_mutex_lock_get(block_ea, (struct mars_mutex *)&queue_block);
+	mutex_lock_get(block_ea, (struct mars_mutex *)&queue_block);
 
 	block_bits = queue_block.bits[index];
 
 	/* unlock the queue block */
-	mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
+	mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
 
 	return block_bits;
 }
@@ -246,8 +255,8 @@ static void update_header_bits(int block
 	}
 
 	/* lock the queue header */
-	mars_mutex_lock_get(kernel_params.workload_queue_ea,
-			    (struct mars_mutex *)&queue_header);
+	mutex_lock_get(kernel_params.workload_queue_ea,
+		       (struct mars_mutex *)&queue_header);
 
 	/* set the info bits inside queue header for this queue block */
 	MARS_BITS_SET(block_bits, BLOCK_READY, block_ready);
@@ -258,8 +267,8 @@ static void update_header_bits(int block
 	queue_header.access++;
 
 	/* unlock the queue header */
-	mars_mutex_unlock_put(kernel_params.workload_queue_ea,
-			      (struct mars_mutex *)&queue_header);
+	mutex_unlock_put(kernel_params.workload_queue_ea,
+			 (struct mars_mutex *)&queue_header);
 }
 
 static void update_header_bits_counter(int block, int reset)
@@ -268,8 +277,8 @@ static void update_header_bits_counter(i
 	uint8_t block_counter = MARS_WORKLOAD_BLOCK_COUNTER_MIN;
 
 	/* lock the queue header */
-	mars_mutex_lock_get(kernel_params.workload_queue_ea,
-			    (struct mars_mutex *)&queue_header);
+	mutex_lock_get(kernel_params.workload_queue_ea,
+		       (struct mars_mutex *)&queue_header);
 
 	/* reset is not specified so increment current block counter */
 	if (!reset) {
@@ -282,8 +291,8 @@ static void update_header_bits_counter(i
 	MARS_BITS_SET(block_bits, BLOCK_COUNTER, block_counter);
 
 	/* unlock the queue header */
-	mars_mutex_unlock_put(kernel_params.workload_queue_ea,
-			      (struct mars_mutex *)&queue_header);
+	mutex_unlock_put(kernel_params.workload_queue_ea,
+			 (struct mars_mutex *)&queue_header);
 }
 
 static int workload_query(uint16_t id, int query)
@@ -338,13 +347,12 @@ static int change_bits(uint16_t id,
 	block_ea = get_block_ea(block);
 
 	/* lock the queue block */
-	mars_mutex_lock_get(block_ea, (struct mars_mutex *)&queue_block);
+	mutex_lock_get(block_ea, (struct mars_mutex *)&queue_block);
 
 	/* check for valid state */
 	if (check_bits &&
 	    !(*check_bits)(queue_block.bits[index], check_bits_param)) {
-		mars_mutex_unlock_put(block_ea,
-				      (struct mars_mutex *)&queue_block);
+		mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
 		return MARS_ERROR_STATE;
 	}
 
@@ -359,7 +367,7 @@ static int change_bits(uint16_t id,
 		(*callback)(id);
 
 	/* unlock the queue block */
-	mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
+	mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
 
 	return MARS_SUCCESS;
 }
@@ -525,16 +533,6 @@ static int workload_schedule_cancel(uint
 			    NULL);
 }
 
-static int host_signal_send(uint64_t watch_point_ea)
-{
-#ifdef ENABLE_COND_WAIT_FUTEX
-	spu_write_out_mbox((uint32_t)(watch_point_ea >> 32));
-	spu_write_out_intr_mbox((uint32_t)(watch_point_ea & 0xffffffff));
-#endif
-
-	return MARS_SUCCESS;
-}
-
 static struct mars_kernel_syscalls kernel_syscalls =
 {
 	get_ticks,
@@ -552,6 +550,8 @@ static struct mars_kernel_syscalls kerne
 	workload_schedule_begin,
 	workload_schedule_end,
 	workload_schedule_cancel,
+	mutex_lock_get,
+	mutex_unlock_put,
 	host_signal_send
 };
 
@@ -564,7 +564,7 @@ static int search_block(int block, int r
 	uint64_t block_ea = get_block_ea(block);
 
 	/* lock the queue block */
-	mars_mutex_lock_get(block_ea, (struct mars_mutex *)&queue_block);
+	mutex_lock_get(block_ea, (struct mars_mutex *)&queue_block);
 
 	/* search through all workloads in block */
 	for (i = 0; i < MARS_WORKLOAD_PER_BLOCK; i++) {
@@ -658,7 +658,7 @@ static int search_block(int block, int r
 	}
 
 	/* unlock the queue block */
-	mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
+	mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
 
 	/* returns -1 if no runnable workload found */
 	return index;
@@ -746,7 +746,7 @@ static void release_workload(void)
 	dma_put(&workload, workload_ea, sizeof(struct mars_workload_context));
 
 	/* lock the queue block */
-	mars_mutex_lock_get(block_ea, (struct mars_mutex *)&queue_block);
+	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], WORKLOAD_STATE, workload_state);
@@ -755,7 +755,7 @@ static void release_workload(void)
 	update_header_bits(block);
 
 	/* unlock the queue block */
-	mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
+	mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block);
 
 	/* workload state is finished so notify host */
 	if (workload_state == MARS_WORKLOAD_STATE_FINISHED)
--- /dev/null
+++ b/base/src/mpu/kernel/mutex.c
@@ -0,0 +1,164 @@
+/*
+ * 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 <stdint.h>
+#include <spu_mfcio.h>
+
+#include "mars/error.h"
+#include "mars/mutex_types.h"
+
+#include "kernel_internal_types.h"
+
+static struct mars_mutex mutex_buffer;
+
+int mutex_lock_get(uint64_t mutex_ea, struct mars_mutex *mutex)
+{
+	int status, mask, done = 0;
+	uint8_t id = 0;
+
+	/* check function params */
+	if (!mutex_ea)
+		return MARS_ERROR_NULL;
+	if (!mutex)
+		return MARS_ERROR_NULL;
+	if (mutex_ea & MARS_MUTEX_ALIGN_MASK)
+		return MARS_ERROR_ALIGN;
+	if ((uintptr_t)mutex & MARS_MUTEX_ALIGN_MASK)
+		return MARS_ERROR_ALIGN;
+
+	/* save event mask */
+	mask = spu_read_event_mask();
+
+	/* set event mask for the lost event */
+	spu_write_event_mask(MFC_LLR_LOST_EVENT);
+
+	/* update waiting state */
+	do {
+		mfc_getllar(mutex, mutex_ea, 0, 0);
+		mfc_read_atomic_status();
+
+		if (mutex->status.lock == MARS_MUTEX_UNLOCKED &&
+		    mutex->status.current_id == mutex->status.next_id) {
+			/* no other thread waiting for mutex so get lock now */
+			mutex->status.lock = MARS_MUTEX_LOCKED;
+			done = 1;
+		}
+		else {
+			/* otherwise update waiting state */
+			id = mutex->status.next_id++;
+			done = 0;
+		}
+
+		spu_dsync();
+		mfc_putllc(mutex, mutex_ea, 0, 0);
+		status = mfc_read_atomic_status() & MFC_PUTLLC_STATUS;
+	} while (status);
+
+	while (!done) {
+		mfc_getllar(mutex, mutex_ea, 0, 0);
+		mfc_read_atomic_status();
+
+		if (mutex->status.lock == MARS_MUTEX_LOCKED ||
+		    mutex->status.current_id != id) {
+			/* wait until mutex is released */
+			spu_read_event_status();
+			spu_write_event_ack(MFC_LLR_LOST_EVENT);
+		}
+		else {
+			/* get lock */
+			mutex->status.lock = MARS_MUTEX_LOCKED;
+			mutex->status.current_id++;
+
+			spu_dsync();
+			mfc_putllc(mutex, mutex_ea, 0, 0);
+			done = !(mfc_read_atomic_status() & MFC_PUTLLC_STATUS);
+		}
+	}
+
+	/* restore event mask */
+	spu_write_event_mask(mask);
+
+	/* clear any remnant lost event */
+	spu_write_event_ack(MFC_LLR_LOST_EVENT);
+
+	return MARS_SUCCESS;
+}
+
+int mutex_unlock_put(uint64_t mutex_ea, struct mars_mutex *mutex)
+{
+	int status, mask;
+
+	/* check function params */
+	if (!mutex_ea)
+		return MARS_ERROR_NULL;
+	if (!mutex)
+		return MARS_ERROR_NULL;
+	if (mutex_ea & MARS_MUTEX_ALIGN_MASK)
+		return MARS_ERROR_ALIGN;
+	if ((uintptr_t)mutex & MARS_MUTEX_ALIGN_MASK)
+		return MARS_ERROR_ALIGN;
+	if (mutex->status.lock != MARS_MUTEX_LOCKED)
+		return MARS_ERROR_STATE;
+
+	mfc_sync(0);
+
+	/* save event mask */
+	mask = spu_read_event_mask();
+
+	/* set event mask for the lost event */
+	spu_write_event_mask(MFC_LLR_LOST_EVENT);
+
+	do {
+		mfc_getllar(&mutex_buffer, mutex_ea, 0, 0);
+		mfc_read_atomic_status();
+
+		mutex->status = mutex_buffer.status;
+		mutex->status.lock = MARS_MUTEX_UNLOCKED;
+
+		spu_dsync();
+		mfc_putllc(mutex, mutex_ea, 0, 0);
+		status = mfc_read_atomic_status() & MFC_PUTLLC_STATUS;
+	} while (status);
+
+	/* restore event mask */
+	spu_write_event_mask(mask);
+
+	/* clear any remnant lost event */
+	spu_write_event_ack(MFC_LLR_LOST_EVENT);
+
+	return MARS_SUCCESS;
+}
--- a/base/src/mpu/lib/Makefile.am
+++ b/base/src/mpu/lib/Makefile.am
@@ -62,8 +62,7 @@ pkginclude_HEADERS = \
 	$(srcdir)/../../../include/common/mars/workload_types.h \
 	$(srcdir)/../../../include/mpu/mars/dma.h \
 	$(srcdir)/../../../include/mpu/mars/mars.h \
-	$(srcdir)/../../../include/mpu/mars/module.h \
-	$(srcdir)/../../../include/mpu/mars/mutex.h
+	$(srcdir)/../../../include/mpu/mars/module.h
 
 nodist_pkginclude_HEADERS = \
 	$(builddir)/../../../include/mpu/mars/base_features.h
@@ -96,5 +95,4 @@ lib_LTLIBRARIES = libmars_base.la
 libmars_base_la_SOURCES = \
 	$(srcdir)/../../../src/common/*.h \
 	dma.c \
-	module.c \
-	mutex.c
+	module.c
--- a/base/src/mpu/lib/module.c
+++ b/base/src/mpu/lib/module.c
@@ -162,6 +162,16 @@ void mars_module_workload_finish(void)
 	(*kernel_syscalls->workload_exit)(MARS_WORKLOAD_STATE_FINISHED);
 }
 
+int mars_module_mutex_lock_get(uint64_t mutex_ea, struct mars_mutex *mutex)
+{
+	return (*kernel_syscalls->mutex_lock_get)(mutex_ea, mutex);
+}
+
+int mars_module_mutex_unlock_put(uint64_t mutex_ea, struct mars_mutex *mutex)
+{
+	return (*kernel_syscalls->mutex_unlock_put)(mutex_ea, mutex);
+}
+
 int mars_module_host_signal_send(uint64_t watch_point_ea)
 {
 	return (*kernel_syscalls->host_signal_send)(watch_point_ea);
--- a/base/src/mpu/lib/mutex.c
+++ /dev/null
@@ -1,163 +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 <spu_mfcio.h>
-
-#include "config.h"
-
-#include "mars/error.h"
-#include "mars/mutex.h"
-
-static struct mars_mutex mutex_buffer;
-
-int mars_mutex_lock_get(uint64_t mutex_ea, struct mars_mutex *mutex)
-{
-	int status, mask, done = 0;
-	uint8_t id = 0;
-
-	/* check function params */
-	if (!mutex_ea)
-		return MARS_ERROR_NULL;
-	if (!mutex)
-		return MARS_ERROR_NULL;
-	if (mutex_ea & MARS_MUTEX_ALIGN_MASK)
-		return MARS_ERROR_ALIGN;
-	if ((uintptr_t)mutex & MARS_MUTEX_ALIGN_MASK)
-		return MARS_ERROR_ALIGN;
-
-	/* save event mask */
-	mask = spu_read_event_mask();
-
-	/* set event mask for the lost event */
-	spu_write_event_mask(MFC_LLR_LOST_EVENT);
-
-	/* update waiting state */
-	do {
-		mfc_getllar(mutex, mutex_ea, 0, 0);
-		mfc_read_atomic_status();
-
-		if (mutex->status.lock == MARS_MUTEX_UNLOCKED &&
-		    mutex->status.current_id == mutex->status.next_id) {
-			/* no other thread waiting for mutex so get lock now */
-			mutex->status.lock = MARS_MUTEX_LOCKED;
-			done = 1;
-		}
-		else {
-			/* otherwise update waiting state */
-			id = mutex->status.next_id++;
-			done = 0;
-		}
-
-		spu_dsync();
-		mfc_putllc(mutex, mutex_ea, 0, 0);
-		status = mfc_read_atomic_status() & MFC_PUTLLC_STATUS;
-	} while (status);
-
-	while (!done) {
-		mfc_getllar(mutex, mutex_ea, 0, 0);
-		mfc_read_atomic_status();
-
-		if (mutex->status.lock == MARS_MUTEX_LOCKED ||
-		    mutex->status.current_id != id) {
-			/* wait until mutex is released */
-			spu_read_event_status();
-			spu_write_event_ack(MFC_LLR_LOST_EVENT);
-		}
-		else {
-			/* get lock */
-			mutex->status.lock = MARS_MUTEX_LOCKED;
-			mutex->status.current_id++;
-
-			spu_dsync();
-			mfc_putllc(mutex, mutex_ea, 0, 0);
-			done = !(mfc_read_atomic_status() & MFC_PUTLLC_STATUS);
-		}
-	}
-
-	/* restore event mask */
-	spu_write_event_mask(mask);
-
-	/* clear any remnant lost event */
-	spu_write_event_ack(MFC_LLR_LOST_EVENT);
-
-	return MARS_SUCCESS;
-}
-
-int mars_mutex_unlock_put(uint64_t mutex_ea, struct mars_mutex *mutex)
-{
-	int status, mask;
-
-	/* check function params */
-	if (!mutex_ea)
-		return MARS_ERROR_NULL;
-	if (!mutex)
-		return MARS_ERROR_NULL;
-	if (mutex_ea & MARS_MUTEX_ALIGN_MASK)
-		return MARS_ERROR_ALIGN;
-	if ((uintptr_t)mutex & MARS_MUTEX_ALIGN_MASK)
-		return MARS_ERROR_ALIGN;
-	if (mutex->status.lock != MARS_MUTEX_LOCKED)
-		return MARS_ERROR_STATE;
-
-	mfc_sync(0);
-
-	/* save event mask */
-	mask = spu_read_event_mask();
-
-	/* set event mask for the lost event */
-	spu_write_event_mask(MFC_LLR_LOST_EVENT);
-
-	do {
-		mfc_getllar(&mutex_buffer, mutex_ea, 0, 0);
-		mfc_read_atomic_status();
-
-		mutex->status = mutex_buffer.status;
-		mutex->status.lock = MARS_MUTEX_UNLOCKED;
-
-		spu_dsync();
-		mfc_putllc(mutex, mutex_ea, 0, 0);
-		status = mfc_read_atomic_status() & MFC_PUTLLC_STATUS;
-	} while (status);
-
-	/* restore event mask */
-	spu_write_event_mask(mask);
-
-	/* clear any remnant lost event */
-	spu_write_event_ack(MFC_LLR_LOST_EVENT);
-
-	return MARS_SUCCESS;
-}





More information about the cbe-oss-dev mailing list