[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