[Cbe-oss-dev] [PATCH 1/2]MARS/core: Tick counter api

Yuji Mano yuji.mano at am.sony.com
Fri Nov 21 12:44:10 EST 2008


[RFC] MARS tick counter API

* Background

  When measuring performance or logging, we can use the time base
  counter register on host side and decrementer on MPU side.

  However, because they are not synchronized, it is impossible to
  measure time across MPU-host and/or MPU-MPU. That means, for
  example, if a MARS task is scheduled out from an MPU then scheduled
  in another MPU, the value returned by spu_read_decrementer() is no
  longer reliable.

* Solution

  To solve the problem, I propose to introduce a new API function
  'mars_tick_get()' to get the current value of tick counters which
  are *approximately* synchronized between host and MPUs.

      [host and MPU]  uint32_t mars_tick_get(void);

         Returns tick counter's value. Counter's frequency depends on
         runtime environment.

Here is a sample implementation. Any comments, improvements and/or 
alternative solutions are appreciated.


Signed-off-by: Kazunori Asayama <asayama at sm.sony.co.jp>
Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>

---
 core/include/host/mars/core.h           |   11 ++++++
 core/include/mpu/mars/core.h            |   15 ++++++++
 core/src/common/kernel_internal_types.h |   13 ++++++-
 core/src/host/lib/context.c             |   31 ++++++++++++++++--
 core/src/mpu/kernel/kernel.c            |   55 ++++++++++++++++++++++++++++++--
 core/src/mpu/kernel/kernel.h            |    1 
 core/src/mpu/kernel/kernel_syscalls.c   |    8 ++++
 core/src/mpu/lib/syscalls.c             |    5 ++
 core/src/mpu/lib/syscalls.h             |    2 +
 doxygen/src/doxygen                     |    5 ++
 10 files changed, 138 insertions(+), 8 deletions(-)

--- a/core/include/host/mars/core.h
+++ b/core/include/host/mars/core.h
@@ -76,6 +76,17 @@ static inline uint64_t mars_ptr_to_ea(co
 	return (uint64_t)(const uintptr_t)ptr;
 }
 
+/**
+ * \ingroup group_mars_core
+ * \brief <b>[host/MPU]</b> Returns tick counter value.
+ *
+ * \note Counter's frequency depends on runtime environment.
+ *
+ * \return
+ *	uint32_t		- 32-bit tick counter value
+ */
+uint32_t mars_get_ticks(void);
+
 #if defined(__cplusplus)
 }
 #endif
--- a/core/include/mpu/mars/core.h
+++ b/core/include/mpu/mars/core.h
@@ -44,4 +44,19 @@
  * \brief <b>[MPU]</b> MARS Core API
  */
 
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ * \ingroup group_mars_core
+ */
+uint32_t mars_get_ticks(void);
+
+#if defined(__cplusplus)
+}
+#endif
+
 #endif
--- a/core/src/common/kernel_internal_types.h
+++ b/core/src/common/kernel_internal_types.h
@@ -40,13 +40,22 @@
 
 #include <stdint.h>
 
-#define MARS_KERNEL_PARAMS_ALIGN	128
+#define MARS_KERNEL_TICKS_FLAG_SYNC_BEGIN	0x1
+#define MARS_KERNEL_TICKS_FLAG_SYNC_END		0x2
+#define MARS_KERNEL_PARAMS_ALIGN		128
+
+/* mars kernel ticks */
+struct mars_kernel_ticks {
+	uint32_t flag;
+	uint32_t offset;
+};
 
 /* mars kernel parameters */
 struct mars_kernel_params {
-	uint32_t id;
+	uint32_t kernel_id;
 	uint64_t mars_context_ea;
 	uint64_t workload_queue_ea;
+	struct mars_kernel_ticks kernel_ticks;
 } __attribute__((aligned(MARS_KERNEL_PARAMS_ALIGN)));
 
 #endif
--- a/core/src/host/lib/context.c
+++ b/core/src/host/lib/context.c
@@ -39,6 +39,7 @@
 #include <string.h>
 #include <pthread.h>
 #include <libspe2.h>
+#include <ppu_intrinsics.h>
 
 #include "mars/context.h"
 #include "mars/core.h"
