1*6b2ce080Schristos /* $NetBSD: syscall.c,v 1.10 2019/01/25 15:31:11 christos Exp $ */
21655d9a8Sdsl
31655d9a8Sdsl /*-
41655d9a8Sdsl * Copyright (c) 2006 The NetBSD Foundation, Inc.
51655d9a8Sdsl * All rights reserved.
61655d9a8Sdsl *
71655d9a8Sdsl * This code is derived from software contributed to The NetBSD Foundation
81655d9a8Sdsl * by David Laight.
91655d9a8Sdsl *
101655d9a8Sdsl * Redistribution and use in source and binary forms, with or without
111655d9a8Sdsl * modification, are permitted provided that the following conditions
121655d9a8Sdsl * are met:
131655d9a8Sdsl * 1. Redistributions of source code must retain the above copyright
141655d9a8Sdsl * notice, this list of conditions and the following disclaimer.
151655d9a8Sdsl * 2. Redistributions in binary form must reproduce the above copyright
161655d9a8Sdsl * notice, this list of conditions and the following disclaimer in the
171655d9a8Sdsl * documentation and/or other materials provided with the distribution.
181655d9a8Sdsl *
191655d9a8Sdsl * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
201655d9a8Sdsl * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
211655d9a8Sdsl * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
221655d9a8Sdsl * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
231655d9a8Sdsl * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
241655d9a8Sdsl * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
251655d9a8Sdsl * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
261655d9a8Sdsl * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
271655d9a8Sdsl * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
281655d9a8Sdsl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
291655d9a8Sdsl * POSSIBILITY OF SUCH DAMAGE.
301655d9a8Sdsl */
311655d9a8Sdsl
321655d9a8Sdsl #include <sys/cdefs.h>
33*6b2ce080Schristos __RCSID("$NetBSD: syscall.c,v 1.10 2019/01/25 15:31:11 christos Exp $");
341655d9a8Sdsl
351655d9a8Sdsl /* System call stats */
361655d9a8Sdsl
371655d9a8Sdsl #include <sys/param.h>
381655d9a8Sdsl #include <sys/namei.h>
391655d9a8Sdsl #include <sys/sysctl.h>
401655d9a8Sdsl
411655d9a8Sdsl #include <uvm/uvm_extern.h>
421655d9a8Sdsl
43ded5cac5Sdsl #include <errno.h>
441655d9a8Sdsl #include <stdlib.h>
451655d9a8Sdsl #include <string.h>
461655d9a8Sdsl #include <util.h>
471655d9a8Sdsl
481655d9a8Sdsl #include "systat.h"
491655d9a8Sdsl #include "extern.h"
50ded5cac5Sdsl #include "drvstats.h"
511655d9a8Sdsl #include "utmpentry.h"
521655d9a8Sdsl #include "vmstat.h"
531655d9a8Sdsl
541655d9a8Sdsl #include <sys/syscall.h>
551655d9a8Sdsl #include <../../sys/kern/syscalls.c>
561655d9a8Sdsl
571655d9a8Sdsl static struct Info {
581655d9a8Sdsl struct uvmexp_sysctl uvmexp;
591655d9a8Sdsl struct vmtotal Total;
60ded5cac5Sdsl uint64_t counts[SYS_NSYSENT];
61ded5cac5Sdsl uint64_t times[SYS_NSYSENT];
6249c5f0e9Sdsl } s, s1, s2;
6349c5f0e9Sdsl
6449c5f0e9Sdsl static uint64_t irf[SYS_NSYSENT], val[SYS_NSYSENT];
6549c5f0e9Sdsl static int irf_first = 1;
661655d9a8Sdsl
671655d9a8Sdsl int syscall_sort[SYS_NSYSENT];
681655d9a8Sdsl
691655d9a8Sdsl static enum sort_order { UNSORTED, NAMES, COUNTS } sort_order = NAMES;
701655d9a8Sdsl
71ded5cac5Sdsl #define SHOW_COUNTS 1
72ded5cac5Sdsl #define SHOW_TIMES 2
73ded5cac5Sdsl static int show = SHOW_COUNTS;
74ded5cac5Sdsl
75ded5cac5Sdsl static void getinfo(struct Info *, int);
761655d9a8Sdsl
7749c5f0e9Sdsl static char buf[32];
781655d9a8Sdsl
79ded5cac5Sdsl static size_t counts_mib_len, times_mib_len;
80ded5cac5Sdsl static int counts_mib[4], times_mib[4];
811655d9a8Sdsl
821655d9a8Sdsl WINDOW *
opensyscall(void)831655d9a8Sdsl opensyscall(void)
841655d9a8Sdsl {
851655d9a8Sdsl return (stdscr);
861655d9a8Sdsl }
871655d9a8Sdsl
881655d9a8Sdsl void
closesyscall(WINDOW * w)891655d9a8Sdsl closesyscall(WINDOW *w)
901655d9a8Sdsl {
911655d9a8Sdsl
921655d9a8Sdsl if (w == NULL)
931655d9a8Sdsl return;
941655d9a8Sdsl wclear(w);
951655d9a8Sdsl wrefresh(w);
961655d9a8Sdsl }
971655d9a8Sdsl
981655d9a8Sdsl
991655d9a8Sdsl /*
1001655d9a8Sdsl * These constants define where the major pieces are laid out
1011655d9a8Sdsl */
1021655d9a8Sdsl #define SYSCALLROW 9 /* Below the vmstat header */
1031655d9a8Sdsl
1041655d9a8Sdsl int
initsyscall(void)1051655d9a8Sdsl initsyscall(void)
1061655d9a8Sdsl {
1071655d9a8Sdsl static char name[] = "name";
1081655d9a8Sdsl
1091655d9a8Sdsl hertz = stathz ? stathz : hz;
1101655d9a8Sdsl
1111655d9a8Sdsl syscall_order(name);
1121655d9a8Sdsl
113ded5cac5Sdsl /* drvinit gets number of cpus! */
114ded5cac5Sdsl drvinit(1);
1151655d9a8Sdsl
116f17f1ddfSchristos counts_mib_len = __arraycount(counts_mib);
117f17f1ddfSchristos if (sysctlnametomib("kern.syscalls.counts", counts_mib,
118f17f1ddfSchristos &counts_mib_len))
119ded5cac5Sdsl counts_mib_len = 0;
1201655d9a8Sdsl
121f17f1ddfSchristos times_mib_len = __arraycount(times_mib);
122ded5cac5Sdsl if (sysctlnametomib("kern.syscalls.times", times_mib, ×_mib_len))
123ded5cac5Sdsl times_mib_len = 0;
124ded5cac5Sdsl
125ded5cac5Sdsl getinfo(&s2, SHOW_COUNTS | SHOW_TIMES);
1261655d9a8Sdsl s1 = s2;
127ded5cac5Sdsl
1281655d9a8Sdsl return(1);
1291655d9a8Sdsl }
1301655d9a8Sdsl
1311655d9a8Sdsl void
fetchsyscall(void)1321655d9a8Sdsl fetchsyscall(void)
1331655d9a8Sdsl {
1341655d9a8Sdsl time_t now;
1351655d9a8Sdsl
1361655d9a8Sdsl time(&now);
1371655d9a8Sdsl strlcpy(buf, ctime(&now), sizeof(buf));
1381655d9a8Sdsl buf[19] = '\0';
139ded5cac5Sdsl getinfo(&s, show);
1401655d9a8Sdsl }
1411655d9a8Sdsl
1421655d9a8Sdsl void
labelsyscall(void)1431655d9a8Sdsl labelsyscall(void)
1441655d9a8Sdsl {
1451655d9a8Sdsl labelvmstat_top();
1461655d9a8Sdsl }
1471655d9a8Sdsl
14849c5f0e9Sdsl static void
putuint64(uint64_t v,int row,int col,int width)14949c5f0e9Sdsl putuint64(uint64_t v, int row, int col, int width)
1501655d9a8Sdsl {
15149c5f0e9Sdsl static const char suffix[] = "KMDT";
15249c5f0e9Sdsl int len, i;
1531655d9a8Sdsl
15449c5f0e9Sdsl len = snprintf(buf, sizeof buf, "%" PRIu64, v);
15549c5f0e9Sdsl if (len > width) {
15649c5f0e9Sdsl i = (len - width) / 3;
157e7a39c4fSlukem if (i >= (int)sizeof(suffix)) {
15849c5f0e9Sdsl memset(buf, '*', width);
15949c5f0e9Sdsl len = width;
16049c5f0e9Sdsl } else {
16149c5f0e9Sdsl len -= (i + 1) * 3;
16249c5f0e9Sdsl buf[len++] = suffix[i];
16349c5f0e9Sdsl }
16449c5f0e9Sdsl buf[len] = 0;
16549c5f0e9Sdsl }
16649c5f0e9Sdsl mvprintw(row, col, "%*s", width, buf);
167ded5cac5Sdsl }
1681655d9a8Sdsl
169ded5cac5Sdsl static int
compare_irf(const void * a,const void * b)17049c5f0e9Sdsl compare_irf(const void *a, const void *b)
171ded5cac5Sdsl {
172ded5cac5Sdsl int ia = *(const int *)a, ib = *(const int *)b;
173ded5cac5Sdsl int64_t delta;
174ded5cac5Sdsl
17549c5f0e9Sdsl delta = irf[ib] - irf[ia];
176ded5cac5Sdsl return delta ? delta < 0 ? -1 : 1 : 0;
1771655d9a8Sdsl }
1781655d9a8Sdsl
1791655d9a8Sdsl void
showsyscall(void)1801655d9a8Sdsl showsyscall(void)
1811655d9a8Sdsl {
1821655d9a8Sdsl int i, ii, l, c;
18349c5f0e9Sdsl uint64_t v;
1841655d9a8Sdsl static int failcnt = 0;
1851655d9a8Sdsl static int relabel = 0;
18649c5f0e9Sdsl uint64_t itime;
1871655d9a8Sdsl
1881655d9a8Sdsl if (relabel) {
1891655d9a8Sdsl labelsyscall();
1901655d9a8Sdsl relabel = 0;
1911655d9a8Sdsl }
1921655d9a8Sdsl
1931655d9a8Sdsl cpuswap();
1941655d9a8Sdsl if (display_mode == TIME) {
195*6b2ce080Schristos if (toofast(&failcnt))
1961655d9a8Sdsl return;
1971655d9a8Sdsl } else
1981655d9a8Sdsl etime = 1.0;
19949c5f0e9Sdsl itime = etime * 100;
2001655d9a8Sdsl
2011655d9a8Sdsl failcnt = 0;
2021655d9a8Sdsl
2031655d9a8Sdsl show_vmstat_top(&s.Total, &s.uvmexp, &s1.uvmexp);
2041655d9a8Sdsl
20549c5f0e9Sdsl /* Sort out the values we are going to display */
206f17f1ddfSchristos for (i = 0; i < (int)__arraycount(s.counts); i++) {
20749c5f0e9Sdsl switch (show) {
20849c5f0e9Sdsl default:
20949c5f0e9Sdsl case SHOW_COUNTS:
21049c5f0e9Sdsl v = s.counts[i] - s1.counts[i];
21149c5f0e9Sdsl break;
21249c5f0e9Sdsl case SHOW_TIMES:
21349c5f0e9Sdsl v = s.times[i] - s1.times[i];
21449c5f0e9Sdsl break;
21549c5f0e9Sdsl case SHOW_COUNTS | SHOW_TIMES: /* time/count */
21649c5f0e9Sdsl v = s.counts[i] - s1.counts[i];
21749c5f0e9Sdsl v = v ? (s.times[i] - s1.times[i]) / v : 0;
21849c5f0e9Sdsl }
21949c5f0e9Sdsl
22049c5f0e9Sdsl if (display_mode == TIME)
22149c5f0e9Sdsl v = (v * 100 + itime/2) / itime;
22249c5f0e9Sdsl
22349c5f0e9Sdsl val[i] = v;
22449c5f0e9Sdsl
2251655d9a8Sdsl /*
2261655d9a8Sdsl * We use an 'infinite response filter' in a vague
2271655d9a8Sdsl * attempt to stop the data leaping around too much.
2281655d9a8Sdsl * I suspect there are other/better methods in use.
2291655d9a8Sdsl */
23049c5f0e9Sdsl if (irf_first) {
23149c5f0e9Sdsl irf[i] = v;
23249c5f0e9Sdsl irf_first = 0;
23349c5f0e9Sdsl } else {
23449c5f0e9Sdsl irf[i] = irf[i] * 7 / 8 + v;
235ded5cac5Sdsl }
2361655d9a8Sdsl }
2371655d9a8Sdsl
23849c5f0e9Sdsl if (sort_order == COUNTS) {
2391655d9a8Sdsl /* mergesort() doesn't swap equal values about... */
240f17f1ddfSchristos mergesort(syscall_sort, __arraycount(syscall_sort),
24149c5f0e9Sdsl sizeof syscall_sort[0], compare_irf);
2421655d9a8Sdsl }
2431655d9a8Sdsl
2441655d9a8Sdsl l = SYSCALLROW;
2451655d9a8Sdsl c = 0;
2461655d9a8Sdsl move(l, c);
247f17f1ddfSchristos #define FMT "compile kernel with \"options SYSCALL_%s\" to get syscall %s"
248f17f1ddfSchristos if (counts_mib_len == 0) {
249f17f1ddfSchristos mvprintw(l, c, FMT, "STATS", "counts");
250f17f1ddfSchristos l++;
251f17f1ddfSchristos }
252f17f1ddfSchristos if (times_mib_len == 0) {
253f17f1ddfSchristos mvprintw(l, c, FMT, "TIMES", "times");
254f17f1ddfSchristos l++;
255f17f1ddfSchristos }
256f17f1ddfSchristos for (ii = 0; ii < (int)__arraycount(s.counts); ii++) {
2571655d9a8Sdsl i = syscall_sort[ii];
25849c5f0e9Sdsl if (val[i] == 0 && irf[i] == 0)
2591655d9a8Sdsl continue;
2601655d9a8Sdsl
261f17f1ddfSchristos if (i < (int)__arraycount(syscallnames)) {
2621655d9a8Sdsl const char *name = syscallnames[i];
2631655d9a8Sdsl while (name[0] == '_')
2641655d9a8Sdsl name++;
2651655d9a8Sdsl if (name[0] == 'c' && !strcmp(name + 1, "ompat_"))
2661655d9a8Sdsl name += 7;
2671655d9a8Sdsl mvprintw(l, c, "%17.17s", name);
2681655d9a8Sdsl } else
2691655d9a8Sdsl mvprintw(l, c, "syscall #%d ", i);
2701655d9a8Sdsl
27149c5f0e9Sdsl putuint64(val[i], l, c + 18, 8);
2721655d9a8Sdsl c += 27;
2731655d9a8Sdsl if (c + 26 > COLS) {
2741655d9a8Sdsl c = 0;
2751655d9a8Sdsl l++;
2761655d9a8Sdsl if (l >= LINES - 1)
2771655d9a8Sdsl break;
2781655d9a8Sdsl }
2791655d9a8Sdsl }
280ded5cac5Sdsl if (display_mode == TIME) {
281ded5cac5Sdsl memcpy(s1.counts, s.counts, sizeof s1.counts);
282ded5cac5Sdsl memcpy(s1.times, s.times, sizeof s1.times);
283ded5cac5Sdsl }
2841655d9a8Sdsl while (l < LINES - 1) {
2851655d9a8Sdsl clrtoeol();
2861655d9a8Sdsl move(++l, 0);
2871655d9a8Sdsl }
2881655d9a8Sdsl }
2891655d9a8Sdsl
2901655d9a8Sdsl void
syscall_boot(char * args)2911655d9a8Sdsl syscall_boot(char *args)
2921655d9a8Sdsl {
2931655d9a8Sdsl memset(&s1, 0, sizeof s1);
2941655d9a8Sdsl display_mode = BOOT;
2951655d9a8Sdsl }
2961655d9a8Sdsl
2971655d9a8Sdsl void
syscall_run(char * args)2981655d9a8Sdsl syscall_run(char *args)
2991655d9a8Sdsl {
3001655d9a8Sdsl s1 = s2;
3011655d9a8Sdsl display_mode = RUN;
3021655d9a8Sdsl }
3031655d9a8Sdsl
3041655d9a8Sdsl void
syscall_time(char * args)3051655d9a8Sdsl syscall_time(char *args)
3061655d9a8Sdsl {
3071655d9a8Sdsl display_mode = TIME;
3081655d9a8Sdsl }
3091655d9a8Sdsl
3101655d9a8Sdsl void
syscall_zero(char * args)3111655d9a8Sdsl syscall_zero(char *args)
3121655d9a8Sdsl {
3131655d9a8Sdsl s1 = s;
3141655d9a8Sdsl }
3151655d9a8Sdsl
3161655d9a8Sdsl static int
compare_names(const void * a,const void * b)3171655d9a8Sdsl compare_names(const void *a, const void *b)
3181655d9a8Sdsl {
3191655d9a8Sdsl const char *name_a = syscallnames[*(const int *)a];
3201655d9a8Sdsl const char *name_b = syscallnames[*(const int *)b];
3211655d9a8Sdsl
3221655d9a8Sdsl while (*name_a == '_')
3231655d9a8Sdsl name_a++;
3241655d9a8Sdsl while (*name_b == '_')
3251655d9a8Sdsl name_b++;
3261655d9a8Sdsl
3271655d9a8Sdsl return strcmp(name_a, name_b);
3281655d9a8Sdsl }
3291655d9a8Sdsl
3301655d9a8Sdsl void
syscall_order(char * args)3311655d9a8Sdsl syscall_order(char *args)
3321655d9a8Sdsl {
3331655d9a8Sdsl int i, len;
3341655d9a8Sdsl
3351655d9a8Sdsl if (args == NULL)
3361655d9a8Sdsl goto usage;
3371655d9a8Sdsl
3381655d9a8Sdsl len = strcspn(args, " \t\r\n");
3391655d9a8Sdsl
3401655d9a8Sdsl if (args[len + strspn(args + len, " \t\r\n")])
3411655d9a8Sdsl goto usage;
3421655d9a8Sdsl
34349c5f0e9Sdsl if (memcmp(args, "count", len) == 0)
3441655d9a8Sdsl sort_order = COUNTS;
34549c5f0e9Sdsl else if (memcmp(args, "name", len) == 0)
3461655d9a8Sdsl sort_order = NAMES;
3471655d9a8Sdsl else if (memcmp(args, "syscall", len) == 0)
3481655d9a8Sdsl sort_order = UNSORTED;
3491655d9a8Sdsl else
3501655d9a8Sdsl goto usage;
3511655d9a8Sdsl
3521655d9a8Sdsl /* Undo all the sorting */
353f17f1ddfSchristos for (i = 0; i < (int)__arraycount(syscall_sort); i++)
3541655d9a8Sdsl syscall_sort[i] = i;
3551655d9a8Sdsl
3561655d9a8Sdsl if (sort_order == NAMES) {
3571655d9a8Sdsl /* Only sort the entries we have names for */
358f17f1ddfSchristos qsort(syscall_sort, __arraycount(syscallnames), sizeof syscall_sort[0],
3591655d9a8Sdsl compare_names);
3601655d9a8Sdsl }
3611655d9a8Sdsl return;
3621655d9a8Sdsl
3631655d9a8Sdsl usage:
3641655d9a8Sdsl error("Usage: sort [count|name|syscall]");
3651655d9a8Sdsl }
3661655d9a8Sdsl
367ded5cac5Sdsl void
syscall_show(char * args)368ded5cac5Sdsl syscall_show(char *args)
369ded5cac5Sdsl {
370ded5cac5Sdsl int len;
371ded5cac5Sdsl
372ded5cac5Sdsl if (args == NULL)
373ded5cac5Sdsl goto usage;
374ded5cac5Sdsl
375ded5cac5Sdsl len = strcspn(args, " \t\r\n");
376ded5cac5Sdsl
377ded5cac5Sdsl if (args[len + strspn(args + len, " \t\r\n")])
378ded5cac5Sdsl goto usage;
379ded5cac5Sdsl
380ded5cac5Sdsl if (memcmp(args, "counts", len) == 0)
381ded5cac5Sdsl show = SHOW_COUNTS;
382ded5cac5Sdsl else if (memcmp(args, "times", len) == 0)
383ded5cac5Sdsl show = SHOW_TIMES;
384ded5cac5Sdsl else if (memcmp(args, "ratio", len) == 0)
385ded5cac5Sdsl show = SHOW_COUNTS | SHOW_TIMES;
386ded5cac5Sdsl else
387ded5cac5Sdsl goto usage;
388ded5cac5Sdsl
38949c5f0e9Sdsl memset(&irf, 0, sizeof irf);
39049c5f0e9Sdsl irf_first = 1;
39149c5f0e9Sdsl
392ded5cac5Sdsl return;
393ded5cac5Sdsl
394ded5cac5Sdsl usage:
395ded5cac5Sdsl error("Usage: show [counts|times|ratio]");
396ded5cac5Sdsl }
397ded5cac5Sdsl
3981655d9a8Sdsl static void
getinfo(struct Info * stats,int get_what)399ded5cac5Sdsl getinfo(struct Info *stats, int get_what)
4001655d9a8Sdsl {
4011655d9a8Sdsl int mib[2];
4021655d9a8Sdsl size_t size;
4031655d9a8Sdsl
4041655d9a8Sdsl cpureadstats();
4051655d9a8Sdsl
406ded5cac5Sdsl if (get_what & SHOW_COUNTS) {
407ded5cac5Sdsl size = sizeof stats->counts;
408f17f1ddfSchristos if (counts_mib_len != 0) {
409f17f1ddfSchristos if (sysctl(counts_mib, counts_mib_len, &stats->counts,
410f17f1ddfSchristos &size, NULL, 0)) {
411f17f1ddfSchristos error("can't get syscall counts: %s\n",
412f17f1ddfSchristos strerror(errno));
413ded5cac5Sdsl memset(&stats->counts, 0, sizeof stats->counts);
414ded5cac5Sdsl }
415ded5cac5Sdsl }
416f17f1ddfSchristos }
417ded5cac5Sdsl
418ded5cac5Sdsl if (get_what & SHOW_TIMES) {
419ded5cac5Sdsl size = sizeof stats->times;
420f17f1ddfSchristos if (times_mib_len != 0) {
421f17f1ddfSchristos if (sysctl(times_mib, times_mib_len, &stats->times,
422f17f1ddfSchristos &size, NULL, 0)) {
423f17f1ddfSchristos error("can't get syscall times: %s\n",
424f17f1ddfSchristos strerror(errno));
425ded5cac5Sdsl memset(&stats->times, 0, sizeof stats->times);
426ded5cac5Sdsl }
4271655d9a8Sdsl }
428f17f1ddfSchristos }
4291655d9a8Sdsl
4301655d9a8Sdsl size = sizeof(stats->uvmexp);
4311655d9a8Sdsl mib[0] = CTL_VM;
4321655d9a8Sdsl mib[1] = VM_UVMEXP2;
4331655d9a8Sdsl if (sysctl(mib, 2, &stats->uvmexp, &size, NULL, 0) < 0) {
4341655d9a8Sdsl error("can't get uvmexp: %s\n", strerror(errno));
4351655d9a8Sdsl memset(&stats->uvmexp, 0, sizeof(stats->uvmexp));
4361655d9a8Sdsl }
4371655d9a8Sdsl size = sizeof(stats->Total);
4381655d9a8Sdsl mib[0] = CTL_VM;
4391655d9a8Sdsl mib[1] = VM_METER;
4401655d9a8Sdsl if (sysctl(mib, 2, &stats->Total, &size, NULL, 0) < 0) {
4411655d9a8Sdsl error("Can't get kernel info: %s\n", strerror(errno));
4421655d9a8Sdsl memset(&stats->Total, 0, sizeof(stats->Total));
4431655d9a8Sdsl }
4441655d9a8Sdsl }
445