[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