summaryrefslogtreecommitdiffstats
path: root/vppinfra/vppinfra/elog.c
diff options
context:
space:
mode:
Diffstat (limited to 'vppinfra/vppinfra/elog.c')
-rw-r--r--vppinfra/vppinfra/elog.c1061
1 files changed, 0 insertions, 1061 deletions
diff --git a/vppinfra/vppinfra/elog.c b/vppinfra/vppinfra/elog.c
deleted file mode 100644
index e9f06d0948c..00000000000
--- a/vppinfra/vppinfra/elog.c
+++ /dev/null
@@ -1,1061 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- Copyright (c) 2005,2009 Eliot Dresselhaus
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include <vppinfra/elog.h>
-#include <vppinfra/cache.h>
-#include <vppinfra/error.h>
-#include <vppinfra/format.h>
-#include <vppinfra/hash.h>
-#include <vppinfra/math.h>
-
-static inline void
-elog_lock (elog_main_t * em)
-{
- if (PREDICT_FALSE (em->lock != 0))
- while (__sync_lock_test_and_set (em->lock, 1))
- ;
-}
-
-static inline void
-elog_unlock (elog_main_t * em)
-{
- if (PREDICT_FALSE (em->lock != 0))
- {
- CLIB_MEMORY_BARRIER ();
- *em->lock = 0;
- }
-}
-
-/* Non-inline version. */
-void *
-elog_event_data (elog_main_t * em,
- elog_event_type_t * type, elog_track_t * track, u64 cpu_time)
-{
- return elog_event_data_inline (em, type, track, cpu_time);
-}
-
-static void
-new_event_type (elog_main_t * em, uword i)
-{
- elog_event_type_t *t = vec_elt_at_index (em->event_types, i);
-
- if (!em->event_type_by_format)
- em->event_type_by_format =
- hash_create_vec ( /* size */ 0, sizeof (u8), sizeof (uword));
-
- hash_set_mem (em->event_type_by_format, t->format, i);
-}
-
-static uword
-find_or_create_type (elog_main_t * em, elog_event_type_t * t)
-{
- uword *p = hash_get_mem (em->event_type_by_format, t->format);
- uword i;
-
- if (p)
- i = p[0];
- else
- {
- i = vec_len (em->event_types);
- vec_add1 (em->event_types, t[0]);
- new_event_type (em, i);
- }
-
- return i;
-}
-
-/* External function to register types. */
-word
-elog_event_type_register (elog_main_t * em, elog_event_type_t * t)
-{
- elog_event_type_t *static_type = t;
- word l;
-
- elog_lock (em);
-
- l = vec_len (em->event_types);
-
- t->type_index_plus_one = 1 + l;
-
- ASSERT (t->format);
-
- /* If format args are not specified try to be smart about providing defaults
- so most of the time user does not have to specify them. */
- if (!t->format_args)
- {
- uword i, l;
- char *this_arg;
-
- l = strlen (t->format);
- for (i = 0; i < l; i++)
- {
- if (t->format[i] != '%')
- continue;
- if (i + 1 >= l)
- continue;
- if (t->format[i + 1] == '%') /* %% */
- continue;
-
- switch (t->format[i + 1])
- {
- default:
- case 'd':
- case 'x':
- case 'u':
- this_arg = "i4"; /* size of u32 */
- break;
- case 'f':
- this_arg = "f8"; /* defaults to f64 */
- break;
- case 's':
- this_arg = "s0"; /* defaults to null terminated string. */
- break;
- }
-
- t->format_args =
- (char *) format ((u8 *) t->format_args, "%s", this_arg);
- }
-
- /* Null terminate. */
- vec_add1 (t->format_args, 0);
- }
-
- vec_add1 (em->event_types, t[0]);
-
- t = em->event_types + l;
-
- /* Make copies of strings for hashing etc. */
- if (t->function)
- t->format = (char *) format (0, "%s %s%c", t->function, t->format, 0);
- else
- t->format = (char *) format (0, "%s%c", t->format, 0);
-
- t->format_args = (char *) format (0, "%s%c", t->format_args, 0);
-
- /* Construct string table. */
- {
- uword i;
- t->n_enum_strings = static_type->n_enum_strings;
- for (i = 0; i < t->n_enum_strings; i++)
- {
- if (!static_type->enum_strings[i])
- static_type->enum_strings[i] = "MISSING";
- vec_add1 (t->enum_strings_vector,
- (char *) format (0, "%s%c", static_type->enum_strings[i],
- 0));
- }
- }
-
- new_event_type (em, l);
- elog_unlock (em);
-
- return l;
-}
-
-word
-elog_track_register (elog_main_t * em, elog_track_t * t)
-{
- word l;
-
- elog_lock (em);
-
- l = vec_len (em->tracks);
-
- t->track_index_plus_one = 1 + l;
-
- ASSERT (t->name);
-
- vec_add1 (em->tracks, t[0]);
-
- t = em->tracks + l;
-
- t->name = (char *) format (0, "%s%c", t->name, 0);
-
- elog_unlock (em);
-
- return l;
-}
-
-static uword
-parse_2digit_decimal (char *p, uword * number)
-{
- uword i = 0;
- u8 digits[2];
-
- digits[0] = digits[1] = 0;
- while (p[i] >= '0' && p[i] <= '9')
- {
- if (i >= 2)
- break;
- digits[i] = p[i] - '0';
- i++;
- }
-
- if (i >= 1 && i <= 2)
- {
- if (i == 1)
- *number = digits[0];
- else
- *number = 10 * digits[0] + digits[1];
- return i;
- }
- else
- return 0;
-}
-
-static u8 *
-fixed_format (u8 * s, char *fmt, char *result, uword * result_len)
-{
- char *f = fmt;
- char *percent;
- uword l = 0;
-
- while (1)
- {
- if (f[0] == 0)
- break;
- if (f[0] == '%' && f[1] != '%')
- break;
- f++;
- }
- if (f > fmt)
- vec_add (s, fmt, f - fmt);
-
- if (f[0] != '%')
- goto done;
-
- /* Skip percent. */
- percent = f++;
-
- /* Skip possible +-= justification. */
- f += f[0] == '+' || f[0] == '-' || f[0] == '=';
-
- /* Skip possible X.Y width. */
- while ((f[0] >= '0' && f[0] <= '9') || f[0] == '.')
- f++;
-
- /* Skip wlL as in e.g. %Ld. */
- f += f[0] == 'w' || f[0] == 'l' || f[0] == 'L';
-
- /* Finally skip format letter. */
- f += f[0] != 0;
-
- ASSERT (*result_len > f - percent);
- l = clib_min (f - percent, *result_len - 1);
- clib_memcpy (result, percent, l);
- result[l] = 0;
-
-done:
- *result_len = f - fmt;
- return s;
-}
-
-u8 *
-format_elog_event (u8 * s, va_list * va)
-{
- elog_main_t *em = va_arg (*va, elog_main_t *);
- elog_event_t *e = va_arg (*va, elog_event_t *);
- elog_event_type_t *t;
- char *a, *f;
- void *d = (u8 *) e->data;
- char arg_format[64];
-
- t = vec_elt_at_index (em->event_types, e->type);
-
- f = t->format;
- a = t->format_args;
- while (1)
- {
- uword n_bytes = 0, n_digits, f_bytes = 0;
-
- f_bytes = sizeof (arg_format);
- s = fixed_format (s, f, arg_format, &f_bytes);
- f += f_bytes;
-
- if (a == 0 || a[0] == 0)
- {
- /* Format must also be at end. */
- ASSERT (f[0] == 0);
- break;
- }
-
- /* Don't go past end of event data. */
- ASSERT (d < (void *) (e->data + sizeof (e->data)));
-
- n_digits = parse_2digit_decimal (a + 1, &n_bytes);
- switch (a[0])
- {
- case 'i':
- case 't':
- case 'T':
- {
- u32 i = 0;
- u64 l = 0;
-
- if (n_bytes == 1)
- i = ((u8 *) d)[0];
- else if (n_bytes == 2)
- i = clib_mem_unaligned (d, u16);
- else if (n_bytes == 4)
- i = clib_mem_unaligned (d, u32);
- else if (n_bytes == 8)
- l = clib_mem_unaligned (d, u64);
- else
- ASSERT (0);
- if (a[0] == 't')
- {
- char *e =
- vec_elt (t->enum_strings_vector, n_bytes == 8 ? l : i);
- s = format (s, arg_format, e);
- }
- else if (a[0] == 'T')
- {
- char *e =
- vec_elt_at_index (em->string_table, n_bytes == 8 ? l : i);
- s = format (s, arg_format, e);
- }
- else if (n_bytes == 8)
- s = format (s, arg_format, l);
- else
- s = format (s, arg_format, i);
- }
- break;
-
- case 'f':
- {
- f64 x = 0;
- if (n_bytes == 4)
- x = clib_mem_unaligned (d, f32);
- else if (n_bytes == 8)
- x = clib_mem_unaligned (d, f64);
- else
- ASSERT (0);
- s = format (s, arg_format, x);
- }
- break;
-
- case 's':
- s = format (s, arg_format, d);
- if (n_bytes == 0)
- n_bytes = strlen (d) + 1;
- break;
-
- default:
- ASSERT (0);
- break;
- }
-
- ASSERT (n_digits > 0 && n_digits <= 2);
- a += 1 + n_digits;
- d += n_bytes;
- }
-
- return s;
-}
-
-u8 *
-format_elog_track (u8 * s, va_list * va)
-{
- elog_main_t *em = va_arg (*va, elog_main_t *);
- elog_event_t *e = va_arg (*va, elog_event_t *);
- elog_track_t *t = vec_elt_at_index (em->tracks, e->track);
- return format (s, "%s", t->name);
-}
-
-void
-elog_time_now (elog_time_stamp_t * et)
-{
- u64 cpu_time_now, os_time_now_nsec;
-
-#ifdef CLIB_UNIX
- {
-#include <sys/syscall.h>
- struct timespec ts;
- syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
- cpu_time_now = clib_cpu_time_now ();
- os_time_now_nsec = 1e9 * ts.tv_sec + ts.tv_nsec;
- }
-#else
- cpu_time_now = clib_cpu_time_now ();
- os_time_now_nsec = 0;
-#endif
-
- et->cpu = cpu_time_now;
- et->os_nsec = os_time_now_nsec;
-}
-
-always_inline i64
-elog_time_stamp_diff_os_nsec (elog_time_stamp_t * t1, elog_time_stamp_t * t2)
-{
- return (i64) t1->os_nsec - (i64) t2->os_nsec;
-}
-
-always_inline i64
-elog_time_stamp_diff_cpu (elog_time_stamp_t * t1, elog_time_stamp_t * t2)
-{
- return (i64) t1->cpu - (i64) t2->cpu;
-}
-
-always_inline f64
-elog_nsec_per_clock (elog_main_t * em)
-{
- return ((f64) elog_time_stamp_diff_os_nsec (&em->serialize_time,
- &em->init_time)
- / (f64) elog_time_stamp_diff_cpu (&em->serialize_time,
- &em->init_time));
-}
-
-void
-elog_alloc (elog_main_t * em, u32 n_events)
-{
- if (em->event_ring)
- vec_free (em->event_ring);
-
- /* Ring size must be a power of 2. */
- em->event_ring_size = n_events = max_pow2 (n_events);
-
- /* Leave an empty ievent at end so we can always speculatively write
- and event there (possibly a long form event). */
- vec_resize_aligned (em->event_ring, n_events, CLIB_CACHE_LINE_BYTES);
-}
-
-void
-elog_init (elog_main_t * em, u32 n_events)
-{
- memset (em, 0, sizeof (em[0]));
-
- em->lock = 0;
-
- if (n_events > 0)
- elog_alloc (em, n_events);
-
- clib_time_init (&em->cpu_timer);
-
- em->n_total_events_disable_limit = ~0;
-
- /* Make track 0. */
- em->default_track.name = "default";
- elog_track_register (em, &em->default_track);
-
- elog_time_now (&em->init_time);
-}
-
-/* Returns number of events in ring and start index. */
-static uword
-elog_event_range (elog_main_t * em, uword * lo)
-{
- uword l = em->event_ring_size;
- u64 i = em->n_total_events;
-
- /* Ring never wrapped? */
- if (i <= (u64) l)
- {
- if (lo)
- *lo = 0;
- return i;
- }
- else
- {
- if (lo)
- *lo = i & (l - 1);
- return l;
- }
-}
-
-elog_event_t *
-elog_peek_events (elog_main_t * em)
-{
- elog_event_t *e, *f, *es = 0;
- uword i, j, n;
-
- n = elog_event_range (em, &j);
- for (i = 0; i < n; i++)
- {
- vec_add2 (es, e, 1);
- f = vec_elt_at_index (em->event_ring, j);
- e[0] = f[0];
-
- /* Convert absolute time from cycles to seconds from start. */
- e->time =
- (e->time_cycles -
- em->init_time.cpu) * em->cpu_timer.seconds_per_clock;
-
- j = (j + 1) & (em->event_ring_size - 1);
- }
-
- return es;
-}
-
-/* Add a formatted string to the string table. */
-u32
-elog_string (elog_main_t * em, char *fmt, ...)
-{
- u32 offset;
- va_list va;
-
- va_start (va, fmt);
- offset = vec_len (em->string_table);
- em->string_table = (char *) va_format ((u8 *) em->string_table, fmt, &va);
- va_end (va);
-
- /* Null terminate string if it is not already. */
- if (vec_end (em->string_table)[-1] != 0)
- vec_add1 (em->string_table, 0);
-
- return offset;
-}
-
-elog_event_t *
-elog_get_events (elog_main_t * em)
-{
- if (!em->events)
- em->events = elog_peek_events (em);
- return em->events;
-}
-
-static void
-maybe_fix_string_table_offset (elog_event_t * e,
- elog_event_type_t * t, u32 offset)
-{
- void *d = (u8 *) e->data;
- char *a;
-
- if (offset == 0)
- return;
-
- a = t->format_args;
-
- while (1)
- {
- uword n_bytes = 0, n_digits;
-
- if (a[0] == 0)
- break;
-
- /* Don't go past end of event data. */
- ASSERT (d < (void *) (e->data + sizeof (e->data)));
-
- n_digits = parse_2digit_decimal (a + 1, &n_bytes);
- switch (a[0])
- {
- case 'T':
- ASSERT (n_bytes == 4);
- clib_mem_unaligned (d, u32) += offset;
- break;
-
- case 'i':
- case 't':
- case 'f':
- case 's':
- break;
-
- default:
- ASSERT (0);
- break;
- }
-
- ASSERT (n_digits > 0 && n_digits <= 2);
- a += 1 + n_digits;
- d += n_bytes;
- }
-}
-
-static int
-elog_cmp (void *a1, void *a2)
-{
- elog_event_t *e1 = a1;
- elog_event_t *e2 = a2;
-
- return e1->time - e2->time;
-}
-
-void
-elog_merge (elog_main_t * dst, u8 * dst_tag, elog_main_t * src, u8 * src_tag)
-{
- elog_event_t *e;
- uword l;
- u32 string_table_offset_for_src_events;
- u32 track_offset_for_src_tracks;
- elog_track_t newt;
- int i;
-
- memset (&newt, 0, sizeof (newt));
-
- elog_get_events (src);
- elog_get_events (dst);
-
- string_table_offset_for_src_events = vec_len (dst->string_table);
- vec_append (dst->string_table, src->string_table);
-
- l = vec_len (dst->events);
- vec_add (dst->events, src->events, vec_len (src->events));
-
- /* Prepend the supplied tag (if any) to all dst track names */
- if (dst_tag)
- {
- for (i = 0; i < vec_len (dst->tracks); i++)
- {
- elog_track_t *t = vec_elt_at_index (dst->tracks, i);
- char *new_name;
-
- new_name = (char *) format (0, "%s:%s%c", dst_tag, t->name, 0);
- vec_free (t->name);
- t->name = new_name;
- }
- }
-
- track_offset_for_src_tracks = vec_len (dst->tracks);
-
- /* Copy / tag source tracks */
- for (i = 0; i < vec_len (src->tracks); i++)
- {
- elog_track_t *t = vec_elt_at_index (src->tracks, i);
- if (src_tag)
- newt.name = (char *) format (0, "%s:%s%c", src_tag, t->name, 0);
- else
- newt.name = (char *) format (0, "%s%c", t->name, 0);
- (void) elog_track_register (dst, &newt);
- vec_free (newt.name);
- }
-
- /* Across all (copied) src events... */
- for (e = dst->events + l; e < vec_end (dst->events); e++)
- {
- elog_event_type_t *t = vec_elt_at_index (src->event_types, e->type);
-
- /* Remap type from src -> dst. */
- e->type = find_or_create_type (dst, t);
-
- /* Remap string table offsets for 'T' format args */
- maybe_fix_string_table_offset (e, t,
- string_table_offset_for_src_events);
-
- /* Remap track */
- e->track += track_offset_for_src_tracks;
- }
-
- /* Adjust event times for relative starting times of event streams. */
- {
- f64 dt_event, dt_os_nsec, dt_clock_nsec;
-
- /* Set clock parameters if dst was not generated by unserialize. */
- if (dst->serialize_time.cpu == 0)
- {
- dst->init_time = src->init_time;
- dst->serialize_time = src->serialize_time;
- dst->nsec_per_cpu_clock = src->nsec_per_cpu_clock;
- }
-
- dt_os_nsec =
- elog_time_stamp_diff_os_nsec (&src->init_time, &dst->init_time);
-
- dt_event = dt_os_nsec;
- dt_clock_nsec =
- (elog_time_stamp_diff_cpu (&src->init_time, &dst->init_time) * .5 *
- (dst->nsec_per_cpu_clock + src->nsec_per_cpu_clock));
-
- /* Heuristic to see if src/dst came from same time source.
- If frequencies are "the same" and os clock and cpu clock agree
- to within 100e-9 secs about time difference between src/dst
- init_time, then we use cpu clock. Otherwise we use OS clock. */
- if (fabs (src->nsec_per_cpu_clock - dst->nsec_per_cpu_clock) < 1e-2
- && fabs (dt_os_nsec - dt_clock_nsec) < 100)
- dt_event = dt_clock_nsec;
-
- /* Convert to seconds. */
- dt_event *= 1e-9;
-
- if (dt_event > 0)
- {
- /* Src started after dst. */
- for (e = dst->events + l; e < vec_end (dst->events); e++)
- e->time += dt_event;
- }
- else
- {
- /* Dst started after src. */
- for (e = dst->events + 0; e < dst->events + l; e++)
- e->time += dt_event;
- }
- }
-
- /* Sort events by increasing time. */
- vec_sort_with_function (dst->events, elog_cmp);
-
- /* Recreate the event ring or the results won't serialize */
- {
- int i;
-
- ASSERT (dst->cpu_timer.seconds_per_clock);
-
- elog_alloc (dst, vec_len (dst->events));
- for (i = 0; i < vec_len (dst->events); i++)
- {
- elog_event_t *es, *ed;
-
- es = dst->events + i;
- ed = dst->event_ring + i;
-
- ed[0] = es[0];
-
- /* Invert elog_peek_events calculation */
- ed->time_cycles =
- (es->time / dst->cpu_timer.seconds_per_clock) + dst->init_time.cpu;
- }
- dst->n_total_events = vec_len (dst->events);
- }
-}
-
-static void
-serialize_elog_event (serialize_main_t * m, va_list * va)
-{
- elog_main_t *em = va_arg (*va, elog_main_t *);
- elog_event_t *e = va_arg (*va, elog_event_t *);
- elog_event_type_t *t = vec_elt_at_index (em->event_types, e->type);
- u8 *d = e->data;
- u8 *p = (u8 *) t->format_args;
-
- serialize_integer (m, e->type, sizeof (e->type));
- serialize_integer (m, e->track, sizeof (e->track));
- serialize (m, serialize_f64, e->time);
-
- while (*p)
- {
- uword n_digits, n_bytes = 0;
-
- n_digits = parse_2digit_decimal ((char *) p + 1, &n_bytes);
-
- switch (p[0])
- {
- case 'i':
- case 't':
- case 'T':
- if (n_bytes == 1)
- serialize_integer (m, d[0], sizeof (u8));
- else if (n_bytes == 2)
- serialize_integer (m, clib_mem_unaligned (d, u16), sizeof (u16));
- else if (n_bytes == 4)
- serialize_integer (m, clib_mem_unaligned (d, u32), sizeof (u32));
- else if (n_bytes == 8)
- serialize (m, serialize_64, clib_mem_unaligned (d, u64));
- else
- ASSERT (0);
- break;
-
- case 's':
- serialize_cstring (m, (char *) d);
- if (n_bytes == 0)
- n_bytes = strlen ((char *) d) + 1;
- break;
-
- case 'f':
- if (n_bytes == 4)
- serialize (m, serialize_f32, clib_mem_unaligned (d, f32));
- else if (n_bytes == 8)
- serialize (m, serialize_f64, clib_mem_unaligned (d, f64));
- else
- ASSERT (0);
- break;
-
- default:
- ASSERT (0);
- break;
- }
-
- p += 1 + n_digits;
- d += n_bytes;
- }
-}
-
-static void
-unserialize_elog_event (serialize_main_t * m, va_list * va)
-{
- elog_main_t *em = va_arg (*va, elog_main_t *);
- elog_event_t *e = va_arg (*va, elog_event_t *);
- elog_event_type_t *t;
- u8 *p, *d;
-
- {
- u16 tmp[2];
-
- unserialize_integer (m, &tmp[0], sizeof (e->type));
- unserialize_integer (m, &tmp[1], sizeof (e->track));
-
- e->type = tmp[0];
- e->track = tmp[1];
-
- /* Make sure it fits. */
- ASSERT (e->type == tmp[0]);
- ASSERT (e->track == tmp[1]);
- }
-
- t = vec_elt_at_index (em->event_types, e->type);
-
- unserialize (m, unserialize_f64, &e->time);
-
- d = e->data;
- p = (u8 *) t->format_args;
-
- while (p && *p)
- {
- uword n_digits, n_bytes = 0;
- u32 tmp;
-
- n_digits = parse_2digit_decimal ((char *) p + 1, &n_bytes);
-
- switch (p[0])
- {
- case 'i':
- case 't':
- case 'T':
- if (n_bytes == 1)
- {
- unserialize_integer (m, &tmp, sizeof (u8));
- d[0] = tmp;
- }
- else if (n_bytes == 2)
- {
- unserialize_integer (m, &tmp, sizeof (u16));
- clib_mem_unaligned (d, u16) = tmp;
- }
- else if (n_bytes == 4)
- {
- unserialize_integer (m, &tmp, sizeof (u32));
- clib_mem_unaligned (d, u32) = tmp;
- }
- else if (n_bytes == 8)
- {
- u64 x;
- unserialize (m, unserialize_64, &x);
- clib_mem_unaligned (d, u64) = x;
- }
- else
- ASSERT (0);
- break;
-
- case 's':
- {
- char *t;
- unserialize_cstring (m, &t);
- if (n_bytes == 0)
- n_bytes = strlen (t) + 1;
- clib_memcpy (d, t, clib_min (n_bytes, vec_len (t)));
- vec_free (t);
- break;
- }
-
- case 'f':
- if (n_bytes == 4)
- {
- f32 x;
- unserialize (m, unserialize_f32, &x);
- clib_mem_unaligned (d, f32) = x;
- }
- else if (n_bytes == 8)
- {
- f64 x;
- unserialize (m, unserialize_f64, &x);
- clib_mem_unaligned (d, f64) = x;
- }
- else
- ASSERT (0);
- break;
-
- default:
- ASSERT (0);
- break;
- }
-
- p += 1 + n_digits;
- d += n_bytes;
- }
-}
-
-static void
-serialize_elog_event_type (serialize_main_t * m, va_list * va)
-{
- elog_event_type_t *t = va_arg (*va, elog_event_type_t *);
- int n = va_arg (*va, int);
- int i, j;
- for (i = 0; i < n; i++)
- {
- serialize_cstring (m, t[i].format);
- serialize_cstring (m, t[i].format_args);
- serialize_integer (m, t[i].type_index_plus_one,
- sizeof (t->type_index_plus_one));
- serialize_integer (m, t[i].n_enum_strings,
- sizeof (t[i].n_enum_strings));
- for (j = 0; j < t[i].n_enum_strings; j++)
- serialize_cstring (m, t[i].enum_strings_vector[j]);
- }
-}
-
-static void
-unserialize_elog_event_type (serialize_main_t * m, va_list * va)
-{
- elog_event_type_t *t = va_arg (*va, elog_event_type_t *);
- int n = va_arg (*va, int);
- int i, j;
- for (i = 0; i < n; i++)
- {
- unserialize_cstring (m, &t[i].format);
- unserialize_cstring (m, &t[i].format_args);
- unserialize_integer (m, &t[i].type_index_plus_one,
- sizeof (t->type_index_plus_one));
- unserialize_integer (m, &t[i].n_enum_strings,
- sizeof (t[i].n_enum_strings));
- vec_resize (t[i].enum_strings_vector, t[i].n_enum_strings);
- for (j = 0; j < t[i].n_enum_strings; j++)
- unserialize_cstring (m, &t[i].enum_strings_vector[j]);
- }
-}
-
-static void
-serialize_elog_track (serialize_main_t * m, va_list * va)
-{
- elog_track_t *t = va_arg (*va, elog_track_t *);
- int n = va_arg (*va, int);
- int i;
- for (i = 0; i < n; i++)
- {
- serialize_cstring (m, t[i].name);
- }
-}
-
-static void
-unserialize_elog_track (serialize_main_t * m, va_list * va)
-{
- elog_track_t *t = va_arg (*va, elog_track_t *);
- int n = va_arg (*va, int);
- int i;
- for (i = 0; i < n; i++)
- {
- unserialize_cstring (m, &t[i].name);
- }
-}
-
-static void
-serialize_elog_time_stamp (serialize_main_t * m, va_list * va)
-{
- elog_time_stamp_t *st = va_arg (*va, elog_time_stamp_t *);
- serialize (m, serialize_64, st->os_nsec);
- serialize (m, serialize_64, st->cpu);
-}
-
-static void
-unserialize_elog_time_stamp (serialize_main_t * m, va_list * va)
-{
- elog_time_stamp_t *st = va_arg (*va, elog_time_stamp_t *);
- unserialize (m, unserialize_64, &st->os_nsec);
- unserialize (m, unserialize_64, &st->cpu);
-}
-
-static char *elog_serialize_magic = "elog v0";
-
-void
-serialize_elog_main (serialize_main_t * m, va_list * va)
-{
- elog_main_t *em = va_arg (*va, elog_main_t *);
- elog_event_t *e;
-
- serialize_magic (m, elog_serialize_magic, strlen (elog_serialize_magic));
-
- serialize_integer (m, em->event_ring_size, sizeof (u32));
-
- elog_time_now (&em->serialize_time);
- serialize (m, serialize_elog_time_stamp, &em->serialize_time);
- serialize (m, serialize_elog_time_stamp, &em->init_time);
-
- vec_serialize (m, em->event_types, serialize_elog_event_type);
- vec_serialize (m, em->tracks, serialize_elog_track);
- vec_serialize (m, em->string_table, serialize_vec_8);
-
- /* Free old events (cached) in case they have changed. */
- vec_free (em->events);
- elog_get_events (em);
-
- serialize_integer (m, vec_len (em->events), sizeof (u32));
-
- /* SMP logs can easily have local time paradoxes... */
- vec_sort_with_function (em->events, elog_cmp);
-
- vec_foreach (e, em->events) serialize (m, serialize_elog_event, em, e);
-}
-
-void
-unserialize_elog_main (serialize_main_t * m, va_list * va)
-{
- elog_main_t *em = va_arg (*va, elog_main_t *);
- uword i;
- u32 rs;
-
- unserialize_check_magic (m, elog_serialize_magic,
- strlen (elog_serialize_magic));
-
- unserialize_integer (m, &rs, sizeof (u32));
- em->event_ring_size = rs;
- elog_init (em, em->event_ring_size);
-
- unserialize (m, unserialize_elog_time_stamp, &em->serialize_time);
- unserialize (m, unserialize_elog_time_stamp, &em->init_time);
- em->nsec_per_cpu_clock = elog_nsec_per_clock (em);
-
- vec_unserialize (m, &em->event_types, unserialize_elog_event_type);
- for (i = 0; i < vec_len (em->event_types); i++)
- new_event_type (em, i);
-
- vec_unserialize (m, &em->tracks, unserialize_elog_track);
- vec_unserialize (m, &em->string_table, unserialize_vec_8);
-
- {
- u32 ne;
- elog_event_t *e;
-
- unserialize_integer (m, &ne, sizeof (u32));
- vec_resize (em->events, ne);
- vec_foreach (e, em->events)
- unserialize (m, unserialize_elog_event, em, e);
- }
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */