From df23af17d84a110bf685bb80a30095ca10a118e5 Mon Sep 17 00:00:00 2001
From: Robert Izzard <r.izzard@surrey.ac.uk>
Date: Mon, 25 Nov 2019 12:05:18 +0800
Subject: [PATCH] more cleanup of the meson build:

put in a compiled test for CPU frequency (when available)
---
 meson.build                        | 77 ++++++++++++++++++++++++----
 meson/cpu_frequency.sh             |  1 -
 src/debug/libbacktrace_functions.h | 80 ++++++++++++++++++------------
 3 files changed, 117 insertions(+), 41 deletions(-)

diff --git a/meson.build b/meson.build
index 786cc979c..1f726eda6 100644
--- a/meson.build
+++ b/meson.build
@@ -1,10 +1,23 @@
 ############################################################
 # meson build file for binary_c
 # 
-# (c) Robert Izzard 10/11/2019
+# (c) Robert Izzard 25/11/2019
 #
 # Known to work with binary_c 2.1.4 using gcc and clang.
 #
+# Supporting scripts are in the meson directory of binary_c.
+#
+# You may well require: bash, gawk, cp, grep, wc, tr, head
+#                       and perl. These are standard tools on
+#                       most systems.
+#
+# You certainly require a C compiler (e.g. gcc or clang),
+# python3 and ninja.
+#
+# Please see the binary_c installation documentation
+# in the doc/ directory of binary_c or
+# http://personal.ph.surrey.ac.uk/~ri0005/doc/binary_c/binary_c.html
+#
 ############################################################
 
 ############################################################
