diff options
Diffstat (limited to 'vppinfra/vppinfra/elog.c')
-rw-r--r-- | vppinfra/vppinfra/elog.c | 1061 |
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: - */ |