diff --git a/include/spdk/event.h b/include/spdk/event.h index 88caefc30..2a5332d32 100644 --- a/include/spdk/event.h +++ b/include/spdk/event.h @@ -128,12 +128,6 @@ struct spdk_app_opts { uint64_t num_entries; }; -struct spdk_reactor_tsc_stats { - uint64_t busy_tsc; - uint64_t idle_tsc; - uint64_t unknown_tsc; -}; - /** * Initialize the default value of opts * @@ -291,15 +285,6 @@ void spdk_reactor_enable_context_switch_monitor(bool enabled); */ bool spdk_reactor_context_switch_monitor_enabled(void); -/** - * Get tsc stats from a given reactor - * Copy cumulative reactor tsc values to user's tsc_stats structure. - * - * \param tsc_stats User's tsc_stats structure. - * \param core_id Get tsc data on this Reactor core id. - */ -int spdk_reactor_get_tsc_stats(struct spdk_reactor_tsc_stats *tsc_stats, uint32_t core_id); - #ifdef __cplusplus } #endif diff --git a/include/spdk/thread.h b/include/spdk/thread.h index 6d3d9f356..75816dc43 100644 --- a/include/spdk/thread.h +++ b/include/spdk/thread.h @@ -268,6 +268,21 @@ struct spdk_thread *spdk_get_thread(void); */ const char *spdk_thread_get_name(const struct spdk_thread *thread); +struct spdk_thread_stats { + uint64_t busy_tsc; + uint64_t idle_tsc; + uint64_t unknown_tsc; +}; + +/** + * Get statistics about the current thread. + * + * Copy cumulative thread stats values to the provided thread stats structure. + * + * \param stats User's thread_stats structure. + */ +int spdk_thread_get_stats(struct spdk_thread_stats *stats); + /** * Send a message to the given thread. * diff --git a/lib/event/reactor.c b/lib/event/reactor.c index 90583f3fe..cf3d67aac 100644 --- a/lib/event/reactor.c +++ b/lib/event/reactor.c @@ -60,11 +60,6 @@ struct spdk_reactor { /* Poller for get the rusage for the reactor. */ struct spdk_poller *rusage_poller; - /* Reactor tsc stats */ - struct spdk_reactor_tsc_stats tsc_stats; - - uint64_t tsc_last; - /* The last known rusage values */ struct rusage rusage; @@ -239,55 +234,15 @@ spdk_reactor_context_switch_monitor_enabled(void) return g_context_switch_monitor_enabled; } -static void -spdk_reactor_add_tsc_stats(void *arg, int rc, uint64_t now) -{ - struct spdk_reactor *reactor = arg; - struct spdk_reactor_tsc_stats *tsc_stats = &reactor->tsc_stats; - - if (rc == 0) { - /* Poller status idle */ - tsc_stats->idle_tsc += now - reactor->tsc_last; - } else if (rc > 0) { - /* Poller status busy */ - tsc_stats->busy_tsc += now - reactor->tsc_last; - } else { - /* Poller status unknown */ - tsc_stats->unknown_tsc += now - reactor->tsc_last; - } - - reactor->tsc_last = now; -} - -int -spdk_reactor_get_tsc_stats(struct spdk_reactor_tsc_stats *tsc_stats, uint32_t core) -{ - struct spdk_reactor *reactor; - - if (!spdk_cpuset_get_cpu(g_spdk_app_core_mask, core)) { - return -1; - } - - reactor = spdk_reactor_get(core); - if (!reactor) { - SPDK_ERRLOG("Unable to get reactor for core %u\n", core); - return -1; - } - *tsc_stats = reactor->tsc_stats; - - return 0; -} - static int _spdk_reactor_run(void *arg) { struct spdk_reactor *reactor = arg; struct spdk_thread *thread; - uint32_t event_count; uint64_t now; uint64_t sleep_cycles; uint32_t sleep_us; - int rc = -1; + int rc; char thread_name[32]; snprintf(thread_name, sizeof(thread_name), "reactor_%u", reactor->lcore); @@ -303,29 +258,14 @@ _spdk_reactor_run(void *arg) _spdk_reactor_context_switch_monitor_start(reactor, NULL); spdk_set_thread(NULL); } - now = spdk_get_ticks(); - reactor->tsc_last = now; while (1) { - bool took_action = false; - - event_count = _spdk_event_queue_run_batch(reactor, thread); - if (event_count > 0) { - rc = 1; - now = spdk_get_ticks(); - spdk_reactor_add_tsc_stats(reactor, rc, now); - took_action = true; - } + _spdk_event_queue_run_batch(reactor, thread); rc = spdk_thread_poll(thread, 0); - if (rc != 0) { - now = spdk_get_ticks(); - spdk_reactor_add_tsc_stats(reactor, rc, now); - took_action = true; - } /* Determine if the thread can sleep */ - if (sleep_cycles && !took_action) { + if (sleep_cycles && rc == 0) { uint64_t next_run_tick; now = spdk_get_ticks(); diff --git a/lib/thread/thread.c b/lib/thread/thread.c index 3935e2bdd..5a33d03e5 100644 --- a/lib/thread/thread.c +++ b/lib/thread/thread.c @@ -112,6 +112,9 @@ struct spdk_thread { TAILQ_ENTRY(spdk_thread) tailq; char *name; + uint64_t tsc_last; + struct spdk_thread_stats stats; + /* * Contains pollers actively running on this thread. Pollers * are run round-robin. The thread takes one poller from the head @@ -209,6 +212,8 @@ spdk_thread_create(const char *name) SLIST_INIT(&thread->msg_cache); thread->msg_cache_count = 0; + thread->tsc_last = spdk_get_ticks(); + thread->messages = spdk_ring_create(SPDK_RING_TYPE_MP_SC, 65536, SPDK_ENV_SOCKET_ID_ANY); if (!thread->messages) { SPDK_ERRLOG("Unable to allocate memory for message ring\n"); @@ -373,6 +378,7 @@ spdk_thread_poll(struct spdk_thread *thread, uint32_t max_msgs) struct spdk_thread *orig_thread; struct spdk_poller *poller; int rc = 0; + uint64_t now; orig_thread = _get_thread(); tls_thread = thread; @@ -437,6 +443,19 @@ spdk_thread_poll(struct spdk_thread *thread, uint32_t max_msgs) } } + now = spdk_get_ticks(); + if (rc == 0) { + /* Poller status idle */ + thread->stats.idle_tsc += now - thread->tsc_last; + } else if (rc > 0) { + /* Poller status busy */ + thread->stats.busy_tsc += now - thread->tsc_last; + } else { + /* Poller status unknown */ + thread->stats.unknown_tsc += now - thread->tsc_last; + } + thread->tsc_last = now; + tls_thread = orig_thread; return rc; @@ -491,6 +510,26 @@ spdk_thread_get_name(const struct spdk_thread *thread) return thread->name; } +int +spdk_thread_get_stats(struct spdk_thread_stats *stats) +{ + struct spdk_thread *thread; + + thread = _get_thread(); + if (!thread) { + SPDK_ERRLOG("No thread allocated\n"); + return -EINVAL; + } + + if (stats == NULL) { + return -EINVAL; + } + + *stats = thread->stats; + + return 0; +} + void spdk_thread_send_msg(const struct spdk_thread *thread, spdk_msg_fn fn, void *ctx) {