@@ -46,16 +59,51 @@ project(
 compiler = meson.get_compiler('c')
 
 ############################################################
-# bail if compiler is buggy/unsupported
+# exit if compiler is buggy/unsupported
 #
 if compiler.get_id() == 'gcc' and \
-   compiler.version() = '4.7.4'
-    error('gcc 4.7.4 is buggy and unsupported')
+   compiler.version() == '4.7.4'
+    error('gcc 4.7.4 is buggy and hence unsupported : please upgrade!')
 endif
 
 ############################################################
 # System information
-cpufreq = run_command('meson/cpu_frequency.sh').stdout().strip()
+if(host_machine.cpu_family() == 'x86_64')
+    # test on 64-bit Intels
+    _cpufreq = compiler.run( '''
+#include <stdio.h>
+#include <cpuid.h>
+int main(void) 
+{
+    /* code based on Linux' turbostat.c by Intel (GPL2) */
+    unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0, max_level = 0;
+    __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
+    /* only works on Skylake (level 0x16) and later */
+    if (max_level >= 0x16) 
+    {
+        unsigned int base_mhz = 0, max_mhz = 0, bus_mhz = 0;
+        __get_cpuid(0x16, &base_mhz, &max_mhz, &bus_mhz, &edx);
+        fprintf(stdout,"%u",max_mhz);
+        return 1;
+    } 
+    else
+    {
+        fprintf(stdout,"0");
+        return 0;
+    }
+}''')
+else
+    _cpufreq = compiler.run('this should error')
+endif
+
+if _cpufreq.compiled() == true and _cpufreq.returncode() != 0
+    # use result of above code to extract CPU Mhz
+    cpufreq = _cpufreq.stdout()
+else
+    # fallback script to use system tools
+    cpufreq = run_command('meson/cpu_frequency.sh').stdout().strip()
+endif
+message('CPU frequency ' + cpufreq + 'MHz')
 
 ############################################################
 # get home directory
@@ -68,7 +116,6 @@ binary_c_src = meson.source_root() + '/src'
 
 ############################################################
 # binary_c version
-# (should be the same as the project version)
 #
 binary_c_version = compiler.run('''
 #include <stdio.h>
@@ -79,6 +126,10 @@ int main(int argc,char **argv)
         return 0;
 }''').stdout().strip()  
 
+############################################################
+# the binary_c version should be the same as the project
+# version: exit if not!
+#
 if binary_c_version != meson.project_version()
     error('binary_c_version and meson.project_version are not the same : they should be!')
 else
@@ -110,11 +161,17 @@ absolute_incdirs = [
 absolute_libdirs = [
 ]
 
+############################################################
+# Data alignment: the longest native data type binary_c
+# uses is double, so select this for alignment.
+#
+alignsize = '-DALIGNSIZE=' + compiler.alignment('double').to_string() 
+
 ############################################################
 # default C flags
 #
 cflags = [
-    '-DALIGNSIZE=16'
+    alignsize
 ]
 executable_build_flags = [
 ]
@@ -229,7 +286,9 @@ endif
 ############################################################
 # system options
 #
-cflags += '-DCPUFREQ=' + cpufreq
+if cpufreq != ''
+    cflags += '-DCPUFREQ=' + cpufreq
+endif
 
 ############################################################
 # operating system flags
@@ -280,7 +339,7 @@ endif
 
 ############################################################
 # version control options
-
+#
 if git_revision != ''
     _flag = '-DGIT_REVISION="' + git_revision + '"'
     cflags += _flag
diff --git a/meson/cpu_frequency.sh b/meson/cpu_frequency.sh
index 26fa8af90..294035406 100755
--- a/meson/cpu_frequency.sh
+++ b/meson/cpu_frequency.sh
@@ -2,7 +2,6 @@
 
 # wrapper script to show maximum CPU frequency in Mhz
 
-
 SYSFILE="/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
 
 if [ -f $SYSFILE ]; then
diff --git a/src/debug/libbacktrace_functions.h b/src/debug/libbacktrace_functions.h
index 850c20cdf..c891947e4 100644
--- a/src/debug/libbacktrace_functions.h
+++ b/src/debug/libbacktrace_functions.h
@@ -3,53 +3,71 @@
 #define LIBBACKTRACE_FUNCTIONS
 
 /*
-* Stuff for using libbacktrace, taken from their 
-* example code at 
-* https://github.com/ErwanLegrand/libbacktrace/blob/master/examples/bt.c
-* although the updated version is at
-* https://github.com/ianlancetaylor/libbacktrace
-*/
+ * Stuff for using libbacktrace, taken from their 
+ * example code at 
+ * https://github.com/ErwanLegrand/libbacktrace/blob/master/examples/bt.c
+ * although the updated version is at
+ * https://github.com/ianlancetaylor/libbacktrace
+ */
 static void error_callback(void *data, const char *msg, int errnum)
 {
-	struct bt_ctx *ctx = data;
-	fprintf(stderr, "ERROR: %s (%d)", msg, errnum);
-	ctx->error = 1;
+    struct bt_ctx *ctx = data;
+    fprintf(stderr, "ERROR: %s (%d)", msg, errnum);
+    ctx->error = 1;
 }
 
-static void syminfo_callback (void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize)
+static void syminfo_callback (void *data,
+                              uintptr_t pc,
+                              const char *symname,
+                              uintptr_t symval,
+                              uintptr_t symsize)
 {
-	//struct bt_ctx *ctx = data;
-	if (symname) {
-		printf("%lx %s ??:0\n", (unsigned long)pc, symname);
-	} else {
-		printf("%lx ?? ??:0\n", (unsigned long)pc);
-	}
+    if (symname)
+    {
+        printf("%lx %s ??:0\n", (unsigned long)pc, symname);
+    }
+    else
+    {
+        printf("%lx ?? ??:0\n", (unsigned long)pc);
+    }
 }
 
-static int full_callback(void *data, uintptr_t pc, const char *filename, int lineno, const char *function)
+static int full_callback(void *data,
+                         uintptr_t pc,
+                         const char *filename,
+                         int lineno,
+                         const char *function)
 {
-	struct bt_ctx *ctx = data;
-	if (function) {
-		printf("%lx %s %s:%d\n", (unsigned long)pc, function, filename?filename:"??", lineno);
-	} else {
-		backtrace_syminfo (ctx->state, pc, syminfo_callback, error_callback, data);
-	}
-	return 0;
+    struct bt_ctx *ctx = data;
+    if (function)
+    {
+        printf("%lx %s %s:%d\n", (unsigned long)pc, function, filename?filename:"??", lineno);
+    }
+    else
+    {
+        backtrace_syminfo (ctx->state,
+                           pc,
+                           (backtrace_syminfo_callback)syminfo_callback,
+                           error_callback,
+                           data);
+    }
+    return 0;
 }
 
 
-static int simple_callback(void *data, uintptr_t pc)
+static int simple_callback(void *data,
+                           uintptr_t pc)
 {
-	struct bt_ctx *ctx = data;
-	backtrace_pcinfo(ctx->state, pc, full_callback, error_callback, data);
-	return 0;
+    struct bt_ctx *ctx = data;
+    backtrace_pcinfo(ctx->state, pc, full_callback, error_callback, data);
+    return 0;
 }
 
 static inline void bt(struct backtrace_state *state)
 {
-	struct bt_ctx ctx = {state, 0};
-	backtrace_print(state, 0, stdout);
-	backtrace_simple(state, 0, simple_callback, error_callback, &ctx);
+    struct bt_ctx ctx = {state, 0};
+    backtrace_print(state, 0, stdout);
+    backtrace_simple(state, 0, simple_callback, error_callback, &ctx);
 }
 
 
-- 
GitLab