aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazunori Asayama <asayama@sm.sony.co.jp>2009-02-12 18:53:55 -0800
committerYuji Mano <yuji.mano@am.sony.com>2009-02-17 14:39:14 -0800
commit267d7be97d54d25472b9e55b64eff699f32b2421 (patch)
treea3e8e70b3e16e5f1a445ba0c0e48f7c279f81b7b
parent5d5e2a729fd1cb4d6e4773d2ede235caabeff4ed (diff)
downloadmars-src-267d7be97d54d25472b9e55b64eff699f32b2421.tar.gz
task: futex signal fix
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@sm.sony.co.jp> Signed-off-by: Yuji Mano <yuji.mano@am.sony.com>
-rw-r--r--task/src/mpu/lib/task_event_flag.c12
-rw-r--r--task/src/mpu/lib/task_queue.c87
2 files changed, 69 insertions, 30 deletions
diff --git a/task/src/mpu/lib/task_event_flag.c b/task/src/mpu/lib/task_event_flag.c
index fb528a9..1de2675 100644
--- 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 event_flag_ea, uint32_t bits)
/* 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 event_flag_ea, uint32_t bits)
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;
}
diff --git a/task/src/mpu/lib/task_queue.c b/task/src/mpu/lib/task_queue.c
index 58cb0ba..68cd001 100644
--- 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_ea, uint32_t *count)
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_ea)
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_ea)
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_ea)
/* 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 void *data,
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 queue_ea, const void *data,
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 queue_ea, uint32_t tag)
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(uint64_t queue_ea, const void *data,
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 *data,
/* 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 queue_ea, void *data, uint32_t tag)
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 queue_ea, uint32_t tag)
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;
}