]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/dpdk/examples/performance-thread/common/lthread_diag.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / seastar / dpdk / 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_log.h>
35 #include <rte_common.h>
36
37 #include "lthread_diag.h"
38 #include "lthread_queue.h"
39 #include "lthread_pool.h"
40 #include "lthread_objcache.h"
41 #include "lthread_sched.h"
42 #include "lthread_diag_api.h"
43
44
45 /* dummy ref value of default diagnostic callback */
46 static uint64_t dummy_ref;
47
48 #define DIAG_SCHED_STATS_FORMAT \
49 "core %d\n%33s %12s %12s %12s %12s\n"
50
51 #define DIAG_CACHE_STATS_FORMAT \
52 "%20s %12lu %12lu %12lu %12lu %12lu\n"
53
54 #define DIAG_QUEUE_STATS_FORMAT \
55 "%20s %12lu %12lu %12lu\n"
56
57
58 /*
59 * texts used in diagnostic events,
60 * corresponding diagnostic mask bit positions are given as comment
61 */
62 const char *diag_event_text[] = {
63 "LTHREAD_CREATE ", /* 00 */
64 "LTHREAD_EXIT ", /* 01 */
65 "LTHREAD_JOIN ", /* 02 */
66 "LTHREAD_CANCEL ", /* 03 */
67 "LTHREAD_DETACH ", /* 04 */
68 "LTHREAD_FREE ", /* 05 */
69 "LTHREAD_SUSPENDED ", /* 06 */
70 "LTHREAD_YIELD ", /* 07 */
71 "LTHREAD_RESCHEDULED", /* 08 */
72 "LTHREAD_SLEEP ", /* 09 */
73 "LTHREAD_RESUMED ", /* 10 */
74 "LTHREAD_AFFINITY ", /* 11 */
75 "LTHREAD_TMR_START ", /* 12 */
76 "LTHREAD_TMR_DELETE ", /* 13 */
77 "LTHREAD_TMR_EXPIRED", /* 14 */
78 "COND_CREATE ", /* 15 */
79 "COND_DESTROY ", /* 16 */
80 "COND_WAIT ", /* 17 */
81 "COND_SIGNAL ", /* 18 */
82 "COND_BROADCAST ", /* 19 */
83 "MUTEX_CREATE ", /* 20 */
84 "MUTEX_DESTROY ", /* 21 */
85 "MUTEX_LOCK ", /* 22 */
86 "MUTEX_TRYLOCK ", /* 23 */
87 "MUTEX_BLOCKED ", /* 24 */
88 "MUTEX_UNLOCKED ", /* 25 */
89 "SCHED_CREATE ", /* 26 */
90 "SCHED_SHUTDOWN " /* 27 */
91 };
92
93
94 /*
95 * set diagnostic ,ask
96 */
97 void lthread_diagnostic_set_mask(DIAG_USED uint64_t mask)
98 {
99 #if LTHREAD_DIAG
100 diag_mask = mask;
101 #else
102 RTE_LOG(INFO, LTHREAD,
103 "LTHREAD_DIAG is not set, see lthread_diag_api.h\n");
104 #endif
105 }
106
107
108 /*
109 * Check consistency of the scheduler stats
110 * Only sensible run after the schedulers are stopped
111 * Count the number of objects lying in caches and queues
112 * and available in the qnode pool.
113 * This should be equal to the total capacity of all
114 * qnode pools.
115 */
116 void
117 _sched_stats_consistency_check(void);
118 void
119 _sched_stats_consistency_check(void)
120 {
121 #if LTHREAD_DIAG
122 int i;
123 struct lthread_sched *sched;
124 uint64_t count = 0;
125 uint64_t capacity = 0;
126
127 for (i = 0; i < LTHREAD_MAX_LCORES; i++) {
128 sched = schedcore[i];
129 if (sched == NULL)
130 continue;
131
132 /* each of these queues consumes a stub node */
133 count += 8;
134 count += DIAG_COUNT(sched->ready, size);
135 count += DIAG_COUNT(sched->pready, size);
136 count += DIAG_COUNT(sched->lthread_cache, available);
137 count += DIAG_COUNT(sched->stack_cache, available);
138 count += DIAG_COUNT(sched->tls_cache, available);
139 count += DIAG_COUNT(sched->per_lthread_cache, available);
140 count += DIAG_COUNT(sched->cond_cache, available);
141 count += DIAG_COUNT(sched->mutex_cache, available);
142
143 /* the node pool does not consume a stub node */
144 if (sched->qnode_pool->fast_alloc != NULL)
145 count++;
146 count += DIAG_COUNT(sched->qnode_pool, available);
147
148 capacity += DIAG_COUNT(sched->qnode_pool, capacity);
149 }
150 if (count != capacity) {
151 RTE_LOG(CRIT, LTHREAD,
152 "Scheduler caches are inconsistent\n");
153 } else {
154 RTE_LOG(INFO, LTHREAD,
155 "Scheduler caches are ok\n");
156 }
157 #endif
158 }
159
160
161 #if LTHREAD_DIAG
162 /*
163 * Display node pool stats
164 */
165 static inline void
166 _qnode_pool_display(DIAG_USED struct qnode_pool *p)
167 {
168
169 printf(DIAG_CACHE_STATS_FORMAT,
170 p->name,
171 DIAG_COUNT(p, rd),
172 DIAG_COUNT(p, wr),
173 DIAG_COUNT(p, available),
174 DIAG_COUNT(p, prealloc),
175 DIAG_COUNT(p, capacity));
176 fflush(stdout);
177 }
178 #endif
179
180
181 #if LTHREAD_DIAG
182 /*
183 * Display queue stats
184 */
185 static inline void
186 _lthread_queue_display(DIAG_USED struct lthread_queue *q)
187 {
188 #if DISPLAY_OBJCACHE_QUEUES
189 printf(DIAG_QUEUE_STATS_FORMAT,
190 q->name,
191 DIAG_COUNT(q, rd),
192 DIAG_COUNT(q, wr),
193 DIAG_COUNT(q, size));
194 fflush(stdout);
195 #else
196 printf("%s: queue stats disabled\n",
197 q->name);
198
199 #endif
200 }
201 #endif
202
203 #if LTHREAD_DIAG
204 /*
205 * Display objcache stats
206 */
207 static inline void
208 _objcache_display(DIAG_USED struct lthread_objcache *c)
209 {
210
211 printf(DIAG_CACHE_STATS_FORMAT,
212 c->name,
213 DIAG_COUNT(c, rd),
214 DIAG_COUNT(c, wr),
215 DIAG_COUNT(c, available),
216 DIAG_COUNT(c, prealloc),
217 DIAG_COUNT(c, capacity));
218 _lthread_queue_display(c->q);
219 fflush(stdout);
220 }
221 #endif
222
223 /*
224 * Display sched stats
225 */
226 void
227 lthread_sched_stats_display(void)
228 {
229 #if LTHREAD_DIAG
230 int i;
231 struct lthread_sched *sched;
232
233 for (i = 0; i < LTHREAD_MAX_LCORES; i++) {
234 sched = schedcore[i];
235 if (sched != NULL) {
236 printf(DIAG_SCHED_STATS_FORMAT,
237 sched->lcore_id,
238 "rd",
239 "wr",
240 "present",
241 "nb preallocs",
242 "capacity");
243 _lthread_queue_display(sched->ready);
244 _lthread_queue_display(sched->pready);
245 _qnode_pool_display(sched->qnode_pool);
246 _objcache_display(sched->lthread_cache);
247 _objcache_display(sched->stack_cache);
248 _objcache_display(sched->tls_cache);
249 _objcache_display(sched->per_lthread_cache);
250 _objcache_display(sched->cond_cache);
251 _objcache_display(sched->mutex_cache);
252 fflush(stdout);
253 }
254 }
255 _sched_stats_consistency_check();
256 #else
257 RTE_LOG(INFO, LTHREAD,
258 "lthread diagnostics disabled\n"
259 "hint - set LTHREAD_DIAG in lthread_diag_api.h\n");
260 #endif
261 }
262
263 /*
264 * Defafult diagnostic callback
265 */
266 static uint64_t
267 _lthread_diag_default_cb(uint64_t time, struct lthread *lt, int diag_event,
268 uint64_t diag_ref, const char *text, uint64_t p1, uint64_t p2)
269 {
270 uint64_t _p2;
271 int lcore = (int) rte_lcore_id();
272
273 switch (diag_event) {
274 case LT_DIAG_LTHREAD_CREATE:
275 case LT_DIAG_MUTEX_CREATE:
276 case LT_DIAG_COND_CREATE:
277 _p2 = dummy_ref;
278 break;
279 default:
280 _p2 = p2;
281 break;
282 }
283
284 printf("%"PRIu64" %d %8.8lx %8.8lx %s %8.8lx %8.8lx\n",
285 time,
286 lcore,
287 (uint64_t) lt,
288 diag_ref,
289 text,
290 p1,
291 _p2);
292
293 return dummy_ref++;
294 }
295
296 /*
297 * plug in default diag callback with mask off
298 */
299 void _lthread_diag_ctor(void)__attribute__((constructor));
300 void _lthread_diag_ctor(void)
301 {
302 diag_cb = _lthread_diag_default_cb;
303 diag_mask = 0;
304 }
305
306
307 /*
308 * enable diagnostics
309 */
310 void lthread_diagnostic_enable(DIAG_USED diag_callback cb,
311 DIAG_USED uint64_t mask)
312 {
313 #if LTHREAD_DIAG
314 if (cb == NULL)
315 diag_cb = _lthread_diag_default_cb;
316 else
317 diag_cb = cb;
318 diag_mask = mask;
319 #else
320 RTE_LOG(INFO, LTHREAD,
321 "LTHREAD_DIAG is not set, see lthread_diag_api.h\n");
322 #endif
323 }