remove extra parentheses in return statement
[dpdk.git] / examples / performance-thread / common / lthread_diag.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2015 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <rte_config.h>
35 #include <rte_log.h>
36 #include <rte_common.h>
37
38 #include "lthread_diag.h"
39 #include "lthread_queue.h"
40 #include "lthread_pool.h"
41 #include "lthread_objcache.h"
42 #include "lthread_sched.h"
43 #include "lthread_diag_api.h"
44
45
46 /* dummy ref value of default diagnostic callback */
47 static uint64_t dummy_ref;
48
49 #define DIAG_SCHED_STATS_FORMAT \
50 "core %d\n%33s %12s %12s %12s %12s\n"
51
52 #define DIAG_CACHE_STATS_FORMAT \
53 "%20s %12lu %12lu %12lu %12lu %12lu\n"
54
55 #define DIAG_QUEUE_STATS_FORMAT \
56 "%20s %12lu %12lu %12lu\n"
57
58
59 /*
60  * texts used in diagnostic events,
61  * corresponding diagnostic mask bit positions are given as comment
62  */
63 const char *diag_event_text[] = {
64         "LTHREAD_CREATE     ",  /* 00 */
65         "LTHREAD_EXIT       ",  /* 01 */
66         "LTHREAD_JOIN       ",  /* 02 */
67         "LTHREAD_CANCEL     ",  /* 03 */
68         "LTHREAD_DETACH     ",  /* 04 */
69         "LTHREAD_FREE       ",  /* 05 */
70         "LTHREAD_SUSPENDED  ",  /* 06 */
71         "LTHREAD_YIELD      ",  /* 07 */
72         "LTHREAD_RESCHEDULED",  /* 08 */
73         "LTHREAD_SLEEP      ",  /* 09 */
74         "LTHREAD_RESUMED    ",  /* 10 */
75         "LTHREAD_AFFINITY   ",  /* 11 */
76         "LTHREAD_TMR_START  ",  /* 12 */
77         "LTHREAD_TMR_DELETE ",  /* 13 */
78         "LTHREAD_TMR_EXPIRED",  /* 14 */
79         "COND_CREATE        ",  /* 15 */
80         "COND_DESTROY       ",  /* 16 */
81         "COND_WAIT          ",  /* 17 */
82         "COND_SIGNAL        ",  /* 18 */
83         "COND_BROADCAST     ",  /* 19 */
84         "MUTEX_CREATE       ",  /* 20 */
85         "MUTEX_DESTROY      ",  /* 21 */
86         "MUTEX_LOCK         ",  /* 22 */
87         "MUTEX_TRYLOCK      ",  /* 23 */
88         "MUTEX_BLOCKED      ",  /* 24 */
89         "MUTEX_UNLOCKED     ",  /* 25 */
90         "SCHED_CREATE       ",  /* 26 */
91         "SCHED_SHUTDOWN     "   /* 27 */
92 };
93
94
95 /*
96  * set diagnostic ,ask
97  */
98 void lthread_diagnostic_set_mask(DIAG_USED uint64_t mask)
99 {
100 #if LTHREAD_DIAG
101         diag_mask = mask;
102 #else
103         RTE_LOG(INFO, LTHREAD,
104                 "LTHREAD_DIAG is not set, see lthread_diag_api.h\n");
105 #endif
106 }
107
108
109 /*
110  * Check consistency of the scheduler stats
111  * Only sensible run after the schedulers are stopped
112  * Count the number of objects lying in caches and queues
113  * and available in the qnode pool.
114  * This should be equal to the total capacity of all
115  * qnode pools.
116  */
117 void
118 _sched_stats_consistency_check(void);
119 void
120 _sched_stats_consistency_check(void)
121 {
122 #if LTHREAD_DIAG
123         int i;
124         struct lthread_sched *sched;
125         uint64_t count = 0;
126         uint64_t capacity = 0;
127
128         for (i = 0; i < LTHREAD_MAX_LCORES; i++) {
129                 sched = schedcore[i];
130                 if (sched == NULL)
131                         continue;
132
133                 /* each of these queues consumes a stub node */
134                 count += 8;
135                 count += DIAG_COUNT(sched->ready, size);
136                 count += DIAG_COUNT(sched->pready, size);
137                 count += DIAG_COUNT(sched->lthread_cache, available);
138                 count += DIAG_COUNT(sched->stack_cache, available);
139                 count += DIAG_COUNT(sched->tls_cache, available);
140                 count += DIAG_COUNT(sched->per_lthread_cache, available);
141                 count += DIAG_COUNT(sched->cond_cache, available);
142                 count += DIAG_COUNT(sched->mutex_cache, available);
143
144                 /* the node pool does not consume a stub node */
145                 if (sched->qnode_pool->fast_alloc != NULL)
146                         count++;
147                 count += DIAG_COUNT(sched->qnode_pool, available);
148
149                 capacity += DIAG_COUNT(sched->qnode_pool, capacity);
150         }
151         if (count != capacity) {
152                 RTE_LOG(CRIT, LTHREAD,
153                         "Scheduler caches are inconsistent\n");
154         } else {
155                 RTE_LOG(INFO, LTHREAD,
156                         "Scheduler caches are ok\n");
157         }
158 #endif
159 }
160
161
162 #if LTHREAD_DIAG
163 /*
164  * Display node pool stats
165  */
166 static inline void
167 _qnode_pool_display(DIAG_USED struct qnode_pool *p)
168 {
169
170         printf(DIAG_CACHE_STATS_FORMAT,
171                         p->name,
172                         DIAG_COUNT(p, rd),
173                         DIAG_COUNT(p, wr),
174                         DIAG_COUNT(p, available),
175                         DIAG_COUNT(p, prealloc),
176                         DIAG_COUNT(p, capacity));
177         fflush(stdout);
178 }
179 #endif
180
181
182 #if LTHREAD_DIAG
183 /*
184  * Display queue stats
185  */
186 static inline void
187 _lthread_queue_display(DIAG_USED struct lthread_queue *q)
188 {
189 #if DISPLAY_OBJCACHE_QUEUES
190         printf(DIAG_QUEUE_STATS_FORMAT,
191                         q->name,
192                         DIAG_COUNT(q, rd),
193                         DIAG_COUNT(q, wr),
194                         DIAG_COUNT(q, size));
195         fflush(stdout);
196 #else
197         printf("%s: queue stats disabled\n",
198                         q->name);
199
200 #endif
201 }
202 #endif
203
204 #if LTHREAD_DIAG
205 /*
206  * Display objcache stats
207  */
208 static inline void
209 _objcache_display(DIAG_USED struct lthread_objcache *c)
210 {
211
212         printf(DIAG_CACHE_STATS_FORMAT,
213                         c->name,
214                         DIAG_COUNT(c, rd),
215                         DIAG_COUNT(c, wr),
216                         DIAG_COUNT(c, available),
217                         DIAG_COUNT(c, prealloc),
218                         DIAG_COUNT(c, capacity));
219         _lthread_queue_display(c->q);
220         fflush(stdout);
221 }
222 #endif
223
224 /*
225  * Display sched stats
226  */
227 void
228 lthread_sched_stats_display(void)
229 {
230 #if LTHREAD_DIAG
231         int i;
232         struct lthread_sched *sched;
233
234         for (i = 0; i < LTHREAD_MAX_LCORES; i++) {
235                 sched = schedcore[i];
236                 if (sched != NULL) {
237                         printf(DIAG_SCHED_STATS_FORMAT,
238                                         sched->lcore_id,
239                                         "rd",
240                                         "wr",
241                                         "present",
242                                         "nb preallocs",
243                                         "capacity");
244                         _lthread_queue_display(sched->ready);
245                         _lthread_queue_display(sched->pready);
246                         _qnode_pool_display(sched->qnode_pool);
247                         _objcache_display(sched->lthread_cache);
248                         _objcache_display(sched->stack_cache);
249                         _objcache_display(sched->tls_cache);
250                         _objcache_display(sched->per_lthread_cache);
251                         _objcache_display(sched->cond_cache);
252                         _objcache_display(sched->mutex_cache);
253                 fflush(stdout);
254                 }
255         }
256         _sched_stats_consistency_check();
257 #else
258         RTE_LOG(INFO, LTHREAD,
259                 "lthread diagnostics disabled\n"
260                 "hint - set LTHREAD_DIAG in lthread_diag_api.h\n");
261 #endif
262 }
263
264 /*
265  * Defafult diagnostic callback
266  */
267 static uint64_t
268 _lthread_diag_default_cb(uint64_t time, struct lthread *lt, int diag_event,
269                 uint64_t diag_ref, const char *text, uint64_t p1, uint64_t p2)
270 {
271         uint64_t _p2;
272         int lcore = (int) rte_lcore_id();
273
274         switch (diag_event) {
275         case LT_DIAG_LTHREAD_CREATE:
276         case LT_DIAG_MUTEX_CREATE:
277         case LT_DIAG_COND_CREATE:
278                 _p2 = dummy_ref;
279                 break;
280         default:
281                 _p2 = p2;
282                 break;
283         }
284
285         printf("%"PRIu64" %d %8.8lx %8.8lx %s %8.8lx %8.8lx\n",
286                 time,
287                 lcore,
288                 (uint64_t) lt,
289                 diag_ref,
290                 text,
291                 p1,
292                 _p2);
293
294         return dummy_ref++;
295 }
296
297 /*
298  * plug in default diag callback with mask off
299  */
300 void _lthread_diag_ctor(void)__attribute__((constructor));
301 void _lthread_diag_ctor(void)
302 {
303         diag_cb = _lthread_diag_default_cb;
304         diag_mask = 0;
305 }
306
307
308 /*
309  * enable diagnostics
310  */
311 void lthread_diagnostic_enable(DIAG_USED diag_callback cb,
312                                 DIAG_USED uint64_t mask)
313 {
314 #if LTHREAD_DIAG
315         if (cb == NULL)
316                 diag_cb = _lthread_diag_default_cb;
317         else
318                 diag_cb = cb;
319         diag_mask = mask;
320 #else
321         RTE_LOG(INFO, LTHREAD,
322                 "LTHREAD_DIAG is not set, see lthread_diag_api.h\n");
323 #endif
324 }