[Cbe-oss-dev] [PATCH 2/2]MARS/base: host signal fix
Yuji Mano
yuji.mano at am.sony.com
Wed Feb 18 09:56:05 EST 2009
From: Kazunori Asayama <asayama at sm.sony.co.jp>
Avoid futex_wake on invalid address
This patch modifies host signal implementation so futex_wake is called
only on valid address.
Signed-off-by: Kazunori Asayama <asayama at sm.sony.co.jp>
Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>
---
base/src/host/lib/cond_cell.c | 87 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 79 insertions(+), 8 deletions(-)
--- a/base/src/host/lib/cond_cell.c
+++ b/base/src/host/lib/cond_cell.c
@@ -44,14 +44,19 @@
#include "mars/base.h"
#include "mars/error.h"
-#define SPIN_MAX 50
-
#ifdef ENABLE_COND_WAIT_FUTEX
+#include <pthread.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/futex.h>
+#define FUTEX_WATCH_POINT_MAX 256
+
+static pthread_mutex_t futex_watch_point_lock = PTHREAD_MUTEX_INITIALIZER;
+static uint64_t futex_watch_point_ea[FUTEX_WATCH_POINT_MAX];
+static int futex_watch_point_count;
+
static int futex_wait(void *ptr, int val)
{
int ret;
@@ -74,6 +79,56 @@ static int futex_wake(void *ptr, int val
return MARS_SUCCESS;
}
+static int watch_point_register(uint64_t ea)
+{
+ int i;
+
+ pthread_mutex_lock(&futex_watch_point_lock);
+
+ if (futex_watch_point_count >= FUTEX_WATCH_POINT_MAX) {
+ pthread_mutex_unlock(&futex_watch_point_lock);
+ return -1;
+ }
+
+ for (i = 0; i < FUTEX_WATCH_POINT_MAX; i++) {
+ if (!futex_watch_point_ea[i]) {
+ futex_watch_point_ea[i] = ea;
+ futex_watch_point_count++;
+ break;
+ }
+ }
+
+ pthread_mutex_unlock(&futex_watch_point_lock);
+
+ return i;
+}
+
+static void watch_point_unregister(int index)
+{
+ pthread_mutex_lock(&futex_watch_point_lock);
+
+ futex_watch_point_ea[index] = 0;
+ futex_watch_point_count--;
+
+ pthread_mutex_unlock(&futex_watch_point_lock);
+}
+
+static int is_watch_point(uint64_t ea)
+{
+ int i;
+ int valid = 0;
+
+ for (i = 0; i < FUTEX_WATCH_POINT_MAX; i++) {
+ if (futex_watch_point_ea[i] == ea)
+ return 1;
+ else if (futex_watch_point_ea[i] &&
+ futex_watch_point_count == ++valid)
+ break;
+ }
+
+ return 0;
+}
+
#endif
int mars_ea_cond_wait(uint64_t watch_point_ea,
@@ -81,17 +136,24 @@ int mars_ea_cond_wait(uint64_t watch_poi
void *test_cond_param)
{
int ret;
- int spin = 0;
+ int index = -1;
while (1) {
- uint32_t val = mars_ea_get_uint32(watch_point_ea);
+ uint32_t val;
+
+#ifdef ENABLE_COND_WAIT_FUTEX
+ if (index < 0)
+ index = watch_point_register(watch_point_ea);
+#endif
+
+ val = mars_ea_get_uint32(watch_point_ea);
ret = (*test_cond)(val, test_cond_param);
if (ret >= 0)
break;
#ifdef ENABLE_COND_WAIT_FUTEX
- if (spin >= SPIN_MAX) {
+ if (index >= 0) {
ret = futex_wait(mars_ea_to_ptr(watch_point_ea), val);
if (ret != MARS_SUCCESS)
break;
@@ -100,18 +162,27 @@ int mars_ea_cond_wait(uint64_t watch_poi
#endif
{
sched_yield();
- spin++;
}
}
+#ifdef ENABLE_COND_WAIT_FUTEX
+ if (index >= 0)
+ watch_point_unregister(index);
+#endif
+
return ret;
}
int mars_ea_cond_signal(uint64_t watch_point_ea, int broadcast)
{
#ifdef ENABLE_COND_WAIT_FUTEX
- futex_wake(mars_ea_to_ptr(watch_point_ea),
- broadcast ? INT_MAX : 1);
+ pthread_mutex_lock(&futex_watch_point_lock);
+
+ if (is_watch_point(watch_point_ea))
+ futex_wake(mars_ea_to_ptr(watch_point_ea),
+ broadcast ? INT_MAX : 1);
+
+ pthread_mutex_unlock(&futex_watch_point_lock);
#endif
return MARS_SUCCESS;
More information about the cbe-oss-dev
mailing list