diff options
Diffstat (limited to 'examples/performance-thread/common/lthread_diag.c')
-rw-r--r-- | examples/performance-thread/common/lthread_diag.c | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/examples/performance-thread/common/lthread_diag.c b/examples/performance-thread/common/lthread_diag.c new file mode 100644 index 00000000..bce1a0c3 --- /dev/null +++ b/examples/performance-thread/common/lthread_diag.c @@ -0,0 +1,323 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2015 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rte_log.h> +#include <rte_common.h> + +#include "lthread_diag.h" +#include "lthread_queue.h" +#include "lthread_pool.h" +#include "lthread_objcache.h" +#include "lthread_sched.h" +#include "lthread_diag_api.h" + + +/* dummy ref value of default diagnostic callback */ +static uint64_t dummy_ref; + +#define DIAG_SCHED_STATS_FORMAT \ +"core %d\n%33s %12s %12s %12s %12s\n" + +#define DIAG_CACHE_STATS_FORMAT \ +"%20s %12lu %12lu %12lu %12lu %12lu\n" + +#define DIAG_QUEUE_STATS_FORMAT \ +"%20s %12lu %12lu %12lu\n" + + +/* + * texts used in diagnostic events, + * corresponding diagnostic mask bit positions are given as comment + */ +const char *diag_event_text[] = { + "LTHREAD_CREATE ", /* 00 */ + "LTHREAD_EXIT ", /* 01 */ + "LTHREAD_JOIN ", /* 02 */ + "LTHREAD_CANCEL ", /* 03 */ + "LTHREAD_DETACH ", /* 04 */ + "LTHREAD_FREE ", /* 05 */ + "LTHREAD_SUSPENDED ", /* 06 */ + "LTHREAD_YIELD ", /* 07 */ + "LTHREAD_RESCHEDULED", /* 08 */ + "LTHREAD_SLEEP ", /* 09 */ + "LTHREAD_RESUMED ", /* 10 */ + "LTHREAD_AFFINITY ", /* 11 */ + "LTHREAD_TMR_START ", /* 12 */ + "LTHREAD_TMR_DELETE ", /* 13 */ + "LTHREAD_TMR_EXPIRED", /* 14 */ + "COND_CREATE ", /* 15 */ + "COND_DESTROY ", /* 16 */ + "COND_WAIT ", /* 17 */ + "COND_SIGNAL ", /* 18 */ + "COND_BROADCAST ", /* 19 */ + "MUTEX_CREATE ", /* 20 */ + "MUTEX_DESTROY ", /* 21 */ + "MUTEX_LOCK ", /* 22 */ + "MUTEX_TRYLOCK ", /* 23 */ + "MUTEX_BLOCKED ", /* 24 */ + "MUTEX_UNLOCKED ", /* 25 */ + "SCHED_CREATE ", /* 26 */ + "SCHED_SHUTDOWN " /* 27 */ +}; + + +/* + * set diagnostic ,ask + */ +void lthread_diagnostic_set_mask(DIAG_USED uint64_t mask) +{ +#if LTHREAD_DIAG + diag_mask = mask; +#else + RTE_LOG(INFO, LTHREAD, + "LTHREAD_DIAG is not set, see lthread_diag_api.h\n"); +#endif +} + + +/* + * Check consistency of the scheduler stats + * Only sensible run after the schedulers are stopped + * Count the number of objects lying in caches and queues + * and available in the qnode pool. + * This should be equal to the total capacity of all + * qnode pools. + */ +void +_sched_stats_consistency_check(void); +void +_sched_stats_consistency_check(void) +{ +#if LTHREAD_DIAG + int i; + struct lthread_sched *sched; + uint64_t count = 0; + uint64_t capacity = 0; + + for (i = 0; i < LTHREAD_MAX_LCORES; i++) { + sched = schedcore[i]; + if (sched == NULL) + continue; + + /* each of these queues consumes a stub node */ + count += 8; + count += DIAG_COUNT(sched->ready, size); + count += DIAG_COUNT(sched->pready, size); + count += DIAG_COUNT(sched->lthread_cache, available); + count += DIAG_COUNT(sched->stack_cache, available); + count += DIAG_COUNT(sched->tls_cache, available); + count += DIAG_COUNT(sched->per_lthread_cache, available); + count += DIAG_COUNT(sched->cond_cache, available); + count += DIAG_COUNT(sched->mutex_cache, available); + + /* the node pool does not consume a stub node */ + if (sched->qnode_pool->fast_alloc != NULL) + count++; + count += DIAG_COUNT(sched->qnode_pool, available); + + capacity += DIAG_COUNT(sched->qnode_pool, capacity); + } + if (count != capacity) { + RTE_LOG(CRIT, LTHREAD, + "Scheduler caches are inconsistent\n"); + } else { + RTE_LOG(INFO, LTHREAD, + "Scheduler caches are ok\n"); + } +#endif +} + + +#if LTHREAD_DIAG +/* + * Display node pool stats + */ +static inline void +_qnode_pool_display(DIAG_USED struct qnode_pool *p) +{ + + printf(DIAG_CACHE_STATS_FORMAT, + p->name, + DIAG_COUNT(p, rd), + DIAG_COUNT(p, wr), + DIAG_COUNT(p, available), + DIAG_COUNT(p, prealloc), + DIAG_COUNT(p, capacity)); + fflush(stdout); +} +#endif + + +#if LTHREAD_DIAG +/* + * Display queue stats + */ +static inline void +_lthread_queue_display(DIAG_USED struct lthread_queue *q) +{ +#if DISPLAY_OBJCACHE_QUEUES + printf(DIAG_QUEUE_STATS_FORMAT, + q->name, + DIAG_COUNT(q, rd), + DIAG_COUNT(q, wr), + DIAG_COUNT(q, size)); + fflush(stdout); +#else + printf("%s: queue stats disabled\n", + q->name); + +#endif +} +#endif + +#if LTHREAD_DIAG +/* + * Display objcache stats + */ +static inline void +_objcache_display(DIAG_USED struct lthread_objcache *c) +{ + + printf(DIAG_CACHE_STATS_FORMAT, + c->name, + DIAG_COUNT(c, rd), + DIAG_COUNT(c, wr), + DIAG_COUNT(c, available), + DIAG_COUNT(c, prealloc), + DIAG_COUNT(c, capacity)); + _lthread_queue_display(c->q); + fflush(stdout); +} +#endif + +/* + * Display sched stats + */ +void +lthread_sched_stats_display(void) +{ +#if LTHREAD_DIAG + int i; + struct lthread_sched *sched; + + for (i = 0; i < LTHREAD_MAX_LCORES; i++) { + sched = schedcore[i]; + if (sched != NULL) { + printf(DIAG_SCHED_STATS_FORMAT, + sched->lcore_id, + "rd", + "wr", + "present", + "nb preallocs", + "capacity"); + _lthread_queue_display(sched->ready); + _lthread_queue_display(sched->pready); + _qnode_pool_display(sched->qnode_pool); + _objcache_display(sched->lthread_cache); + _objcache_display(sched->stack_cache); + _objcache_display(sched->tls_cache); + _objcache_display(sched->per_lthread_cache); + _objcache_display(sched->cond_cache); + _objcache_display(sched->mutex_cache); + fflush(stdout); + } + } + _sched_stats_consistency_check(); +#else + RTE_LOG(INFO, LTHREAD, + "lthread diagnostics disabled\n" + "hint - set LTHREAD_DIAG in lthread_diag_api.h\n"); +#endif +} + +/* + * Defafult diagnostic callback + */ +static uint64_t +_lthread_diag_default_cb(uint64_t time, struct lthread *lt, int diag_event, + uint64_t diag_ref, const char *text, uint64_t p1, uint64_t p2) +{ + uint64_t _p2; + int lcore = (int) rte_lcore_id(); + + switch (diag_event) { + case LT_DIAG_LTHREAD_CREATE: + case LT_DIAG_MUTEX_CREATE: + case LT_DIAG_COND_CREATE: + _p2 = dummy_ref; + break; + default: + _p2 = p2; + break; + } + + printf("%"PRIu64" %d %8.8lx %8.8lx %s %8.8lx %8.8lx\n", + time, + lcore, + (uint64_t) lt, + diag_ref, + text, + p1, + _p2); + + return dummy_ref++; +} + +/* + * plug in default diag callback with mask off + */ +void _lthread_diag_ctor(void)__attribute__((constructor)); +void _lthread_diag_ctor(void) +{ + diag_cb = _lthread_diag_default_cb; + diag_mask = 0; +} + + +/* + * enable diagnostics + */ +void lthread_diagnostic_enable(DIAG_USED diag_callback cb, + DIAG_USED uint64_t mask) +{ +#if LTHREAD_DIAG + if (cb == NULL) + diag_cb = _lthread_diag_default_cb; + else + diag_cb = cb; + diag_mask = mask; +#else + RTE_LOG(INFO, LTHREAD, + "LTHREAD_DIAG is not set, see lthread_diag_api.h\n"); +#endif +} |