[Cbe-oss-dev] [PATCH 02/23]MARS/base: avoid host mutex contention

Yuji Mano yuji.mano at am.sony.com
Sat Mar 14 12:18:07 EST 2009


From: Kazunori Asayama <asayama at sm.sony.co.jp>

Avoid host mutex contention

This patch avoids mutex contention on host side by using waiting
queue.

Signed-off-by: Kazunori Asayama <asayama at sm.sony.co.jp>
---
 base/src/host/lib/mutex_cell.c |   51 ++++++++++++++++++++++++++++-------------
 1 file changed, 35 insertions(+), 16 deletions(-)

Index: b/base/src/host/lib/mutex_cell.c
===================================================================
--- a/base/src/host/lib/mutex_cell.c	2009-02-19 22:40:34.000000000 +0900
+++ b/base/src/host/lib/mutex_cell.c	2009-02-20 12:02:13.000000000 +0900
@@ -36,6 +36,7 @@
  */
 
 #include <ppu_intrinsics.h>
+#include <unistd.h>
 
 #include "config.h"
 
@@ -43,6 +44,11 @@
 #include "mars/error.h"
 #include "mars/mutex.h"
 
+union mars_mutex_header {
+	struct mars_mutex_status status;
+	uint32_t bits;
+};
+
 static void init_status(struct mars_mutex_status *status)
 {
 	status->lock = MARS_MUTEX_UNLOCKED;
@@ -99,21 +105,37 @@ int mars_mutex_reset(uint64_t mutex_ea)
 int mars_mutex_lock(uint64_t mutex_ea)
 {
 	struct mars_mutex *mutex = mars_ea_to_ptr(mutex_ea);
-	struct mars_mutex_status status;
-	uint32_t value;
+	union mars_mutex_header header;
+	uint8_t id;
+	int retry;
 
 	if (!mutex_ea) {
 		return MARS_ERROR_NULL;
 	}
 
 	do {
-		do {
-			value = __lwarx(&mutex->status);
-			status = *(struct mars_mutex_status *)&value;
-		} while (status.lock == MARS_MUTEX_LOCKED);
-		status.lock = MARS_MUTEX_LOCKED;
-		value = *(uint32_t *)&status;
-	} while (!__stwcx(&mutex->status, value));
+		header.bits = __lwarx(&mutex->status);
+
+		/* get my id */
+		id = header.status.next_id++;
+	} while (!__stwcx(&mutex->status, header.bits));
+
+	do {
+		header.bits = __lwarx(&mutex->status);
+
+		if (header.status.lock == MARS_MUTEX_LOCKED ||
+		    header.status.current_id != id) {
+			/* wait until mutex is released */
+			usleep(1);
+			retry = 1;
+		}
+		else {
+			/* get lock */
+			header.status.lock = MARS_MUTEX_LOCKED;
+			header.status.current_id++;
+			retry = !__stwcx(&mutex->status, header.bits);
+		}
+	} while (retry);
 
 	__isync();
 
@@ -123,8 +145,7 @@ int mars_mutex_lock(uint64_t mutex_ea)
 int mars_mutex_unlock(uint64_t mutex_ea)
 {
 	struct mars_mutex *mutex = mars_ea_to_ptr(mutex_ea);
-	struct mars_mutex_status status;
-	uint32_t value;
+	union mars_mutex_header header;
 
 	if (!mutex_ea)
 		return MARS_ERROR_NULL;
@@ -134,11 +155,9 @@ int mars_mutex_unlock(uint64_t mutex_ea)
 	__lwsync();
 
 	do {
-		value = __lwarx(&mutex->status);
-		status = *(struct mars_mutex_status *)&value;
-		status.lock = MARS_MUTEX_UNLOCKED;
-		value = *(uint32_t *)&status;
-	} while (!__stwcx(&mutex->status, value));
+		header.bits = __lwarx(&mutex->status);
+		header.status.lock = MARS_MUTEX_UNLOCKED;
+	} while (!__stwcx(&mutex->status, header.bits));
 
 	return MARS_SUCCESS;
 }






More information about the cbe-oss-dev mailing list