[Cbe-oss-dev] [PATCH 13/28]MARS/base: kernel scheduler idle wait

Yuji Mano yuji.mano at am.sony.com
Fri Feb 6 13:31:37 EST 2009


This adds a scheduler_idle_wait() function in the kernel which gets called
when the scheduler() function returns MARS_KERNEL_STATUS_IDLE.

The scheduler_idle_wait() function loads the queue header with reservation and
compares against queue header that was used when searching for a schedulable
workload. If the queue header state has not changed since the scheduler search,
the function will wait until receiving a reservation lost event when some other
entity modifies the queue header. If the queue header state has changed since
the scheduler search, the function will return immediately so the kernel
scheduler can search for a schedulable workload again.

Any time the queue header is accessed (locked/unlocked) it is guaranteed that
there is some workload state change. However this does not guarantee the
contents of the queue header to be modified. In order to avoid missing
notifications of any workload state changes, an extra member 'access' is added
to the queue header that is incremented any time the queue header is accessed.
This way, even if the rest of queue header is not changed, the 'access' member
will have changed causing the memcmp to fail when there has been some change in
workload states.

Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>
---
 base/src/common/workload_internal_types.h |    2 -
 base/src/host/lib/workload_queue.c        |   11 +++++++++
 base/src/mpu/kernel/kernel.c              |   34 ++++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+), 1 deletion(-)

--- a/base/src/common/workload_internal_types.h
+++ b/base/src/common/workload_internal_types.h
@@ -139,7 +139,7 @@
 /* 128 byte workload queue header structure */
 struct mars_workload_queue_header {
 	uint32_t lock;
-	uint32_t pad;
+	uint32_t access;
 	uint64_t queue_ea;
 	uint64_t context_ea;
 	uint32_t flag;
--- a/base/src/host/lib/workload_queue.c
+++ b/base/src/host/lib/workload_queue.c
@@ -478,6 +478,8 @@ static void update_header_bits(struct ma
 	uint64_t block_ea;
 	uint64_t header_bits_ea;
 	uint16_t header_bits;
+	uint64_t header_access_ea;
+	uint32_t header_access;
 	uint8_t block_ready = MARS_WORKLOAD_BLOCK_READY_OFF;
 	uint8_t block_waiting = MARS_WORKLOAD_BLOCK_WAITING_OFF;
 	uint8_t block_priority = MARS_WORKLOAD_BLOCK_PRIORITY_MIN;
@@ -524,6 +526,15 @@ static void update_header_bits(struct ma
 
 	mars_ea_put_uint16(header_bits_ea, header_bits);
 
+	/* increment the header access value */
+	header_access_ea = queue_ea +
+			   offsetof(struct mars_workload_queue_header, access);
+	header_access = mars_ea_get_uint32(header_access_ea);
+
+	header_access++;
+
+	mars_ea_put_uint32(header_access_ea, header_access);
+
 	/* unlock the queue header */
 	mars_mutex_unlock(queue_ea);
 }
--- a/base/src/mpu/kernel/kernel.c
+++ b/base/src/mpu/kernel/kernel.c
@@ -254,6 +254,9 @@ static void update_header_bits(int block
 	MARS_BITS_SET(block_bits, BLOCK_WAITING, block_waiting);
 	MARS_BITS_SET(block_bits, BLOCK_PRIORITY, block_priority);
 
+	/* increment the header access value */
+	queue_header.access++;
+
 	/* unlock the queue header */
 	mars_mutex_unlock_put(kernel_params.workload_queue_ea,
 			      (struct mars_mutex *)&queue_header);
@@ -818,6 +821,36 @@ static int scheduler(void)
 	return status;
 }
 
+static void scheduler_idle_wait(void)
+{
+	int mask;
+	struct mars_workload_queue_header cur_queue_header;
+
+	/* save event mask */
+	mask = spu_read_event_mask();
+
+	/* set event mask for the lost event */
+	spu_write_event_mask(MFC_LLR_LOST_EVENT);
+
+	/* get current atomic state of queue header */
+	mfc_getllar(&cur_queue_header, kernel_params.workload_queue_ea, 0, 0);
+	mfc_read_atomic_status();
+
+	/* check if queue header has been modified since we last fetched it */
+	if (!kernel_memcmp(&queue_header, &cur_queue_header,
+			   sizeof(struct mars_workload_queue_header))) {
+		/* wait until queue header is modified */
+		spu_read_event_status();
+		spu_write_event_ack(MFC_LLR_LOST_EVENT);
+	}
+
+	/* restore event mask */
+	spu_write_event_mask(mask);
+
+	/* clear any remnant lost event */
+	spu_write_event_ack(MFC_LLR_LOST_EVENT);
+}
+
 static void get_params(uint64_t kernel_params_ea)
 {
 	int mask;
@@ -886,6 +919,7 @@ int main(unsigned long long mpu_context_
 		case MARS_KERNEL_STATUS_BUSY:
 			break;
 		case MARS_KERNEL_STATUS_IDLE:
+			scheduler_idle_wait();
 			break;
 		case MARS_KERNEL_STATUS_EXIT:
 			exit_flag = 1;







More information about the cbe-oss-dev mailing list