diff options
author | Kazunori Asayama <asayama@sm.sony.co.jp> | 2009-01-20 16:29:15 -0800 |
---|---|---|
committer | Yuji Mano <yuji.mano@am.sony.com> | 2009-01-23 11:00:59 -0800 |
commit | a674859251c00bd34bf5c938ef471c4428158db5 (patch) | |
tree | 395ab692e622353565f7c25cf3bb102ca9a2c233 | |
parent | 90a8d6c1983474c1a24f00828f8996d068dfacf1 (diff) | |
download | mars-src-a674859251c00bd34bf5c938ef471c4428158db5.tar.gz |
base: No busy wait
Remove busy loops from host side code (base)
This patch removes busy loops from host side code by using futex.
Signed-off-by: Kazunori Asayama <asayama@sm.sony.co.jp>
Signed-off-by: Yuji Mano <yuji.mano@am.sony.com>
-rw-r--r-- | base/include/host/mars/base.h | 2 | ||||
-rw-r--r-- | base/include/mpu/mars/module.h | 11 | ||||
-rw-r--r-- | base/src/common/kernel_internal_types.h | 3 | ||||
-rw-r--r-- | base/src/common/workload_internal_types.h | 2 | ||||
-rw-r--r-- | base/src/host/lib/cond_cell.c | 60 | ||||
-rw-r--r-- | base/src/host/lib/mpu_cell.c | 86 | ||||
-rw-r--r-- | base/src/mpu/kernel/kernel.c | 27 | ||||
-rw-r--r-- | base/src/mpu/lib/module.c | 5 | ||||
-rw-r--r-- | scripts/acinclude.m4 | 23 |
9 files changed, 215 insertions, 4 deletions
diff --git a/base/include/host/mars/base.h b/base/include/host/mars/base.h index 05f01a4..d0b1f87 100644 --- a/base/include/host/mars/base.h +++ b/base/include/host/mars/base.h @@ -232,6 +232,8 @@ int mars_ea_cond_wait(uint64_t watch_point_ea, int (*test_cond)(uint32_t , void *), void *test_cond_param); +int mars_ea_cond_signal(uint64_t watch_point_ea, int broadcast); + #ifdef MARS_ENABLE_DISCRETE_SHARED_MEMORY # define mars_ea_work_area_get(ea, boundary, size) mars_alloca_align(boundary, size) #else /* !MARS_ENABLE_DISCRETE_SHARED_MEMORY */ diff --git a/base/include/mpu/mars/module.h b/base/include/mpu/mars/module.h index 76ce6b7..5e010e8 100644 --- a/base/include/mpu/mars/module.h +++ b/base/include/mpu/mars/module.h @@ -289,6 +289,17 @@ void mars_module_workload_yield(void); */ void mars_module_workload_finish(void); +/** + * \ingroup group_mars_workload_module + * \brief <b>[MPU]</b> Notify host a particular 32-bit area is modified. + * + * \param[in] watch_point_ea - ea of modified area + * + * \return + * MARS_SUCCESS - signal sent to host + */ +int mars_module_host_signal_send(uint64_t watch_point_ea); + #if defined(__cplusplus) } #endif diff --git a/base/src/common/kernel_internal_types.h b/base/src/common/kernel_internal_types.h index 1020958..82fe125 100644 --- a/base/src/common/kernel_internal_types.h +++ b/base/src/common/kernel_internal_types.h @@ -70,6 +70,9 @@ struct mars_kernel_syscalls { struct mars_workload_context **workload); int (*workload_schedule_end)(uint16_t id); int (*workload_schedule_cancel)(uint16_t id); + + int (*host_signal_send)(uint64_t watch_point_ea); + void (*exit)(uint8_t state); }; diff --git a/base/src/common/workload_internal_types.h b/base/src/common/workload_internal_types.h index 228201b..f35358b 100644 --- a/base/src/common/workload_internal_types.h +++ b/base/src/common/workload_internal_types.h @@ -104,6 +104,8 @@ (*bits) = ((*(bits) & ~MARS_BITS_MASK_##name) | \ ((uint64_t)(val) << MARS_BITS_SHIFT_##name)) +#define MARS_HOST_SIGNAL_EXIT 0 + /* 128 byte workload queue header structure */ struct mars_workload_queue_header { uint64_t queue_ea; diff --git a/base/src/host/lib/cond_cell.c b/base/src/host/lib/cond_cell.c index bd8d348..9f5163e 100644 --- a/base/src/host/lib/cond_cell.c +++ b/base/src/host/lib/cond_cell.c @@ -36,20 +36,76 @@ */ #include <sched.h> +#include <errno.h> +#include <limits.h> #include "config.h" #include "mars/base.h" +#include "mars/error.h" + +#ifdef ENABLE_COND_WAIT_FUTEX + +#include <unistd.h> +#include <sys/syscall.h> +#include <linux/futex.h> + +static int futex_wait(void *ptr, int val) +{ + int ret; + + ret = syscall(__NR_futex, ptr, FUTEX_WAIT, val, NULL, NULL, 0); + if (ret && errno != EWOULDBLOCK) + return MARS_ERROR_INTERNAL; + + return MARS_SUCCESS; +} + +static int futex_wake(void *ptr, int val) +{ + int ret; + + ret = syscall(__NR_futex, ptr, FUTEX_WAKE, val, NULL, NULL, 0); + if (ret < 0) + return MARS_ERROR_INTERNAL; + + return MARS_SUCCESS; +} + +#endif int mars_ea_cond_wait(uint64_t watch_point_ea, int (*test_cond)(uint32_t , void *), void *test_cond_param) { + int i = 0; int ret; - while ((ret = (*test_cond)(mars_ea_get_uint32(watch_point_ea), - test_cond_param)) < 0) + while (1) { + uint32_t val = mars_ea_get_uint32(watch_point_ea); + + ret = (*test_cond)(val, test_cond_param); + if (ret >= 0) + break; + +#ifdef ENABLE_COND_WAIT_FUTEX + ret = futex_wait(mars_ea_to_ptr(watch_point_ea), val); + if (ret != MARS_SUCCESS) + break; +#else sched_yield(); +#endif + } return ret; } + +int mars_ea_cond_signal(uint64_t watch_point_ea, int broadcast) +{ +#ifdef ENABLE_COND_WAIT_FUTEX + futex_wake(mars_ea_to_ptr(watch_point_ea), + broadcast ? INT_MAX : 1); +#endif + + return MARS_SUCCESS; +} diff --git a/base/src/host/lib/mpu_cell.c b/base/src/host/lib/mpu_cell.c index 94dd195..2580726 100644 --- a/base/src/host/lib/mpu_cell.c +++ b/base/src/host/lib/mpu_cell.c @@ -40,10 +40,12 @@ #include "config.h" +#include "mars/base.h" #include "mars/context.h" #include "mars/error.h" #include "context_internal.h" +#include "workload_internal_types.h" #include "numa_internal.h" #ifdef MARS_ENABLE_NUMA @@ -100,13 +102,87 @@ int mars_mpu_max(int *num) return MARS_SUCCESS; } +#ifdef ENABLE_COND_WAIT_FUTEX + +static void *mpu_handler_thread(void *arg) +{ + int ret; + spe_context_ptr_t spe = (spe_context_ptr_t)arg; + + while (1) { + unsigned int ea_h, ea_l; + uint64_t ea; + + ret = spe_out_intr_mbox_read(spe, &ea_l, 1, + SPE_MBOX_ANY_BLOCKING); + if (ret < 1) + goto error; + + ret = spe_out_mbox_read(spe, &ea_h, 1); + if (ret != 1) + goto error; + + ea = ((uint64_t)ea_h << 32) | ea_l; + if (ea == MARS_HOST_SIGNAL_EXIT) + break; + + mars_ea_cond_signal(ea, 1); + } + + return (void *)(uintptr_t)MARS_SUCCESS; + +error: + return (void *)(uintptr_t)MARS_ERROR_INTERNAL; +} + +static int handler_thread_create(pthread_t *thread, spe_context_ptr_t spe) +{ + int ret; + + ret = pthread_create(thread, NULL, mpu_handler_thread, spe); + if (ret) + return MARS_ERROR_INTERNAL; + + return MARS_SUCCESS; +} + +static int handler_thread_join(pthread_t thread) +{ + int ret; + + ret = pthread_join(thread, NULL); + if (ret) + return MARS_ERROR_INTERNAL; + + return MARS_SUCCESS; +} + +#else /* !ENABLE_COND_WAIT_FUTEX */ + +static int handler_thread_create(pthread_t *thread, spe_context_ptr_t spe) +{ + (void)thread; + + return MARS_SUCCESS; +} + +static int handler_thread_join(pthread_t thread) +{ + (void)thread; + + return MARS_SUCCESS; +} + +#endif /* !ENABLE_COND_WAIT_FUTEX */ + static void *mpu_context_thread(void *arg) { int ret; unsigned int entry = SPE_DEFAULT_ENTRY; struct mars_kernel_params *params = (struct mars_kernel_params *)arg; - struct spe_context *spe; + spe_context_ptr_t spe; spe_program_handle_t prog; + pthread_t handler_thread; spe = spe_context_create(0, NULL); if (!spe) @@ -121,12 +197,20 @@ static void *mpu_context_thread(void *arg) return (void *)MARS_ERROR_INTERNAL; } + ret = handler_thread_create(&handler_thread, spe); + if (ret) { + spe_context_destroy(spe); + return (void *)ret; + } + ret = spe_context_run(spe, &entry, 0, params, NULL, NULL); if (ret) { spe_context_destroy(spe); return (void *)MARS_ERROR_INTERNAL; } + handler_thread_join(handler_thread); + ret = spe_context_destroy(spe); if (ret) return (void *)MARS_ERROR_INTERNAL; diff --git a/base/src/mpu/kernel/kernel.c b/base/src/mpu/kernel/kernel.c index 080f6e7..2556b2a 100644 --- a/base/src/mpu/kernel/kernel.c +++ b/base/src/mpu/kernel/kernel.c @@ -402,6 +402,16 @@ static int module_workload_schedule_cancel(uint16_t id) NULL); } +static int module_host_signal_send(uint64_t watch_point_ea) +{ +#ifdef ENABLE_COND_WAIT_FUTEX + spu_write_out_mbox((uint32_t)(watch_point_ea >> 32)); + spu_write_out_intr_mbox((uint32_t)(watch_point_ea & 0xffffffff)); +#endif + + return MARS_SUCCESS; +} + static void module_exit(uint8_t state) { workload_state = state; @@ -412,7 +422,6 @@ static void module_exit(uint8_t state) "br _module_exit;" ); } - static struct mars_kernel_syscalls kernel_syscalls = { get_ticks, @@ -429,6 +438,7 @@ static struct mars_kernel_syscalls kernel_syscalls = module_workload_schedule_begin, module_workload_schedule_end, module_workload_schedule_cancel, + module_host_signal_send, module_exit }; @@ -540,6 +550,16 @@ static int reserve_block(int block) return index; } +static void notify_host_bits(uint64_t block_ea, int index) +{ + uint64_t bits_ea = + block_ea + + offsetof(struct mars_workload_queue_block, bits) + + sizeof(uint64_t) * index; + + module_host_signal_send(bits_ea); +} + static void release_block(int block, int index) { uint64_t block_ea = get_block_ea(block); @@ -550,6 +570,9 @@ static void release_block(int block, int index) MARS_BITS_SET(&queue_block.bits[index], STATE, workload_state); mars_mutex_unlock_put(block_ea, (struct mars_mutex *)&queue_block); + + if (workload_state == MARS_WORKLOAD_STATE_FINISHED) + notify_host_bits(block_ea, index); } static int __attribute__((noinline)) reserve_workload(void) @@ -716,5 +739,7 @@ int main(unsigned long long mpu_context_id, } } + module_host_signal_send(MARS_HOST_SIGNAL_EXIT); + return MARS_SUCCESS; } diff --git a/base/src/mpu/lib/module.c b/base/src/mpu/lib/module.c index 617a31d..3227d0b 100644 --- a/base/src/mpu/lib/module.c +++ b/base/src/mpu/lib/module.c @@ -163,3 +163,8 @@ void mars_module_workload_finish(void) { (*kernel_syscalls->exit)(MARS_WORKLOAD_STATE_FINISHED); } + +int mars_module_host_signal_send(uint64_t watch_point_ea) +{ + return (*kernel_syscalls->host_signal_send)(watch_point_ea); +} diff --git a/scripts/acinclude.m4 b/scripts/acinclude.m4 index df8c686..3a5e409 100644 --- a/scripts/acinclude.m4 +++ b/scripts/acinclude.m4 @@ -66,6 +66,28 @@ AC_ARG_ENABLE( AC_MSG_RESULT([using enable-discrete-shared-memory ${enable_discrete_shared_memory}]) ]) # AC_CONFIG_MARS_DISCRETE_SHARED_MEMORY +AC_DEFUN([AC_CONFIG_MARS_COND_WAIT],[ +AC_ARG_ENABLE([cond-wait], + [AS_HELP_STRING([--enable-cond-wait=TYPE], + [specify how to wait for conditions (busy | futex)])], + [],[AS_CASE([$with_mars_platform], + [cell],[enable_cond_wait=futex], + [enable_cond_wait=busy])]) + +AS_CASE([$enable_cond_wait], + [busy],[ + AC_DEFINE([ENABLE_COND_WAIT_BUSY],[1], + [Define to 1 if busy loop is used to wait for conditions.])], + [futex],[ + AS_CASE([$with_mars_platform], + [cell],[], + [AC_MSG_ERROR([futex is not supported on other platforms than Cell/B.E.])]) + AC_DEFINE([ENABLE_COND_WAIT_FUTEX],[1], + [Define to 1 if futex is used to wait for conditions.])], + [AC_MSG_ERROR([invalid option --enable-cond-wait=$enable_cond_wait])]) + +AC_MSG_RESULT([using enable-cond-wait $enable_cond_wait]) +]) # AC_CONFIG_MARS_COND_WAIT AC_DEFUN([AC_CONFIG_DEBUG],[ @@ -95,6 +117,7 @@ AC_DEFUN([AC_CONFIG_MARS],[ AC_CONFIG_MARS_PLATFORM AC_CONFIG_MARS_DISCRETE_SHARED_MEMORY +AC_CONFIG_MARS_COND_WAIT AC_CONFIG_DEBUG AC_CONFIG_MARS_POST |