2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 Copyright (c) 2005,2009 Eliot Dresselhaus
18 Permission is hereby granted, free of charge, to any person obtaining
19 a copy of this software and associated documentation files (the
20 "Software"), to deal in the Software without restriction, including
21 without limitation the rights to use, copy, modify, merge, publish,
22 distribute, sublicense, and/or sell copies of the Software, and to
23 permit persons to whom the Software is furnished to do so, subject to
24 the following conditions:
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
29 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 #include <vppinfra/elog.h>
39 #include <vppinfra/cache.h>
40 #include <vppinfra/error.h>
41 #include <vppinfra/format.h>
42 #include <vppinfra/hash.h>
43 #include <vppinfra/math.h>
46 elog_lock (elog_main_t * em)
48 if (PREDICT_FALSE (em->lock != 0))
49 while (clib_atomic_test_and_set (em->lock))
54 elog_unlock (elog_main_t * em)
56 if (PREDICT_FALSE (em->lock != 0))
58 CLIB_MEMORY_BARRIER ();
63 /* Non-inline version. */
65 elog_event_data (elog_main_t * em,
66 elog_event_type_t * type, elog_track_t * track, u64 cpu_time)
68 return elog_event_data_inline (em, type, track, cpu_time);
72 new_event_type (elog_main_t * em, uword i)
74 elog_event_type_t *t = vec_elt_at_index (em->event_types, i);
76 if (!em->event_type_by_format)
77 em->event_type_by_format =
78 hash_create_vec ( /* size */ 0, sizeof (u8), sizeof (uword));
80 t->type_index_plus_one = i + 1;
81 hash_set_mem (em->event_type_by_format, t->format, i);
85 find_or_create_type (elog_main_t * em, elog_event_type_t * t)
87 uword *p = hash_get_mem (em->event_type_by_format, t->format);
94 i = vec_len (em->event_types);
95 vec_add1 (em->event_types, t[0]);
96 new_event_type (em, i);
102 /* External function to register types. */
104 elog_event_type_register (elog_main_t * em, elog_event_type_t * t)
106 elog_event_type_t *static_type = t;
111 /* Multiple simultaneous registration attempts, */
112 if (t->type_index_plus_one > 0)
115 return t->type_index_plus_one - 1;
118 l = vec_len (em->event_types);
120 t->type_index_plus_one = 1 + l;
124 /* If format args are not specified try to be smart about providing defaults
125 so most of the time user does not have to specify them. */
131 l = strlen (t->format);
132 for (i = 0; i < l; i++)
134 if (t->format[i] != '%')
138 if (t->format[i + 1] == '%') /* %% */
141 switch (t->format[i + 1])
147 this_arg = "i4"; /* size of u32 */
150 this_arg = "f8"; /* defaults to f64 */
153 this_arg = "s0"; /* defaults to null terminated string. */
158 (char *) format ((u8 *) t->format_args, "%s", this_arg);
161 /* Null terminate. */
162 vec_add1 (t->format_args, 0);
165 vec_add1 (em->event_types, t[0]);
167 t = em->event_types + l;
169 /* Make copies of strings for hashing etc. */
171 t->format = (char *) format (0, "%s %s%c", t->function, t->format, 0);
173 t->format = (char *) format (0, "%s%c", t->format, 0);
175 t->format_args = (char *) format (0, "%s%c", t->format_args, 0);
177 /* Construct string table. */
180 t->n_enum_strings = static_type->n_enum_strings;
181 for (i = 0; i < t->n_enum_strings; i++)
183 if (!static_type->enum_strings[i])
184 static_type->enum_strings[i] = "MISSING";
185 vec_add1 (t->enum_strings_vector,
186 (char *) format (0, "%s%c", static_type->enum_strings[i],
191 new_event_type (em, l);
198 elog_track_register (elog_main_t * em, elog_track_t * t)
204 l = vec_len (em->tracks);
206 t->track_index_plus_one = 1 + l;
210 vec_add1 (em->tracks, t[0]);
214 t->name = (char *) format (0, "%s%c", t->name, 0);
222 parse_2digit_decimal (char *p, uword * number)
227 digits[0] = digits[1] = 0;
228 while (p[i] >= '0' && p[i] <= '9')
232 digits[i] = p[i] - '0';
236 if (i >= 1 && i <= 2)
241 *number = 10 * digits[0] + digits[1];
249 fixed_format (u8 * s, char *fmt, char *result, uword * result_len)
259 if (f[0] == '%' && f[1] != '%')
264 vec_add (s, fmt, f - fmt);
272 /* Skip possible +-= justification. */
273 f += f[0] == '+' || f[0] == '-' || f[0] == '=';
275 /* Skip possible X.Y width. */
276 while ((f[0] >= '0' && f[0] <= '9') || f[0] == '.')
279 /* Skip wlL as in e.g. %Ld. */
280 f += f[0] == 'w' || f[0] == 'l' || f[0] == 'L';
282 /* Finally skip format letter. */
285 ASSERT (*result_len > f - percent);
286 l = clib_min (f - percent, *result_len - 1);
287 clib_memcpy (result, percent, l);
291 *result_len = f - fmt;
296 format_elog_event (u8 * s, va_list * va)
298 elog_main_t *em = va_arg (*va, elog_main_t *);
299 elog_event_t *e = va_arg (*va, elog_event_t *);
300 elog_event_type_t *t;
302 void *d = (u8 *) e->data;
305 t = vec_elt_at_index (em->event_types, e->type);
311 uword n_bytes = 0, n_digits, f_bytes = 0;
313 f_bytes = sizeof (arg_format);
314 s = fixed_format (s, f, arg_format, &f_bytes);
317 if (a == 0 || a[0] == 0)
319 /* Format must also be at end. */
324 /* Don't go past end of event data. */
325 ASSERT (d < (void *) (e->data + sizeof (e->data)));
327 n_digits = parse_2digit_decimal (a + 1, &n_bytes);
339 else if (n_bytes == 2)
340 i = clib_mem_unaligned (d, u16);
341 else if (n_bytes == 4)
342 i = clib_mem_unaligned (d, u32);
343 else if (n_bytes == 8)
344 l = clib_mem_unaligned (d, u64);
350 vec_elt (t->enum_strings_vector, n_bytes == 8 ? l : i);
351 s = format (s, arg_format, e);
353 else if (a[0] == 'T')
356 vec_elt_at_index (em->string_table, n_bytes == 8 ? l : i);
357 s = format (s, arg_format, e);
359 else if (n_bytes == 8)
360 s = format (s, arg_format, l);
362 s = format (s, arg_format, i);
370 x = clib_mem_unaligned (d, f32);
371 else if (n_bytes == 8)
372 x = clib_mem_unaligned (d, f64);
375 s = format (s, arg_format, x);
380 s = format (s, arg_format, d);
382 n_bytes = strlen (d) + 1;
390 ASSERT (n_digits > 0 && n_digits <= 2);
399 format_elog_track_name (u8 * s, va_list * va)
401 elog_main_t *em = va_arg (*va, elog_main_t *);
402 elog_event_t *e = va_arg (*va, elog_event_t *);
403 elog_track_t *t = vec_elt_at_index (em->tracks, e->track);
404 return format (s, "%s", t->name);
408 format_elog_track (u8 * s, va_list * args)
410 elog_main_t *em = va_arg (*args, elog_main_t *);
411 f64 dt = va_arg (*args, f64);
412 int track_index = va_arg (*args, int);
413 elog_event_t *e, *es;
416 indent = format_get_indent (s) + 1;
418 es = elog_peek_events (em);
421 if (e->track != track_index)
423 s = format (s, "%U%18.9f: %U\n", format_white_space, indent, e->time + dt,
424 format_elog_event, em, e);
431 elog_time_now (elog_time_stamp_t * et)
433 u64 cpu_time_now, os_time_now_nsec;
438 #include <sys/syscall.h>
440 clock_gettime (CLOCK_REALTIME, &ts);
442 syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
444 cpu_time_now = clib_cpu_time_now ();
445 /* Subtract 3/30/2017's worth of seconds to retain precision */
446 os_time_now_nsec = 1e9 * (ts.tv_sec - 1490885108) + ts.tv_nsec;
449 cpu_time_now = clib_cpu_time_now ();
450 os_time_now_nsec = 0;
453 et->cpu = cpu_time_now;
454 et->os_nsec = os_time_now_nsec;
458 elog_time_stamp_diff_os_nsec (elog_time_stamp_t * t1, elog_time_stamp_t * t2)
460 return (i64) t1->os_nsec - (i64) t2->os_nsec;
464 elog_time_stamp_diff_cpu (elog_time_stamp_t * t1, elog_time_stamp_t * t2)
466 return (i64) t1->cpu - (i64) t2->cpu;
470 elog_nsec_per_clock (elog_main_t * em)
472 return ((f64) elog_time_stamp_diff_os_nsec (&em->serialize_time,
474 / (f64) elog_time_stamp_diff_cpu (&em->serialize_time,
479 elog_alloc (elog_main_t * em, u32 n_events)
482 vec_free (em->event_ring);
484 /* Ring size must be a power of 2. */
485 em->event_ring_size = n_events = max_pow2 (n_events);
487 /* Leave an empty ievent at end so we can always speculatively write
488 and event there (possibly a long form event). */
489 vec_resize_aligned (em->event_ring, n_events, CLIB_CACHE_LINE_BYTES);
493 elog_init (elog_main_t * em, u32 n_events)
495 clib_memset (em, 0, sizeof (em[0]));
500 elog_alloc (em, n_events);
502 clib_time_init (&em->cpu_timer);
504 em->n_total_events_disable_limit = ~0;
507 em->default_track.name = "default";
508 elog_track_register (em, &em->default_track);
510 elog_time_now (&em->init_time);
513 /* Returns number of events in ring and start index. */
515 elog_event_range (elog_main_t * em, uword * lo)
517 uword l = em->event_ring_size;
518 u64 i = em->n_total_events;
520 /* Ring never wrapped? */
536 elog_peek_events (elog_main_t * em)
538 elog_event_t *e, *f, *es = 0;
541 n = elog_event_range (em, &j);
542 for (i = 0; i < n; i++)
545 f = vec_elt_at_index (em->event_ring, j);
548 /* Convert absolute time from cycles to seconds from start. */
551 em->init_time.cpu) * em->cpu_timer.seconds_per_clock;
553 j = (j + 1) & (em->event_ring_size - 1);
559 /* Add a formatted string to the string table. */
561 elog_string (elog_main_t * em, char *fmt, ...)
567 offset = vec_len (em->string_table);
568 em->string_table = (char *) va_format ((u8 *) em->string_table, fmt, &va);
571 /* Null terminate string if it is not already. */
572 if (vec_end (em->string_table)[-1] != 0)
573 vec_add1 (em->string_table, 0);
579 elog_get_events (elog_main_t * em)
582 em->events = elog_peek_events (em);
587 maybe_fix_string_table_offset (elog_event_t * e,
588 elog_event_type_t * t, u32 offset)
590 void *d = (u8 *) e->data;
600 uword n_bytes = 0, n_digits;
605 /* Don't go past end of event data. */
606 ASSERT (d < (void *) (e->data + sizeof (e->data)));
608 n_digits = parse_2digit_decimal (a + 1, &n_bytes);
612 ASSERT (n_bytes == 4);
613 clib_mem_unaligned (d, u32) += offset;
627 ASSERT (n_digits > 0 && n_digits <= 2);
634 elog_cmp (void *a1, void *a2)
636 elog_event_t *e1 = a1;
637 elog_event_t *e2 = a2;
639 if (e1->time < e2->time)
642 if (e1->time > e2->time)
649 * merge two event logs. Complicated and cranky.
652 elog_merge (elog_main_t * dst, u8 * dst_tag, elog_main_t * src, u8 * src_tag,
657 u32 string_table_offset_for_src_events;
658 u32 track_offset_for_src_tracks;
662 clib_memset (&newt, 0, sizeof (newt));
664 /* Acquire src and dst events */
665 elog_get_events (src);
666 elog_get_events (dst);
668 string_table_offset_for_src_events = vec_len (dst->string_table);
669 vec_append (dst->string_table, src->string_table);
671 l = vec_len (dst->events);
672 vec_append (dst->events, src->events);
674 /* Prepend the supplied tag (if any) to all dst track names */
677 for (i = 0; i < vec_len (dst->tracks); i++)
679 elog_track_t *t = vec_elt_at_index (dst->tracks, i);
682 new_name = (char *) format (0, "%s:%s%c", dst_tag, t->name, 0);
689 * Remember where we started allocating new tracks while merging
691 track_offset_for_src_tracks = vec_len (dst->tracks);
693 /* Copy / tag source tracks */
694 for (i = 0; i < vec_len (src->tracks); i++)
696 elog_track_t *t = vec_elt_at_index (src->tracks, i);
698 newt.name = (char *) format (0, "%s:%s%c", src_tag, t->name, 0);
700 newt.name = (char *) format (0, "%s%c", t->name, 0);
701 (void) elog_track_register (dst, &newt);
702 vec_free (newt.name);
705 /* Across all (copied) src events... */
706 for (e = dst->events + l; e < vec_end (dst->events); e++)
708 elog_event_type_t *t = vec_elt_at_index (src->event_types, e->type);
710 /* Remap type from src -> dst. */
711 e->type = find_or_create_type (dst, t);
713 /* Remap string table offsets for 'T' format args */
714 maybe_fix_string_table_offset (e, t,
715 string_table_offset_for_src_events);
718 e->track += track_offset_for_src_tracks;
721 /* Adjust event times for relative starting times of event streams. */
723 f64 dt_event, dt_os_nsec, dt_clock_nsec;
725 /* Set clock parameters if dst was not generated by unserialize. */
726 if (dst->serialize_time.cpu == 0)
728 dst->init_time = src->init_time;
729 dst->serialize_time = src->serialize_time;
730 dst->nsec_per_cpu_clock = src->nsec_per_cpu_clock;
734 elog_time_stamp_diff_os_nsec (&src->init_time, &dst->init_time);
736 dt_event = dt_os_nsec;
738 (elog_time_stamp_diff_cpu (&src->init_time, &dst->init_time) * .5 *
739 (dst->nsec_per_cpu_clock + src->nsec_per_cpu_clock));
742 * Heuristic to see if src/dst came from same time source.
743 * If frequencies are "the same" and os clock and cpu clock agree
744 * to within 100e-9 secs about time difference between src/dst
745 * init_time, then we use cpu clock. Otherwise we use OS clock.
747 * When merging event logs from different systems, time paradoxes
748 * at the O(1ms) level are to be expected. Hence, the "align_tweak"
749 * parameter. If two events logged on different processors are known
750 * to occur in a specific order - and with a reasonably-estimated
751 * interval - supply a non-zero "align_tweak" parameter
753 if (fabs (src->nsec_per_cpu_clock - dst->nsec_per_cpu_clock) < 1e-2
754 && fabs (dt_os_nsec - dt_clock_nsec) < 100)
755 dt_event = dt_clock_nsec;
757 /* Convert to seconds. */
761 * Move the earlier set of events later, to avoid creating
762 * events which precede the Big Bang (aka have negative timestamps).
764 * Not to any scale, we have something like the following picture:
766 * DST capture start point
770 * SRC capture start point
772 * In this case dt_event is positive, src started after dst,
773 * to put src events onto a common timebase we have to move them
774 * forward in time. Naturally, the opposite case is
775 * possible, too: dt_event will be negative, and so we have to
776 * move dst events forward in time by the |dt_event|.
777 * In both cases, we add align_tweak.
781 /* Src started after dst. */
782 for (e = dst->events + l; e < vec_end (dst->events); e++)
783 e->time += dt_event + align_tweak;
787 /* Dst started after src. */
788 dt_event = -dt_event;
789 for (e = dst->events + 0; e < dst->events + l; e++)
790 e->time += dt_event + align_tweak;
794 /* Sort events by increasing time. */
795 vec_sort_with_function (dst->events, elog_cmp);
797 dst->n_total_events = vec_len (dst->events);
799 /* Recreate the event ring or the results won't serialize */
803 ASSERT (dst->cpu_timer.seconds_per_clock);
805 elog_alloc (dst, vec_len (dst->events));
806 for (i = 0; i < vec_len (dst->events); i++)
808 elog_event_t *es, *ed;
810 es = dst->events + i;
811 ed = dst->event_ring + i;
819 serialize_elog_event (serialize_main_t * m, va_list * va)
821 elog_main_t *em = va_arg (*va, elog_main_t *);
822 elog_event_t *e = va_arg (*va, elog_event_t *);
823 elog_event_type_t *t = vec_elt_at_index (em->event_types, e->type);
825 u8 *p = (u8 *) t->format_args;
827 serialize_integer (m, e->type, sizeof (e->type));
828 serialize_integer (m, e->track, sizeof (e->track));
829 serialize (m, serialize_f64, e->time);
833 uword n_digits, n_bytes = 0;
835 n_digits = parse_2digit_decimal ((char *) p + 1, &n_bytes);
843 serialize_integer (m, d[0], sizeof (u8));
844 else if (n_bytes == 2)
845 serialize_integer (m, clib_mem_unaligned (d, u16), sizeof (u16));
846 else if (n_bytes == 4)
847 serialize_integer (m, clib_mem_unaligned (d, u32), sizeof (u32));
848 else if (n_bytes == 8)
849 serialize (m, serialize_64, clib_mem_unaligned (d, u64));
855 serialize_cstring (m, (char *) d);
857 n_bytes = strlen ((char *) d) + 1;
862 serialize (m, serialize_f32, clib_mem_unaligned (d, f32));
863 else if (n_bytes == 8)
864 serialize (m, serialize_f64, clib_mem_unaligned (d, f64));
880 unserialize_elog_event (serialize_main_t * m, va_list * va)
882 elog_main_t *em = va_arg (*va, elog_main_t *);
883 elog_event_t *e = va_arg (*va, elog_event_t *);
884 elog_event_type_t *t;
890 unserialize_integer (m, &tmp[0], sizeof (e->type));
891 unserialize_integer (m, &tmp[1], sizeof (e->track));
896 /* Make sure it fits. */
897 ASSERT (e->type == tmp[0]);
898 ASSERT (e->track == tmp[1]);
901 t = vec_elt_at_index (em->event_types, e->type);
903 unserialize (m, unserialize_f64, &e->time);
906 p = (u8 *) t->format_args;
910 uword n_digits, n_bytes = 0;
913 n_digits = parse_2digit_decimal ((char *) p + 1, &n_bytes);
922 unserialize_integer (m, &tmp, sizeof (u8));
925 else if (n_bytes == 2)
927 unserialize_integer (m, &tmp, sizeof (u16));
928 clib_mem_unaligned (d, u16) = tmp;
930 else if (n_bytes == 4)
932 unserialize_integer (m, &tmp, sizeof (u32));
933 clib_mem_unaligned (d, u32) = tmp;
935 else if (n_bytes == 8)
938 unserialize (m, unserialize_64, &x);
939 clib_mem_unaligned (d, u64) = x;
948 unserialize_cstring (m, &t);
950 n_bytes = strlen (t) + 1;
951 clib_memcpy (d, t, clib_min (n_bytes, vec_len (t)));
960 unserialize (m, unserialize_f32, &x);
961 clib_mem_unaligned (d, f32) = x;
963 else if (n_bytes == 8)
966 unserialize (m, unserialize_f64, &x);
967 clib_mem_unaligned (d, f64) = x;
984 serialize_elog_event_type (serialize_main_t * m, va_list * va)
986 elog_event_type_t *t = va_arg (*va, elog_event_type_t *);
987 int n = va_arg (*va, int);
989 for (i = 0; i < n; i++)
991 serialize_cstring (m, t[i].format);
992 serialize_cstring (m, t[i].format_args);
993 serialize_integer (m, t[i].type_index_plus_one,
994 sizeof (t->type_index_plus_one));
995 serialize_integer (m, t[i].n_enum_strings,
996 sizeof (t[i].n_enum_strings));
997 for (j = 0; j < t[i].n_enum_strings; j++)
998 serialize_cstring (m, t[i].enum_strings_vector[j]);
1003 unserialize_elog_event_type (serialize_main_t * m, va_list * va)
1005 elog_event_type_t *t = va_arg (*va, elog_event_type_t *);
1006 int n = va_arg (*va, int);
1008 for (i = 0; i < n; i++)
1010 unserialize_cstring (m, &t[i].format);
1011 unserialize_cstring (m, &t[i].format_args);
1012 unserialize_integer (m, &t[i].type_index_plus_one,
1013 sizeof (t->type_index_plus_one));
1014 unserialize_integer (m, &t[i].n_enum_strings,
1015 sizeof (t[i].n_enum_strings));
1016 vec_resize (t[i].enum_strings_vector, t[i].n_enum_strings);
1017 for (j = 0; j < t[i].n_enum_strings; j++)
1018 unserialize_cstring (m, &t[i].enum_strings_vector[j]);
1023 serialize_elog_track (serialize_main_t * m, va_list * va)
1025 elog_track_t *t = va_arg (*va, elog_track_t *);
1026 int n = va_arg (*va, int);
1028 for (i = 0; i < n; i++)
1030 serialize_cstring (m, t[i].name);
1035 unserialize_elog_track (serialize_main_t * m, va_list * va)
1037 elog_track_t *t = va_arg (*va, elog_track_t *);
1038 int n = va_arg (*va, int);
1040 for (i = 0; i < n; i++)
1042 unserialize_cstring (m, &t[i].name);
1047 serialize_elog_time_stamp (serialize_main_t * m, va_list * va)
1049 elog_time_stamp_t *st = va_arg (*va, elog_time_stamp_t *);
1050 serialize (m, serialize_64, st->os_nsec);
1051 serialize (m, serialize_64, st->cpu);
1055 unserialize_elog_time_stamp (serialize_main_t * m, va_list * va)
1057 elog_time_stamp_t *st = va_arg (*va, elog_time_stamp_t *);
1058 unserialize (m, unserialize_64, &st->os_nsec);
1059 unserialize (m, unserialize_64, &st->cpu);
1062 static char *elog_serialize_magic = "elog v0";
1065 serialize_elog_main (serialize_main_t * m, va_list * va)
1067 elog_main_t *em = va_arg (*va, elog_main_t *);
1068 int flush_ring = va_arg (*va, int);
1071 serialize_magic (m, elog_serialize_magic, strlen (elog_serialize_magic));
1073 serialize_integer (m, em->event_ring_size, sizeof (u32));
1075 elog_time_now (&em->serialize_time);
1076 serialize (m, serialize_elog_time_stamp, &em->serialize_time);
1077 serialize (m, serialize_elog_time_stamp, &em->init_time);
1079 vec_serialize (m, em->event_types, serialize_elog_event_type);
1080 vec_serialize (m, em->tracks, serialize_elog_track);
1081 vec_serialize (m, em->string_table, serialize_vec_8);
1083 /* Free old events (cached) in case they have changed. */
1086 vec_free (em->events);
1087 elog_get_events (em);
1090 serialize_integer (m, vec_len (em->events), sizeof (u32));
1092 /* SMP logs can easily have local time paradoxes... */
1093 vec_sort_with_function (em->events, elog_cmp);
1095 vec_foreach (e, em->events) serialize (m, serialize_elog_event, em, e);
1099 unserialize_elog_main (serialize_main_t * m, va_list * va)
1101 elog_main_t *em = va_arg (*va, elog_main_t *);
1105 unserialize_check_magic (m, elog_serialize_magic,
1106 strlen (elog_serialize_magic));
1108 unserialize_integer (m, &rs, sizeof (u32));
1109 em->event_ring_size = rs;
1110 elog_init (em, em->event_ring_size);
1112 unserialize (m, unserialize_elog_time_stamp, &em->serialize_time);
1113 unserialize (m, unserialize_elog_time_stamp, &em->init_time);
1114 em->nsec_per_cpu_clock = elog_nsec_per_clock (em);
1116 vec_unserialize (m, &em->event_types, unserialize_elog_event_type);
1117 for (i = 0; i < vec_len (em->event_types); i++)
1118 new_event_type (em, i);
1120 vec_unserialize (m, &em->tracks, unserialize_elog_track);
1121 vec_unserialize (m, &em->string_table, unserialize_vec_8);
1127 unserialize_integer (m, &ne, sizeof (u32));
1128 vec_resize (em->events, ne);
1129 vec_foreach (e, em->events)
1130 unserialize (m, unserialize_elog_event, em, e);
1135 * fd.io coding-style-patch-verification: ON
1138 * eval: (c-set-style "gnu")