[Cbe-oss-dev] [PATCH 4/10 v3] MARS: task barrier fix notify

Yuji Mano Yuji.Mano at am.sony.com
Wed Sep 3 07:35:19 EST 2008


This fixes a bug in task barrier's notify function so it only sends a signal to
workload id's that are in the wait list.

This also fixes a bug where the barrier count was not being properly reset once
the barrier is released.

This also makes the notify function a blocking call that forces the task into
a wait state when not all task's have returned from waiting from the previous
barrier release.

A non-blocking notify routine is also provided.

Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>

---
v2:
 - fixed functionality of the barrier with the requirement that
   (total count == # of notify == # of wait calls)
 - reset barrier when all tasks have notified and waited
 - return error when # of notifies exceeds barrier total
v3:
 - change notify routine to block when not all tasks have completed waiting for
   previous barrier
 - add non-blocking routine (mars_task_barrier_try_notify)
 - update patch header

 include/common/mars/mars_task_barrier_types.h |    7 +
 include/mpu/mars/mars_task_barrier.h          |   18 +++-
 src/host/lib/mars_task_barrier.c              |    6 -
 src/mpu/lib/mars_task_barrier.c               |  112 ++++++++++++++++++++++----
 4 files changed, 123 insertions(+), 20 deletions(-)

--- a/include/common/mars/mars_task_barrier_types.h
+++ b/include/common/mars/mars_task_barrier_types.h
@@ -72,7 +72,7 @@ extern "C" {
  * \ingroup group_mars_task_barrier
  * \brief Maximum tasks allowed for single barrier
  */
-#define MARS_TASK_BARRIER_WAIT_MAX		53
+#define MARS_TASK_BARRIER_WAIT_MAX		25
 
 /**
  * \ingroup group_mars_task_barrier
@@ -88,7 +88,10 @@ extern "C" {
 struct mars_task_barrier {
 	uint32_t lock;
 	uint32_t total;
-	uint32_t count;
+	uint32_t notified_count;
+	uint32_t waited_count;
+	uint16_t notify_wait_count;
+	uint16_t notify_wait_id[MARS_TASK_BARRIER_WAIT_MAX];
 	uint16_t wait_count;
 	uint16_t wait_id[MARS_TASK_BARRIER_WAIT_MAX];
 	uint64_t mars_context_ea;
--- a/include/mpu/mars/mars_task_barrier.h
+++ b/include/mpu/mars/mars_task_barrier.h
@@ -66,19 +66,33 @@ int mars_task_barrier_initialize(uint64_
 
 /**
  * \ingroup group_mars_task_barrier
- * \brief [MPU] Notifies a task barrier.
+ * \brief [MPU] Notifies a task barrier. (Blocking)
  *
  * \param[in] barrier_ea	- ea of initialized barrier instance
  * \return
  *	MARS_SUCCESS		- successfully notified barrier
  * \n	MARS_ERROR_NULL		- ea is 0
  * \n	MARS_ERROR_ALIGN	- ea not properly aligned
- * \n	MARS_ERROR_LIMIT	- total notifications already received
+ * \n	MARS_ERROR_LIMIT	- maximum number of tasks already waiting
+ * \n	MARS_ERROR_FORMAT	- no context save area specified
  */
 int mars_task_barrier_notify(uint64_t barrier_ea);
 
 /**
  * \ingroup group_mars_task_barrier
+ * \brief [MPU] Notifies a task barrier. (Non-Blocking)
+ *
+ * \param[in] barrier_ea	- ea of initialized barrier instance
+ * \return
+ *	MARS_SUCCESS		- successfully notified barrier
+ * \n	MARS_ERROR_NULL		- ea is 0
+ * \n	MARS_ERROR_ALIGN	- ea not properly aligned
+ * \n	MARS_ERROR_BUSY		- previous waits have not completed
+ */
+int mars_task_barrier_try_notify(uint64_t barrier_ea);
+
+/**
+ * \ingroup group_mars_task_barrier
  * \brief [MPU] Waits on a task barrier. (Blocking)
  *
  * \param[in] barrier_ea	- ea of initialized barrier instance
--- a/src/host/lib/mars_task_barrier.c
+++ b/src/host/lib/mars_task_barrier.c
@@ -50,14 +50,14 @@ int mars_task_barrier_initialize(struct 
 			== 0, MARS_ERROR_ALIGN);
 	MARS_CHECK_RET(total <= MARS_TASK_BARRIER_WAIT_MAX, MARS_ERROR_PARAMS);
 
-	int i;
-
 	mars_mutex_initialize((struct mars_mutex *)barrier);
 	mars_mutex_lock((struct mars_mutex *)barrier);
 
 	barrier->mars_context_ea = (uint64_t)(uintptr_t)mars;
 	barrier->total = total;
-	barrier->count = 0;
+	barrier->notified_count = 0;
+	barrier->waited_count = 0;
+	barrier->notify_wait_count = 0;
 	barrier->wait_count = 0;
 
 	mars_mutex_unlock((struct mars_mutex *)barrier);
--- a/src/mpu/lib/mars_task_barrier.c
+++ b/src/mpu/lib/mars_task_barrier.c
@@ -56,7 +56,9 @@ int mars_task_barrier_initialize(uint64_
 
 	barrier.mars_context_ea = mars_get_mars_context_ea();
 	barrier.total = total;
-	barrier.count = 0;
+	barrier.notified_count = 0;
+	barrier.waited_count = 0;
+	barrier.notify_wait_count = 0;
 	barrier.wait_count = 0;
 
 	mars_mutex_unlock_put(barrier_ea, (struct mars_mutex *)&barrier);
@@ -71,19 +73,73 @@ int mars_task_barrier_notify(uint64_t ba
 			MARS_ERROR_ALIGN);
 
 	int i;
+	struct mars_task_context *task;
+
+	task = (struct mars_task_context *)mars_get_workload_context();
+
+	/* make sure task context has a context save area */
+	MARS_CHECK_RET(task->context_save_size && task->context_save_area,
+			MARS_ERROR_FORMAT);
 
 	mars_mutex_lock_get(barrier_ea, (struct mars_mutex *)&barrier);
 
-	/* set the necessary bits */
-	barrier.count++;
+	/* previous barrier wait not complete so wait */
+	if (barrier.notified_count == barrier.total) {
+		/* add id to wait list */
+		barrier.notify_wait_id[barrier.notify_wait_count] =
+			mars_get_workload_id();
+		barrier.notify_wait_count++;
+
+		mars_mutex_unlock_put(barrier_ea,
+				(struct mars_mutex *)&barrier);
+
+		/* wait for signal */
+		mars_signal_wait();
+
+		mars_mutex_lock_get(barrier_ea, (struct mars_mutex *)&barrier);
+	}
 
-	/* barrier count reached total so release barrier */
-	if (barrier.count == barrier.total) {
+	/* increment notified count */
+	barrier.notified_count++;
+
+	/* notified count reached total so release barrier */
+	if (barrier.notified_count == barrier.total) {
 		/* signal all task ids in wait list */
-		for (i = 0; i < barrier.total; i++)
+		for (i = 0; i < barrier.wait_count; i++)
 			mars_signal_send(barrier.wait_id[i]);
+		barrier.wait_count = 0;
+	}
+
+	mars_mutex_unlock_put(barrier_ea, (struct mars_mutex *)&barrier);
+
+	return MARS_SUCCESS;
+}
+
+int mars_task_barrier_try_notify(uint64_t barrier_ea)
+{
+	MARS_CHECK_RET(barrier_ea, MARS_ERROR_NULL);
+	MARS_CHECK_RET((barrier_ea & MARS_TASK_BARRIER_ALIGN_MASK) == 0,
+			MARS_ERROR_ALIGN);
+
+	int i;
+
+	mars_mutex_lock_get(barrier_ea, (struct mars_mutex *)&barrier);
+
+	/* previous barrier wait not complete so return busy */
+	if (barrier.notified_count == barrier.total) {
+		mars_mutex_unlock_put(barrier_ea,
+				(struct mars_mutex *)&barrier);
+		return MARS_ERROR_BUSY;
+	}
 
-		/* flush wait list */
+	/* increment notified count */
+	barrier.notified_count++;
+
+	/* notified count reached total so release barrier */
+	if (barrier.notified_count == barrier.total) {
+		/* signal all task ids in wait list */
+		for (i = 0; i < barrier.wait_count; i++)
+			mars_signal_send(barrier.wait_id[i]);
 		barrier.wait_count = 0;
 	}
 
@@ -98,6 +154,7 @@ int mars_task_barrier_wait(uint64_t barr
 	MARS_CHECK_RET((barrier_ea & MARS_TASK_BARRIER_ALIGN_MASK) == 0,
 			MARS_ERROR_ALIGN);
 
+	int i;
 	struct mars_task_context *task;
 
 	task = (struct mars_task_context *)mars_get_workload_context();
@@ -109,16 +166,15 @@ int mars_task_barrier_wait(uint64_t barr
 	mars_mutex_lock_get(barrier_ea, (struct mars_mutex *)&barrier);
 
 	/* check if barrier wait limit reached */
-	MARS_CHECK_CLEANUP_RET(barrier.wait_count < MARS_TASK_BARRIER_WAIT_MAX,
+	MARS_CHECK_CLEANUP_RET(barrier.wait_count < barrier.total,
 		mars_mutex_unlock_put(barrier_ea,
 				(struct mars_mutex *)&barrier),
 		MARS_ERROR_LIMIT);
 
 	/* not all tasks notified barrier so need to wait */
-	if (barrier.count != barrier.total) {
+	if (barrier.notified_count != barrier.total) {
 		/* add id to wait list */
-		barrier.wait_id[barrier.wait_count] =
-			mars_get_workload_id();
+		barrier.wait_id[barrier.wait_count] = mars_get_workload_id();
 		barrier.wait_count++;
 
 		mars_mutex_unlock_put(barrier_ea,
@@ -127,7 +183,21 @@ int mars_task_barrier_wait(uint64_t barr
 		/* wait for signal */
 		mars_signal_wait();
 
-		return MARS_SUCCESS;
+		mars_mutex_lock_get(barrier_ea, (struct mars_mutex *)&barrier);
+	}
+
+	/* increment waited count */
+	barrier.waited_count++;
+
+	/* all tasks have called wait so reset barrier */
+	if (barrier.waited_count == barrier.total) {
+		barrier.notified_count = 0;
+		barrier.waited_count = 0;
+
+		/* signal all task ids in notify wait list */
+		for (i = 0; i < barrier.notify_wait_count; i++)
+			mars_signal_send(barrier.notify_wait_id[i]);
+		barrier.notify_wait_count = 0;
 	}
 
 	mars_mutex_unlock_put(barrier_ea, (struct mars_mutex *)&barrier);
@@ -141,15 +211,31 @@ int mars_task_barrier_try_wait(uint64_t 
 	MARS_CHECK_RET((barrier_ea & MARS_TASK_BARRIER_ALIGN_MASK) == 0,
 			MARS_ERROR_ALIGN);
 
+	int i;
+
 	mars_mutex_lock_get(barrier_ea, (struct mars_mutex *)&barrier);
 
 	/* not all tasks notified barrier so return busy */
-	if (barrier.count != barrier.total) {
+	if (barrier.notified_count != barrier.total) {
 		mars_mutex_unlock_put(barrier_ea,
 				(struct mars_mutex *)&barrier);
 		return MARS_ERROR_BUSY;
 	}
 
+	/* increment waited count */
+	barrier.waited_count++;
+
+	/* all tasks have called wait so reset barrier */
+	if (barrier.waited_count == barrier.total) {
+		barrier.notified_count = 0;
+		barrier.waited_count = 0;
+
+		/* signal all task ids in notify wait list */
+		for (i = 0; i < barrier.notify_wait_count; i++)
+			mars_signal_send(barrier.notify_wait_id[i]);
+		barrier.notify_wait_count = 0;
+	}
+
 	mars_mutex_unlock_put(barrier_ea, (struct mars_mutex *)&barrier);
 
 	return MARS_SUCCESS;





More information about the cbe-oss-dev mailing list