Commit 23df7824 authored by Michal Berger's avatar Michal Berger Committed by Tomasz Zawadzki
Browse files

lib/event: Introduce init_proc_stat() variant for FreeBSD



Current parse_proc_stat() is Linux-specific yet it's being called
unconditionally. This leads to confusing NOTICE()s under non-Linux
systems, like FreeBSD:

  spdk_app_start: *NOTICE*: Total cores available: 2
  app.c: 952:spdk_app_start: *NOTICE*: Unable to parse /proc/stat [core: 0].
  app.c: 952:spdk_app_start: *NOTICE*: Unable to parse /proc/stat [core: 1].
  reactor.c: 996:reactor_run: *NOTICE*: Reactor started on core 0
  reactor.c: 996:reactor_run: *NOTICE*: Reactor started on core 1

To avoid this confusion add parse_proc_stat() variant dedicated to
FreeBSD. Similarly to reading Linux's /proc/stat, the FreeBSD variant
fetches accumulated number of cpu ticks for different states by
reading sysctl's kern.cp_times node, e.g.:

 # e.g for 2 CPUs
 $ sysctl kern.cp_times
 kern.cp_times: 37924 0 2593 961 9270910 19400 0 1341 4 9291643

Output is formatted as a single line holding 5 states per cpu:
  user nice system interrupt idle

Similarly to Linux-based variant, we fetch user, system and interrupt
counters. Note that kern.cp_times doesn't account separately for soft
irqs as in case of Linux's /proc/stat.

Change-Id: I36eea531dee4aace2aad18ed346659b3c9dacd08
Signed-off-by: default avatarMichal Berger <michal.berger@nutanix.com>
Reviewed-on: https://review.spdk.io/c/spdk/spdk/+/26379


Reviewed-by: default avatarKonrad Sztyber <ksztyber@nvidia.com>
Tested-by: default avatarSPDK Automated Test System <spdkbot@gmail.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz@tzawadzki.com>
Community-CI: Mellanox Build Bot
parent 809162d0
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -80,6 +80,11 @@ extern "C" {
#include <sched.h>
#endif

/* FreeBSD */
#if defined(__FreeBSD__)
#include <sys/sysctl.h>
#endif

/* FreeBSD or Linux */
#if defined(__FreeBSD__) || defined(__linux__)
#include <aio.h>
+46 −1
Original line number Diff line number Diff line
@@ -151,6 +151,44 @@ static const struct option g_cmdline_options[] = {
	{"enforce-numa",		no_argument,		NULL, ENFORCE_NUMA_OPT_IDX},
};

#if defined(__FreeBSD__)
static int
parse_proc_stat(unsigned int core, uint64_t *user, uint64_t *sys, uint64_t *irq)
{
	size_t len, ncpu = 0;
	long *cp_times;

	len = sizeof(ncpu);
	if (sysctlbyname("hw.ncpu", &ncpu, &len, NULL, 0) < 0) {
		return -1;
	}
	if (core >= ncpu) {
		return -1;
	}
	/*
	 * kern.cp_times returns 5 (CPUSTATES) values per cpu in a single line. E.g. for 4 cpus
	 *   kern.cp_times: 37924 0 2593 961 9270910 19400 0 1341 4 9291643 868 0 1338 2 9310180 938 0 1382 9 9309979
	 * Values in order are:
	 *   user nice system interrupt idle
	 */
	len = ncpu * CPUSTATES * sizeof(long);
	cp_times = malloc(len);
	if (cp_times == NULL) {
		return -1;
	}
	if (sysctlbyname("kern.cp_times", cp_times, &len, NULL, 0) < 0) {
		free(cp_times);
		return -1;
	}

	*user = (uint64_t)cp_times[core * CPUSTATES + 0];
	*sys = (uint64_t)cp_times[core * CPUSTATES + 2];
	*irq = (uint64_t)cp_times[core * CPUSTATES + 3];

	free(cp_times);
	return 0;
}
#elif defined(__linux__)
static int
parse_proc_stat(unsigned int core, uint64_t *user, uint64_t *sys, uint64_t *irq)
{
@@ -184,6 +222,13 @@ parse_proc_stat(unsigned int core, uint64_t *user, uint64_t *sys, uint64_t *irq)
	fclose(f);
	return found ? 0 : -1;
}
#else
static int
parse_proc_stat(unsigned int core, uint64_t *user, uint64_t *sys, uint64_t *irq)
{
	return -1;
}
#endif

static int
init_proc_stat(unsigned int core)
@@ -949,7 +994,7 @@ spdk_app_start(struct spdk_app_opts *opts_user, spdk_msg_fn start_fn,
	SPDK_ENV_FOREACH_CORE(core) {
		rc = init_proc_stat(core);
		if (rc) {
			SPDK_NOTICELOG("Unable to parse /proc/stat [core: %d].\n", core);
			SPDK_NOTICELOG("Unable to parse CPU statistics [core: %d].\n", core);
		}
	}