1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2015 Intel Corporation
6 #include <rte_common.h>
8 #include "lthread_diag.h"
9 #include "lthread_queue.h"
10 #include "lthread_pool.h"
11 #include "lthread_objcache.h"
12 #include "lthread_sched.h"
13 #include "lthread_diag_api.h"
16 /* dummy ref value of default diagnostic callback */
17 static uint64_t dummy_ref;
19 #define DIAG_SCHED_STATS_FORMAT \
20 "core %d\n%33s %12s %12s %12s %12s\n"
22 #define DIAG_CACHE_STATS_FORMAT \
23 "%20s %12lu %12lu %12lu %12lu %12lu\n"
25 #define DIAG_QUEUE_STATS_FORMAT \
26 "%20s %12lu %12lu %12lu\n"
30 * texts used in diagnostic events,
31 * corresponding diagnostic mask bit positions are given as comment
33 const char *diag_event_text[] = {
34 "LTHREAD_CREATE ", /* 00 */
35 "LTHREAD_EXIT ", /* 01 */
36 "LTHREAD_JOIN ", /* 02 */
37 "LTHREAD_CANCEL ", /* 03 */
38 "LTHREAD_DETACH ", /* 04 */
39 "LTHREAD_FREE ", /* 05 */
40 "LTHREAD_SUSPENDED ", /* 06 */
41 "LTHREAD_YIELD ", /* 07 */
42 "LTHREAD_RESCHEDULED", /* 08 */
43 "LTHREAD_SLEEP ", /* 09 */
44 "LTHREAD_RESUMED ", /* 10 */
45 "LTHREAD_AFFINITY ", /* 11 */
46 "LTHREAD_TMR_START ", /* 12 */
47 "LTHREAD_TMR_DELETE ", /* 13 */
48 "LTHREAD_TMR_EXPIRED", /* 14 */
49 "COND_CREATE ", /* 15 */
50 "COND_DESTROY ", /* 16 */
51 "COND_WAIT ", /* 17 */
52 "COND_SIGNAL ", /* 18 */
53 "COND_BROADCAST ", /* 19 */
54 "MUTEX_CREATE ", /* 20 */
55 "MUTEX_DESTROY ", /* 21 */
56 "MUTEX_LOCK ", /* 22 */
57 "MUTEX_TRYLOCK ", /* 23 */
58 "MUTEX_BLOCKED ", /* 24 */
59 "MUTEX_UNLOCKED ", /* 25 */
60 "SCHED_CREATE ", /* 26 */
61 "SCHED_SHUTDOWN " /* 27 */
68 void lthread_diagnostic_set_mask(DIAG_USED uint64_t mask)
73 RTE_LOG(INFO, LTHREAD,
74 "LTHREAD_DIAG is not set, see lthread_diag_api.h\n");
80 * Check consistency of the scheduler stats
81 * Only sensible run after the schedulers are stopped
82 * Count the number of objects lying in caches and queues
83 * and available in the qnode pool.
84 * This should be equal to the total capacity of all
88 _sched_stats_consistency_check(void);
90 _sched_stats_consistency_check(void)
94 struct lthread_sched *sched;
96 uint64_t capacity = 0;
98 for (i = 0; i < LTHREAD_MAX_LCORES; i++) {
103 /* each of these queues consumes a stub node */
105 count += DIAG_COUNT(sched->ready, size);
106 count += DIAG_COUNT(sched->pready, size);
107 count += DIAG_COUNT(sched->lthread_cache, available);
108 count += DIAG_COUNT(sched->stack_cache, available);
109 count += DIAG_COUNT(sched->tls_cache, available);
110 count += DIAG_COUNT(sched->per_lthread_cache, available);
111 count += DIAG_COUNT(sched->cond_cache, available);
112 count += DIAG_COUNT(sched->mutex_cache, available);
114 /* the node pool does not consume a stub node */
115 if (sched->qnode_pool->fast_alloc != NULL)
117 count += DIAG_COUNT(sched->qnode_pool, available);
119 capacity += DIAG_COUNT(sched->qnode_pool, capacity);
121 if (count != capacity) {
122 RTE_LOG(CRIT, LTHREAD,
123 "Scheduler caches are inconsistent\n");
125 RTE_LOG(INFO, LTHREAD,
126 "Scheduler caches are ok\n");
134 * Display node pool stats
137 _qnode_pool_display(DIAG_USED struct qnode_pool *p)
140 printf(DIAG_CACHE_STATS_FORMAT,
144 DIAG_COUNT(p, available),
145 DIAG_COUNT(p, prealloc),
146 DIAG_COUNT(p, capacity));
154 * Display queue stats
157 _lthread_queue_display(DIAG_USED struct lthread_queue *q)
159 #if DISPLAY_OBJCACHE_QUEUES
160 printf(DIAG_QUEUE_STATS_FORMAT,
164 DIAG_COUNT(q, size));
167 printf("%s: queue stats disabled\n",
176 * Display objcache stats
179 _objcache_display(DIAG_USED struct lthread_objcache *c)
182 printf(DIAG_CACHE_STATS_FORMAT,
186 DIAG_COUNT(c, available),
187 DIAG_COUNT(c, prealloc),
188 DIAG_COUNT(c, capacity));
189 _lthread_queue_display(c->q);
195 * Display sched stats
198 lthread_sched_stats_display(void)
202 struct lthread_sched *sched;
204 for (i = 0; i < LTHREAD_MAX_LCORES; i++) {
205 sched = schedcore[i];
207 printf(DIAG_SCHED_STATS_FORMAT,
214 _lthread_queue_display(sched->ready);
215 _lthread_queue_display(sched->pready);
216 _qnode_pool_display(sched->qnode_pool);
217 _objcache_display(sched->lthread_cache);
218 _objcache_display(sched->stack_cache);
219 _objcache_display(sched->tls_cache);
220 _objcache_display(sched->per_lthread_cache);
221 _objcache_display(sched->cond_cache);
222 _objcache_display(sched->mutex_cache);
226 _sched_stats_consistency_check();
228 RTE_LOG(INFO, LTHREAD,
229 "lthread diagnostics disabled\n"
230 "hint - set LTHREAD_DIAG in lthread_diag_api.h\n");
235 * Defafult diagnostic callback
238 _lthread_diag_default_cb(uint64_t time, struct lthread *lt, int diag_event,
239 uint64_t diag_ref, const char *text, uint64_t p1, uint64_t p2)
242 int lcore = (int) rte_lcore_id();
244 switch (diag_event) {
245 case LT_DIAG_LTHREAD_CREATE:
246 case LT_DIAG_MUTEX_CREATE:
247 case LT_DIAG_COND_CREATE:
255 printf("%"PRIu64" %d %8.8lx %8.8lx %s %8.8lx %8.8lx\n",
268 * plug in default diag callback with mask off
270 RTE_INIT(_lthread_diag_ctor)
272 diag_cb = _lthread_diag_default_cb;
280 void lthread_diagnostic_enable(DIAG_USED diag_callback cb,
281 DIAG_USED uint64_t mask)
285 diag_cb = _lthread_diag_default_cb;
290 RTE_LOG(INFO, LTHREAD,
291 "LTHREAD_DIAG is not set, see lthread_diag_api.h\n");