aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazunori Asayama <asayama@sm.sony.co.jp>2009-03-13 18:18:07 -0700
committerYuji Mano <yuji.mano@am.sony.com>2009-03-17 10:58:15 -0700
commite1a811432bb398258ea2c7d71b5dc24be71cadac (patch)
tree53e9d1765e021a92da33a48df99d47060076c3f3
parentf432a71298e538ed4cd11ee1348ee0d92638f03c (diff)
downloadmars-src-e1a811432bb398258ea2c7d71b5dc24be71cadac.tar.gz
base: Avoid host mutex contention
Avoid host mutex contention This patch avoids mutex contention on host side by using waiting queue. Signed-off-by: Kazunori Asayama <asayama@sm.sony.co.jp> Signed-off-by: Yuji Mano <yuji.mano@am.sony.com>
-rw-r--r--base/src/host/lib/mutex_cell.c51
1 files changed, 35 insertions, 16 deletions
diff --git a/base/src/host/lib/mutex_cell.c b/base/src/host/lib/mutex_cell.c
index fd0170c..c1daa4e 100644
--- a/base/src/host/lib/mutex_cell.c
+++ b/base/src/host/lib/mutex_cell.c
@@ -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;
}