diff options
author | Kazunori Asayama <asayama@sm.sony.co.jp> | 2009-03-13 18:18:07 -0700 |
---|---|---|
committer | Yuji Mano <yuji.mano@am.sony.com> | 2009-03-17 10:58:15 -0700 |
commit | e1a811432bb398258ea2c7d71b5dc24be71cadac (patch) | |
tree | 53e9d1765e021a92da33a48df99d47060076c3f3 | |
parent | f432a71298e538ed4cd11ee1348ee0d92638f03c (diff) | |
download | mars-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.c | 51 |
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; } |