@@ -52,6 +53,27 @@ extern struct spe_program_handle mars_ke
 static struct mars_context *mars_shared_context;
 static pthread_mutex_t mars_mutex = PTHREAD_MUTEX_INITIALIZER;
 
+uint32_t mars_get_ticks(void)
+{
+	return __mftb() & 0xffffffff;
+}
+
+static void kernel_ticks_sync(volatile struct mars_kernel_ticks *kernel_ticks)
+{
+	/* wait until kernel sets the sync begin flag */
+	do {
+	} while (kernel_ticks->flag != MARS_KERNEL_TICKS_FLAG_SYNC_BEGIN);
+
+	__lwsync();
+
+	kernel_ticks->offset = mars_get_ticks();
+
+	__lwsync();
+
+	/* set the sync end flag so kernel can finish sync */
+	kernel_ticks->flag = MARS_KERNEL_TICKS_FLAG_SYNC_END;
+}
+
 static void *mpu_context_thread(void *arg)
 {
 	int ret;
@@ -91,7 +113,7 @@ static int mpu_contexts_create(struct ma
 	for (i = mars->mpu_context_count; i < num_mpus; i++) {
 		struct mars_kernel_params *params = &mars->kernel_params[i];
 
-		params->id = i;
+		params->kernel_id = i;
 		params->mars_context_ea =
 			mars_ptr_to_ea(mars);
 		params->workload_queue_ea =
@@ -102,6 +124,8 @@ static int mpu_contexts_create(struct ma
 		if (ret)
 			return MARS_ERROR_INTERNAL;
 
+		kernel_ticks_sync(&params->kernel_ticks);
+
 		mars->mpu_context_count++;
 	}
 
@@ -170,7 +194,7 @@ int mars_context_create(struct mars_cont
 		goto done;
 	}
 
-	/* allocate */
+	/* allocate context */
 	mars = malloc(sizeof(struct mars_context));
 	if (!mars) {
 		ret = MARS_ERROR_MEMORY;
@@ -191,6 +215,9 @@ int mars_context_create(struct mars_cont
 		ret = MARS_ERROR_MEMORY;
 		goto error_malloc_kernel_params;
 	}
+	/* zero kernel params */
+	memset(mars->kernel_params, 0,
+		sizeof(struct mars_kernel_params) * num_mpus_max);
 
 	/* allocate mpu context thread array */
 	mars->mpu_context_threads = (pthread_t *)
--- a/core/src/mpu/kernel/kernel.c
+++ b/core/src/mpu/kernel/kernel.c
@@ -39,14 +39,65 @@
 
 struct mars_kernel_params kernel_params;
 
+static void kernel_get_params(uint64_t kernel_params_ea)
+{
+	int mask;
+
+	/* save event mask */
+	mask = spu_read_event_mask();
+
+	/* set event mask for the lost event */
+	spu_write_event_mask(MFC_LLR_LOST_EVENT);
+
+	/* set sync begin flag so host knows to begin sync process */
+	do {
+		mfc_getllar(&kernel_params, kernel_params_ea, 0, 0);
+		mfc_read_atomic_status();
+
+		/* set the flag */
+		kernel_params.kernel_ticks.flag =
+			MARS_KERNEL_TICKS_FLAG_SYNC_BEGIN;
+		spu_dsync();
+
+		mfc_putllc(&kernel_params, kernel_params_ea, 0, 0);
+	} while (mfc_read_atomic_status() & MFC_PUTLLC_STATUS);
+
+	/* get the tick offset from host and check if sync end flag is set */
+	do {
+		spu_write_event_ack(MFC_LLR_LOST_EVENT);
+
+		mfc_getllar(&kernel_params, kernel_params_ea, 0, 0);
+		mfc_read_atomic_status();
+
+		/* host set the sync end flag so finish */
+		if (kernel_params.kernel_ticks.flag ==
+			MARS_KERNEL_TICKS_FLAG_SYNC_END)
+			break;
+
+		spu_read_event_status();
+	} while (1);
+
+	/* now, kernel parameters, including offset of tick counters,
+	 * are stored in 'kernel_params'.
+	 */
+
+	/* start decrementer */
+	spu_write_decrementer(0);
+
+	/* restore event mask */
+	spu_write_event_mask(mask);
+
+	/* clear any remnant lost event */
+	spu_write_event_ack(MFC_LLR_LOST_EVENT);
+}
+
 int main(unsigned long long mpu_context_id, unsigned long long kernel_params_ea)
 {
 	(void)mpu_context_id;
 
 	int exit_flag = 0;
 
-	mars_dma_get_and_wait(&kernel_params, kernel_params_ea,
-		sizeof(struct mars_kernel_params), MARS_DMA_TAG);
+	kernel_get_params(kernel_params_ea);
 
 	while (!exit_flag) {
 		int status = scheduler();
--- a/core/src/mpu/kernel/kernel.h
+++ b/core/src/mpu/kernel/kernel.h
@@ -69,6 +69,7 @@ void mars_reentry(void);
 int scheduler(void);
 
 /* kernel syscall functions */
+uint32_t syscall_get_ticks(void);
 uint64_t syscall_get_mars_context_ea(void);
 uint32_t syscall_get_kernel_id(void);
 uint16_t syscall_get_workload_id(void);
--- a/core/src/mpu/kernel/kernel_syscalls.c
+++ b/core/src/mpu/kernel/kernel_syscalls.c
@@ -42,6 +42,7 @@ void *workload_stack;
 
 struct mars_kernel_syscalls kernel_syscalls =
 {
+	syscall_get_ticks,
 	syscall_get_mars_context_ea,
 	syscall_get_kernel_id,
 	syscall_get_workload_id,
@@ -64,6 +65,11 @@ void mars_reentry(void)
 	syscall_resume();
 }
 
+uint32_t syscall_get_ticks(void)
+{
+	return kernel_params.kernel_ticks.offset - spu_read_decrementer();
+}
+
 uint64_t syscall_get_mars_context_ea(void)
 {
 	return kernel_params.mars_context_ea;
@@ -71,7 +77,7 @@ uint64_t syscall_get_mars_context_ea(voi
 
 uint32_t syscall_get_kernel_id(void)
 {
-	return kernel_params.id;
+	return kernel_params.kernel_id;
 }
 
 uint16_t syscall_get_workload_id(void)
--- a/core/src/mpu/lib/syscalls.c
+++ b/core/src/mpu/lib/syscalls.c
@@ -39,6 +39,11 @@
 
 struct mars_kernel_syscalls *mars_kernel_syscalls;
 
+uint32_t mars_get_ticks(void)
+{
+	return (*mars_kernel_syscalls->get_ticks)();
+}
+
 uint64_t mars_get_mars_context_ea(void)
 {
 	return (*mars_kernel_syscalls->get_mars_context_ea)();
--- a/core/src/mpu/lib/syscalls.h
+++ b/core/src/mpu/lib/syscalls.h
@@ -42,6 +42,7 @@
 
 /* mars kernel syscalls */
 struct mars_kernel_syscalls {
+	uint32_t (*get_ticks)(void);
 	uint64_t (*get_mars_context_ea)(void);
 	uint32_t (*get_kernel_id)(void);
 	uint16_t (*get_workload_id)(void);
@@ -65,6 +66,7 @@ struct mars_kernel_syscalls {
 extern "C" {
 #endif
 
+uint32_t mars_get_ticks(void);
 uint64_t mars_get_mars_context_ea(void);
 uint32_t mars_get_kernel_id(void);
 uint16_t mars_get_workload_id(void);
--- a/doxygen/src/doxygen
+++ b/doxygen/src/doxygen
@@ -4159,6 +4159,7 @@ This section will describe the MARS API.
 
 - Host Library API
  - Core Management
+  - \ref mars_get_ticks
   - \ref mars_ptr_to_ea
   - \ref mars_ea_to_ptr
  - Context Management
@@ -4205,6 +4206,8 @@ This section will describe the MARS API.
    - \ref group_mars_task_signal "mars_task_signal_send"
 
 - MPU Library API
+ - Core Management
+  - \ref mars_get_ticks
  - Mutex Management
   - \ref mars_mutex_lock
   - \ref mars_mutex_lock_get
@@ -4262,7 +4265,7 @@ This section will describe the MARS API.
 
 /**
 ********************************************************************************
-\defgroup group_mars_core MARS Core API
+\defgroup group_mars_core Core Management API
 
 ********************************************************************************
 **/






More information about the cbe-oss-dev mailing list