Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2020 Marvell International Ltd.
3 : : */
4 : :
5 : : #include <stdlib.h>
6 : : #include <fnmatch.h>
7 : : #include <pthread.h>
8 : : #include <sys/queue.h>
9 : : #include <regex.h>
10 : :
11 : : #include <rte_common.h>
12 : : #include <rte_errno.h>
13 : : #include <rte_lcore.h>
14 : : #include <rte_per_lcore.h>
15 : : #include <rte_string_fns.h>
16 : :
17 : : #include <eal_export.h>
18 : : #include "eal_trace.h"
19 : :
20 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(per_lcore_trace_point_sz, 20.05)
21 : : RTE_DEFINE_PER_LCORE(volatile int, trace_point_sz);
22 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(per_lcore_trace_mem, 20.05)
23 : : RTE_DEFINE_PER_LCORE(void *, trace_mem);
24 : : static RTE_DEFINE_PER_LCORE(char *, ctf_field);
25 : :
26 : : static struct trace_point_head tp_list = STAILQ_HEAD_INITIALIZER(tp_list);
27 : : static struct trace trace = { .args = STAILQ_HEAD_INITIALIZER(trace.args), };
28 : :
29 : : struct trace *
30 : 2963 : trace_obj_get(void)
31 : : {
32 : 2963 : return &trace;
33 : : }
34 : :
35 : : struct trace_point_head *
36 : 107002 : trace_list_head_get(void)
37 : : {
38 : 107002 : return &tp_list;
39 : : }
40 : :
41 : : int
42 : 200 : eal_trace_init(void)
43 : : {
44 : : struct trace_arg *arg;
45 : :
46 : : /* Trace memory should start with 8B aligned for natural alignment */
47 : : RTE_BUILD_BUG_ON((offsetof(struct __rte_trace_header, mem) % 8) != 0);
48 : :
49 : : /* One of the trace point registration failed */
50 [ - + ]: 200 : if (trace.register_errno) {
51 : 0 : rte_errno = trace.register_errno;
52 : 0 : goto fail;
53 : : }
54 : :
55 : : rte_spinlock_init(&trace.lock);
56 : :
57 : : /* Is duplicate trace name registered */
58 [ - + ]: 200 : if (trace_has_duplicate_entry())
59 : 0 : goto fail;
60 : :
61 : : /* Generate UUID ver 4 with total size of events and number of
62 : : * events
63 : : */
64 : 200 : trace_uuid_generate();
65 : :
66 : : /* Apply buffer size configuration for trace output */
67 : 200 : trace_bufsz_args_apply();
68 : :
69 : : /* Generate CTF TDSL metadata */
70 [ - + ]: 200 : if (trace_metadata_create() < 0)
71 : 0 : goto fail;
72 : :
73 : : /* Save current epoch timestamp for future use */
74 [ - + ]: 200 : if (trace_epoch_time_save() < 0)
75 : 0 : goto free_meta;
76 : :
77 : : /* Apply global configurations */
78 [ + + ]: 201 : STAILQ_FOREACH(arg, &trace.args, next)
79 : 1 : trace_args_apply(arg->val);
80 : :
81 : 200 : rte_trace_mode_set(trace.mode);
82 : :
83 : 200 : return 0;
84 : :
85 : : free_meta:
86 : 0 : trace_metadata_destroy();
87 : 0 : fail:
88 : 0 : trace_err("failed to initialize trace [%s]", rte_strerror(rte_errno));
89 : 0 : return -rte_errno;
90 : : }
91 : :
92 : : void
93 : 253 : eal_trace_fini(void)
94 : : {
95 : 253 : trace_mem_free();
96 : 253 : trace_metadata_destroy();
97 : 253 : eal_trace_args_free();
98 : 253 : }
99 : :
100 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_is_enabled, 20.05)
101 : : bool
102 : 809 : rte_trace_is_enabled(void)
103 : : {
104 : 809 : return rte_atomic_load_explicit(&trace.status, rte_memory_order_acquire) != 0;
105 : : }
106 : :
107 : : static void
108 : 244188 : trace_mode_set(rte_trace_point_t *t, enum rte_trace_mode mode)
109 : : {
110 [ + + ]: 244188 : if (mode == RTE_TRACE_MODE_OVERWRITE)
111 : 243124 : rte_atomic_fetch_and_explicit(t, ~__RTE_TRACE_FIELD_ENABLE_DISCARD,
112 : : rte_memory_order_release);
113 : : else
114 : 1064 : rte_atomic_fetch_or_explicit(t, __RTE_TRACE_FIELD_ENABLE_DISCARD,
115 : : rte_memory_order_release);
116 : 244188 : }
117 : :
118 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_mode_set, 20.05)
119 : : void
120 : 206 : rte_trace_mode_set(enum rte_trace_mode mode)
121 : : {
122 : : struct trace_point *tp;
123 : :
124 [ + + ]: 109798 : STAILQ_FOREACH(tp, &tp_list, next)
125 : 109592 : trace_mode_set(tp->handle, mode);
126 : :
127 : 206 : trace.mode = mode;
128 : 206 : }
129 : :
130 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_mode_get, 20.05)
131 : : enum
132 : 8 : rte_trace_mode rte_trace_mode_get(void)
133 : : {
134 : 8 : return trace.mode;
135 : : }
136 : :
137 : : static bool
138 : : trace_point_is_invalid(rte_trace_point_t *t)
139 : : {
140 [ - + - + : 1628 : return (t == NULL) || (trace_id_get(t) >= trace.nb_trace_points);
- + ]
141 : : }
142 : :
143 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_point_is_enabled, 20.05)
144 : : bool
145 [ + - ]: 1076 : rte_trace_point_is_enabled(rte_trace_point_t *t)
146 : : {
147 : : uint64_t val;
148 : :
149 [ + - ]: 1076 : if (trace_point_is_invalid(t))
150 : : return false;
151 : :
152 : 1076 : val = rte_atomic_load_explicit(t, rte_memory_order_acquire);
153 : 1076 : return (val & __RTE_TRACE_FIELD_ENABLE_MASK) != 0;
154 : : }
155 : :
156 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_point_enable, 20.05)
157 : : int
158 [ + - ]: 542 : rte_trace_point_enable(rte_trace_point_t *t)
159 : : {
160 : : uint64_t prev;
161 : :
162 [ + - ]: 542 : if (trace_point_is_invalid(t))
163 : : return -ERANGE;
164 : :
165 : 542 : prev = rte_atomic_fetch_or_explicit(t, __RTE_TRACE_FIELD_ENABLE_MASK,
166 : : rte_memory_order_release);
167 [ + - ]: 542 : if ((prev & __RTE_TRACE_FIELD_ENABLE_MASK) == 0)
168 : 542 : rte_atomic_fetch_add_explicit(&trace.status, 1, rte_memory_order_release);
169 : : return 0;
170 : : }
171 : :
172 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_point_disable, 20.05)
173 : : int
174 [ + - ]: 10 : rte_trace_point_disable(rte_trace_point_t *t)
175 : : {
176 : : uint64_t prev;
177 : :
178 [ + - ]: 10 : if (trace_point_is_invalid(t))
179 : : return -ERANGE;
180 : :
181 : 10 : prev = rte_atomic_fetch_and_explicit(t, ~__RTE_TRACE_FIELD_ENABLE_MASK,
182 : : rte_memory_order_release);
183 [ + + ]: 10 : if ((prev & __RTE_TRACE_FIELD_ENABLE_MASK) != 0)
184 : 8 : rte_atomic_fetch_sub_explicit(&trace.status, 1, rte_memory_order_release);
185 : : return 0;
186 : : }
187 : :
188 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_pattern, 20.05)
189 : : int
190 : 6 : rte_trace_pattern(const char *pattern, bool enable)
191 : : {
192 : : struct trace_point *tp;
193 : : int rc = 0, found = 0;
194 : :
195 [ + + ]: 3198 : STAILQ_FOREACH(tp, &tp_list, next) {
196 [ + + ]: 3192 : if (fnmatch(pattern, tp->name, 0) != 0)
197 : 3184 : continue;
198 : :
199 [ + + ]: 8 : if (enable)
200 : 4 : rc = rte_trace_point_enable(tp->handle);
201 : : else
202 : 4 : rc = rte_trace_point_disable(tp->handle);
203 [ + - ]: 8 : if (rc < 0) {
204 : : found = 0;
205 : : break;
206 : : }
207 : : found = 1;
208 : : }
209 : :
210 : 6 : return rc | found;
211 : : }
212 : :
213 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_regexp, 20.05)
214 : : int
215 : 7 : rte_trace_regexp(const char *regex, bool enable)
216 : : {
217 : : struct trace_point *tp;
218 : : int rc = 0, found = 0;
219 : : regex_t r;
220 : :
221 [ + - ]: 7 : if (regcomp(&r, regex, 0) != 0)
222 : : return -EINVAL;
223 : :
224 [ + + ]: 3731 : STAILQ_FOREACH(tp, &tp_list, next) {
225 [ + + ]: 3724 : if (regexec(&r, tp->name, 0, NULL, 0) != 0)
226 : 3184 : continue;
227 : :
228 [ + + ]: 540 : if (enable)
229 : 536 : rc = rte_trace_point_enable(tp->handle);
230 : : else
231 : 4 : rc = rte_trace_point_disable(tp->handle);
232 [ + - ]: 540 : if (rc < 0) {
233 : : found = 0;
234 : : break;
235 : : }
236 : : found = 1;
237 : : }
238 : 7 : regfree(&r);
239 : :
240 : 7 : return rc | found;
241 : : }
242 : :
243 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_point_lookup, 20.05)
244 : : rte_trace_point_t *
245 : 4 : rte_trace_point_lookup(const char *name)
246 : : {
247 : : struct trace_point *tp;
248 : :
249 [ + - ]: 4 : if (name == NULL)
250 : : return NULL;
251 : :
252 [ + + ]: 1068 : STAILQ_FOREACH(tp, &tp_list, next)
253 [ + + ]: 1066 : if (strcmp(tp->name, name) == 0)
254 : 2 : return tp->handle;
255 : :
256 : : return NULL;
257 : : }
258 : :
259 : : static void
260 : 1064 : trace_point_dump(FILE *f, struct trace_point *tp)
261 : : {
262 : 1064 : rte_trace_point_t *handle = tp->handle;
263 : :
264 [ + + ]: 1064 : fprintf(f, "\tid %d, %s, size is %d, %s\n",
265 : : trace_id_get(handle), tp->name,
266 : 1064 : (uint16_t)(*handle & __RTE_TRACE_FIELD_SIZE_MASK),
267 : 1064 : rte_trace_point_is_enabled(handle) ? "enabled" : "disabled");
268 : 1064 : }
269 : :
270 : : static void
271 : 2 : trace_lcore_mem_dump(FILE *f)
272 : : {
273 : 2 : struct trace *trace = trace_obj_get();
274 : : struct __rte_trace_header *header;
275 : : uint32_t count;
276 : :
277 : 2 : rte_spinlock_lock(&trace->lock);
278 [ - + ]: 2 : if (trace->nb_trace_mem_list == 0)
279 : 0 : goto out;
280 : : fprintf(f, "nb_trace_mem_list = %d\n", trace->nb_trace_mem_list);
281 : : fprintf(f, "\nTrace mem info\n--------------\n");
282 [ + + ]: 7 : for (count = 0; count < trace->nb_trace_mem_list; count++) {
283 : 5 : header = trace->lcore_meta[count].mem;
284 : 5 : fprintf(f, "\tid %d, mem=%p, area=%s, lcore_id=%d, name=%s\n",
285 : : count, header,
286 : : trace_area_to_string(trace->lcore_meta[count].area),
287 : : header->stream_header.lcore_id,
288 : 5 : header->stream_header.thread_name);
289 : : }
290 : 2 : out:
291 : : rte_spinlock_unlock(&trace->lock);
292 : 2 : }
293 : :
294 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_dump, 20.05)
295 : : void
296 : 2 : rte_trace_dump(FILE *f)
297 : : {
298 : 2 : struct trace_point_head *tp_list = trace_list_head_get();
299 : 2 : struct trace *trace = trace_obj_get();
300 : : struct trace_point *tp;
301 : :
302 : : fprintf(f, "\nGlobal info\n-----------\n");
303 [ - + ]: 2 : fprintf(f, "status = %s\n",
304 : 2 : rte_trace_is_enabled() ? "enabled" : "disabled");
305 : 2 : fprintf(f, "mode = %s\n",
306 : : trace_mode_to_string(rte_trace_mode_get()));
307 : 2 : fprintf(f, "dir = %s\n", trace->dir);
308 : 2 : fprintf(f, "buffer len = %d\n", trace->buff_len);
309 : 2 : fprintf(f, "number of trace points = %d\n", trace->nb_trace_points);
310 : :
311 : 2 : trace_lcore_mem_dump(f);
312 : : fprintf(f, "\nTrace point info\n----------------\n");
313 [ + + ]: 1066 : STAILQ_FOREACH(tp, tp_list, next)
314 : 1064 : trace_point_dump(f, tp);
315 : 2 : }
316 : :
317 : : static void
318 : : thread_get_name(rte_thread_t id, char *name, size_t len)
319 : : {
320 : : #if defined(RTE_EXEC_ENV_LINUX) && defined(__GLIBC__) && defined(__GLIBC_PREREQ)
321 : : #if __GLIBC_PREREQ(2, 12)
322 : 5 : pthread_getname_np((pthread_t)id.opaque_id, name, len);
323 : : #endif
324 : : #endif
325 : : RTE_SET_USED(id);
326 : : RTE_SET_USED(name);
327 : : RTE_SET_USED(len);
328 : : }
329 : :
330 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(__rte_trace_mem_per_thread_alloc, 20.05)
331 : : void
332 : 807 : __rte_trace_mem_per_thread_alloc(void)
333 : : {
334 : 807 : struct trace *trace = trace_obj_get();
335 : : struct __rte_trace_header *header;
336 : : uint32_t count;
337 : :
338 [ + + ]: 807 : if (!rte_trace_is_enabled())
339 : 802 : return;
340 : :
341 [ + - ]: 5 : if (RTE_PER_LCORE(trace_mem))
342 : : return;
343 : :
344 : 5 : rte_spinlock_lock(&trace->lock);
345 : :
346 : 5 : count = trace->nb_trace_mem_list;
347 : :
348 : : /* Allocate room for storing the thread trace mem meta */
349 : 5 : trace->lcore_meta = realloc(trace->lcore_meta,
350 : 5 : sizeof(trace->lcore_meta[0]) * (count + 1));
351 : :
352 : : /* Provide dummy space for fast path to consume */
353 [ - + ]: 5 : if (trace->lcore_meta == NULL) {
354 : 0 : trace_crit("trace mem meta memory realloc failed");
355 : : header = NULL;
356 : 0 : goto fail;
357 : : }
358 : :
359 : : /* First attempt from huge page */
360 : 5 : header = eal_malloc_no_trace(NULL, trace_mem_sz(trace->buff_len), 8);
361 [ + + ]: 5 : if (header) {
362 : 3 : trace->lcore_meta[count].area = TRACE_AREA_HUGEPAGE;
363 : 3 : goto found;
364 : : }
365 : :
366 : : /* Second attempt from heap with proper alignment */
367 : 2 : size_t mem_size = trace_mem_sz(trace->buff_len);
368 : 2 : void *aligned_ptr = NULL;
369 : 2 : int ret = posix_memalign(&aligned_ptr, 8, mem_size);
370 [ + - ]: 2 : header = (ret == 0) ? aligned_ptr : NULL;
371 [ - + ]: 2 : if (header == NULL) {
372 : 0 : trace_crit("trace mem malloc attempt failed");
373 : : header = NULL;
374 : 0 : goto fail;
375 : :
376 : : }
377 : :
378 : : /* Second attempt from heap is success */
379 : 2 : trace->lcore_meta[count].area = TRACE_AREA_HEAP;
380 : :
381 : : /* Initialize the trace header */
382 : 5 : found:
383 : 5 : header->offset = 0;
384 : 5 : header->len = trace->buff_len;
385 : 5 : header->stream_header.magic = TRACE_CTF_MAGIC;
386 : 5 : rte_uuid_copy(header->stream_header.uuid, trace->uuid);
387 : 5 : header->stream_header.lcore_id = rte_lcore_id();
388 : :
389 : : /* Store the thread name */
390 : 5 : char *name = header->stream_header.thread_name;
391 : : memset(name, 0, __RTE_TRACE_EMIT_STRING_LEN_MAX);
392 : 5 : thread_get_name(rte_thread_self(), name,
393 : : __RTE_TRACE_EMIT_STRING_LEN_MAX);
394 : :
395 : 5 : trace->lcore_meta[count].mem = header;
396 : 5 : trace->nb_trace_mem_list++;
397 : 5 : fail:
398 : 5 : RTE_PER_LCORE(trace_mem) = header;
399 : : rte_spinlock_unlock(&trace->lock);
400 : : }
401 : :
402 : : static void
403 : 5 : trace_mem_per_thread_free_unlocked(struct thread_mem_meta *meta)
404 : : {
405 [ + + ]: 5 : if (meta->area == TRACE_AREA_HUGEPAGE)
406 : 3 : eal_free_no_trace(meta->mem);
407 [ + - ]: 2 : else if (meta->area == TRACE_AREA_HEAP)
408 : 2 : free(meta->mem);
409 : 5 : }
410 : :
411 : : void
412 : 129 : trace_mem_per_thread_free(void)
413 : : {
414 : 129 : struct trace *trace = trace_obj_get();
415 : : struct __rte_trace_header *header;
416 : : uint32_t count;
417 : :
418 : 129 : header = RTE_PER_LCORE(trace_mem);
419 [ - + ]: 129 : if (header == NULL)
420 : : return;
421 : :
422 : 0 : rte_spinlock_lock(&trace->lock);
423 [ # # ]: 0 : for (count = 0; count < trace->nb_trace_mem_list; count++) {
424 [ # # ]: 0 : if (trace->lcore_meta[count].mem == header)
425 : : break;
426 : : }
427 [ # # ]: 0 : if (count != trace->nb_trace_mem_list) {
428 : 0 : struct thread_mem_meta *meta = &trace->lcore_meta[count];
429 : :
430 : 0 : trace_mem_per_thread_free_unlocked(meta);
431 [ # # ]: 0 : if (count != trace->nb_trace_mem_list - 1) {
432 : 0 : memmove(meta, meta + 1,
433 : : sizeof(*meta) *
434 : 0 : (trace->nb_trace_mem_list - count - 1));
435 : : }
436 : 0 : trace->nb_trace_mem_list--;
437 : : }
438 : : rte_spinlock_unlock(&trace->lock);
439 : : }
440 : :
441 : : void
442 : 253 : trace_mem_free(void)
443 : : {
444 : 253 : struct trace *trace = trace_obj_get();
445 : : uint32_t count;
446 : :
447 : 253 : rte_spinlock_lock(&trace->lock);
448 [ + + ]: 258 : for (count = 0; count < trace->nb_trace_mem_list; count++) {
449 : 5 : trace_mem_per_thread_free_unlocked(&trace->lcore_meta[count]);
450 : : }
451 : 253 : trace->nb_trace_mem_list = 0;
452 : : rte_spinlock_unlock(&trace->lock);
453 : 253 : }
454 : :
455 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(__rte_trace_point_emit_field, 20.05)
456 : : void
457 : 502205 : __rte_trace_point_emit_field(size_t sz, const char *in, const char *datatype)
458 : : {
459 : : char *field;
460 : : char *fixup;
461 : : int rc;
462 : :
463 : 502205 : fixup = trace_metadata_fixup_field(in);
464 [ + + ]: 502205 : if (fixup != NULL)
465 : : in = fixup;
466 : 502205 : rc = asprintf(&field, "%s %s %s;\n",
467 [ + + ]: 502205 : RTE_PER_LCORE(ctf_field) != NULL ?
468 : : RTE_PER_LCORE(ctf_field) : "",
469 : : datatype, in);
470 : 502205 : free(RTE_PER_LCORE(ctf_field));
471 : 502205 : free(fixup);
472 [ - + ]: 502205 : if (rc == -1) {
473 : 0 : RTE_PER_LCORE(trace_point_sz) = 0;
474 : 0 : RTE_PER_LCORE(ctf_field) = NULL;
475 : 0 : trace_crit("could not allocate CTF field");
476 : 0 : return;
477 : : }
478 : 502205 : RTE_PER_LCORE(trace_point_sz) += sz;
479 : 502205 : RTE_PER_LCORE(ctf_field) = field;
480 : : }
481 : :
482 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(__rte_trace_point_register, 20.05)
483 : : int
484 : 134596 : __rte_trace_point_register(rte_trace_point_t *handle, const char *name,
485 : : void (*register_fn)(void))
486 : : {
487 : : struct trace_point *tp;
488 : : uint16_t sz;
489 : :
490 : : /* Sanity checks of arguments */
491 [ + - - + ]: 134596 : if (name == NULL || register_fn == NULL || handle == NULL) {
492 : 0 : trace_err("invalid arguments");
493 : 0 : rte_errno = EINVAL;
494 : 0 : goto fail;
495 : : }
496 : :
497 : : /* Check the size of the trace point object */
498 : 134596 : RTE_PER_LCORE(trace_point_sz) = 0;
499 : 134596 : register_fn();
500 [ - + ]: 134596 : if (RTE_PER_LCORE(trace_point_sz) == 0) {
501 : 0 : trace_err("missing rte_trace_emit_header() in register fn");
502 : 0 : rte_errno = EBADF;
503 : 0 : goto fail;
504 : : }
505 : :
506 : : /* Is size overflowed */
507 [ - + ]: 134596 : if (RTE_PER_LCORE(trace_point_sz) > UINT16_MAX) {
508 : 0 : trace_err("trace point size overflowed");
509 : 0 : rte_errno = ENOSPC;
510 : 0 : goto fail;
511 : : }
512 : :
513 : : /* Are we running out of space to store trace points? */
514 [ - + ]: 134596 : if (trace.nb_trace_points > UINT16_MAX) {
515 : 0 : trace_err("trace point exceeds the max count");
516 : 0 : rte_errno = ENOSPC;
517 : 0 : goto fail;
518 : : }
519 : :
520 : : /* Get the size of the trace point */
521 : 134596 : sz = RTE_PER_LCORE(trace_point_sz);
522 : 134596 : tp = calloc(1, sizeof(struct trace_point));
523 [ - + ]: 134596 : if (tp == NULL) {
524 : 0 : trace_err("fail to allocate trace point memory");
525 : 0 : rte_errno = ENOMEM;
526 : 0 : goto fail;
527 : : }
528 : :
529 : : /* Initialize the trace point */
530 : 134596 : tp->name = name;
531 : :
532 : : /* Copy the accumulated fields description and clear it for the next
533 : : * trace point.
534 : : */
535 : 134596 : tp->ctf_field = RTE_PER_LCORE(ctf_field);
536 : 134596 : RTE_PER_LCORE(ctf_field) = NULL;
537 : :
538 : : /* Form the trace handle */
539 : 134596 : *handle = sz;
540 : 134596 : *handle |= trace.nb_trace_points << __RTE_TRACE_FIELD_ID_SHIFT;
541 : 134596 : trace_mode_set(handle, trace.mode);
542 : :
543 : 134596 : trace.nb_trace_points++;
544 : 134596 : tp->handle = handle;
545 : :
546 : : /* Add the trace point at tail */
547 : 134596 : STAILQ_INSERT_TAIL(&tp_list, tp, next);
548 : : rte_atomic_thread_fence(rte_memory_order_release);
549 : :
550 : : /* All Good !!! */
551 : 134596 : return 0;
552 : :
553 : 0 : fail:
554 [ # # ]: 0 : if (trace.register_errno == 0)
555 : 0 : trace.register_errno = rte_errno;
556 : :
557 : 0 : return -rte_errno;
558 : : }
|