[Cbe-oss-dev] [PATCH 2/2]MARS/task: futex signal fix

Yuji Mano yuji.mano at am.sony.com
Fri Feb 13 13:53:55 EST 2009


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

Fix timing of signaling host

The current task queue and event flag implementation signal to host
before actually changing status of the objects. Such behavior can
cause deadlock in waiting futex.

Signed-off-by: Kazunori Asayama <asayama at sm.sony.co.jp>
Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>
---
 task/src/mpu/lib/task_event_flag.c |   12 ++---
 task/src/mpu/lib/task_queue.c      |   87 ++++++++++++++++++++++++++-----------
 2 files changed, 69 insertions(+), 30 deletions(-)

--- a/task/src/mpu/lib/task_event_flag.c
+++ b/task/src/mpu/lib/task_event_flag.c
@@ -95,12 +95,6 @@ int mars_task_event_flag_set(uint64_t ev
 	/* save current set bits */
 	bits = event_flag.bits;
 
-	/* signal the waiting host */
-	if (event_flag.direction != MARS_TASK_EVENT_FLAG_HOST_TO_MPU &&
-	    event_flag.direction != MARS_TASK_EVENT_FLAG_MPU_TO_MPU)
-		mars_task_module_signal_host(event_flag_ea +
-			offsetof(struct mars_task_event_flag, bits));
-
 	/* search through wait list for tasks to be signalled */
 	for (i = 0; i < event_flag.wait_count; i++) {
 		/* check condition based on wait mode */
@@ -135,6 +129,12 @@ int mars_task_event_flag_set(uint64_t ev
 
 	mars_mutex_unlock_put(event_flag_ea, (struct mars_mutex *)&event_flag);
 
+	/* signal the waiting host */
+	if (event_flag.direction != MARS_TASK_EVENT_FLAG_HOST_TO_MPU &&
+	    event_flag.direction != MARS_TASK_EVENT_FLAG_MPU_TO_MPU)
+		mars_task_module_signal_host(event_flag_ea +
+			offsetof(struct mars_task_event_flag, bits));
+
 	return MARS_SUCCESS;
 }
 
--- a/task/src/mpu/lib/task_queue.c
+++ b/task/src/mpu/lib/task_queue.c
@@ -74,6 +74,7 @@ int mars_task_queue_count(uint64_t queue
 int mars_task_queue_clear(uint64_t queue_ea)
 {
 	int i;
+	int signal_host;
 
 	/* check function params */
 	if (!queue_ea)
@@ -83,12 +84,11 @@ int mars_task_queue_clear(uint64_t queue
 
 	mars_mutex_lock_get(queue_ea, (struct mars_mutex *)&queue);
 
-	/* signal the waiting host */
-	if (queue.count == queue.depth &&
-	    queue.direction != MARS_TASK_QUEUE_MPU_TO_HOST &&
-	    queue.direction != MARS_TASK_QUEUE_MPU_TO_MPU)
-		mars_task_module_signal_host(queue_ea +
-			offsetof(struct mars_task_queue, count));
+	/* whether signal the waiting host */
+	signal_host =
+		(queue.count == queue.depth &&
+		 queue.direction != MARS_TASK_QUEUE_MPU_TO_HOST &&
+		 queue.direction != MARS_TASK_QUEUE_MPU_TO_MPU);
 
 	/* signal all waiting tasks that queue is ready for push */
 	for (i = 0; i < queue.push_wait_count; i++)
@@ -104,17 +104,23 @@ int mars_task_queue_clear(uint64_t queue
 
 	mars_mutex_unlock_put(queue_ea, (struct mars_mutex *)&queue);
 
+	/* signal the waiting host */
+	if (signal_host)
+		mars_task_module_signal_host(
+			queue_ea + offsetof(struct mars_task_queue, count));
+
 	return MARS_SUCCESS;
 }
 
-static void push_update(uint64_t queue_ea)
+static int push_update(void)
 {
-	/* signal the waiting host */
-	if (queue.count == 0 &&
-	    queue.direction != MARS_TASK_QUEUE_HOST_TO_MPU &&
-	    queue.direction != MARS_TASK_QUEUE_MPU_TO_MPU)
-		mars_task_module_signal_host(queue_ea +
-			offsetof(struct mars_task_queue, count));
+	int signal_host;
+
+	/* whether signal the waiting host */
+	signal_host =
+		(queue.count == 0 &&
+		 queue.direction != MARS_TASK_QUEUE_HOST_TO_MPU &&
+		 queue.direction != MARS_TASK_QUEUE_MPU_TO_MPU);
 
 	/* signal waiting task that queue is ready for pop */
 	if (queue.pop_wait_count) {
@@ -137,12 +143,15 @@ static void push_update(uint64_t queue_e
 	/* wrap to front of queue if necessary */
 	if (queue.push_ea == queue.buffer_ea + (queue.size * queue.depth))
 		queue.push_ea = queue.buffer_ea;
+
+	return signal_host;
 }
 
 static int push(uint64_t queue_ea, const void *data,
 		int try, int begin, uint32_t tag)
 {
 	struct mars_task_context *task;
+	int signal_host;
 
 	/* check function params */
 	if (!queue_ea)
@@ -210,10 +219,15 @@ static int push(uint64_t queue_ea, const
 	mars_dma_wait(tag);
 
 	/* update queue data */
-	push_update(queue_ea);
+	signal_host = push_update();
 
 	mars_mutex_unlock_put(queue_ea, (struct mars_mutex *)&queue);
 
+	/* signal the waiting host */
+	if (signal_host)
+		mars_task_module_signal_host(
+			queue_ea + offsetof(struct mars_task_queue, count));
+
 	return MARS_SUCCESS;
 }
 
@@ -230,6 +244,8 @@ int mars_task_queue_push_begin(uint64_t 
 
 int mars_task_queue_push_end(uint64_t queue_ea, uint32_t tag)
 {
+	int signal_host;
+
 	/* check function params */
 	if (!queue_ea)
 		return MARS_ERROR_NULL;
@@ -242,10 +258,15 @@ int mars_task_queue_push_end(uint64_t qu
 	mars_dma_wait(tag);
 
 	/* update queue data */
-	push_update(queue_ea);
+	signal_host = push_update();
 
 	mars_mutex_unlock_put(queue_ea, (struct mars_mutex *)&queue);
 
+	/* signal the waiting host */
+	if (signal_host)
+		mars_task_module_signal_host(
+			queue_ea + offsetof(struct mars_task_queue, count));
+
 	return MARS_SUCCESS;
 }
 
@@ -260,14 +281,15 @@ int mars_task_queue_try_push_begin(uint6
 	return push(queue_ea, data, 1, 1, tag);
 }
 
-static void pop_update(uint64_t queue_ea)
+static int pop_update(void)
 {
-	/* signal the waiting host */
-	if (queue.count == queue.depth &&
-	    queue.direction != MARS_TASK_QUEUE_MPU_TO_HOST &&
-	    queue.direction != MARS_TASK_QUEUE_MPU_TO_MPU)
-		mars_task_module_signal_host(queue_ea +
-			offsetof(struct mars_task_queue, count));
+	int signal_host;
+
+	/* whether signal the waiting host */
+	signal_host =
+		(queue.count == queue.depth &&
+		 queue.direction != MARS_TASK_QUEUE_MPU_TO_HOST &&
+		 queue.direction != MARS_TASK_QUEUE_MPU_TO_MPU);
 
 	/* signal waiting task that queue is ready for push */
 	if (queue.push_wait_count) {
@@ -290,12 +312,15 @@ static void pop_update(uint64_t queue_ea
 	/* wrap to front of queue if necessary */
 	if (queue.pop_ea == queue.buffer_ea + (queue.size * queue.depth))
 		queue.pop_ea = queue.buffer_ea;
+
+	return signal_host;
 }
 
 static int pop(uint64_t queue_ea, void *data,
 	       int peek, int try, int begin, uint32_t tag)
 {
 	struct mars_task_context *task;
+	int signal_host;
 
 	/* check function params */
 	if (!queue_ea)
@@ -363,10 +388,17 @@ static int pop(uint64_t queue_ea, void *
 
 	/* update queue data only if this is not a peek operation */
 	if (!peek)
-		pop_update(queue_ea);
+		signal_host = pop_update();
+	else
+		signal_host = 0;
 
 	mars_mutex_unlock_put(queue_ea, (struct mars_mutex *)&queue);
 
+	/* signal the waiting host */
+	if (signal_host)
+		mars_task_module_signal_host(
+			queue_ea + offsetof(struct mars_task_queue, count));
+
 	return MARS_SUCCESS;
 }
 
@@ -382,6 +414,8 @@ int mars_task_queue_pop_begin(uint64_t q
 
 int mars_task_queue_pop_end(uint64_t queue_ea, uint32_t tag)
 {
+	int signal_host;
+
 	/* check function params */
 	if (!queue_ea)
 		return MARS_ERROR_NULL;
@@ -394,10 +428,15 @@ int mars_task_queue_pop_end(uint64_t que
 	mars_dma_wait(tag);
 
 	/* update queue data */
-	pop_update(queue_ea);
+	signal_host = pop_update();
 
 	mars_mutex_unlock_put(queue_ea, (struct mars_mutex *)&queue);
 
+	/* signal the waiting host */
+	if (signal_host)
+		mars_task_module_signal_host(
+			queue_ea + offsetof(struct mars_task_queue, count));
+
 	return MARS_SUCCESS;
 }
 






More information about the cbe-oss-dev mailing list