aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Benjamin Barenblat <bbarenblat@galois.com>2014-01-13 15:56:57 -0800
committerGravatar Benjamin Barenblat <bbarenblat@galois.com>2014-01-13 15:56:57 -0800
commitb69ec3f6d953e67422dd32b72688cba850fd1b2e (patch)
treea24e664807c19bd3b50f504ce0d33df24f135a23 /src
Initial commit
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am35
-rw-r--r--src/index.dox45
-rw-r--r--src/require.h46
-rw-r--r--src/timing.c86
-rw-r--r--src/timing.h32
-rw-r--r--src/tracer.c133
6 files changed, 377 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..d5f4ab2
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,35 @@
+# Makefile.am -- automake script for ppamltracer
+# Copyright (C) 2013 Galois, Inc.
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+# Oregon, 97204-1622.
+
+lib_LTLIBRARIES = libppamltracer.la
+libppamltracer_la_SOURCES = \
+ $(srcdir)/require.h \
+ $(srcdir)/timing.c \
+ $(srcdir)/timing.h \
+ $(srcdir)/tracer.c
+libppamltracer_la_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -std=c99 \
+ -Wall \
+ -Wextra \
+ -pedantic \
+ @OTF_CFLAGS@
+libppamltracer_la_LIBADD = @OTF_LIBS@
+libppamltracer_la_LDFLAGS = -export-symbols-regex '^ppaml_'
diff --git a/src/index.dox b/src/index.dox
new file mode 100644
index 0000000..3dd4b77
--- /dev/null
+++ b/src/index.dox
@@ -0,0 +1,45 @@
+/* index.dox -- front-page documentation for ppamltracer -*- c -*-
+ * Copyright (C) 2013 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+/**
+ * @mainpage Overview
+ *
+ * ppamltracer is a lightweight, portable tracing library designed for explicit
+ * instrumention of generated code. If you're writing a compiler and need hard
+ * data on your optimizer's efficacy, ppamltracer is the library for you.
+ *
+ * @ref simple.c shows ppamltracer in action tracing two phases of computation
+ * (factorials and Fibonacci numbers), and honestly, it's probably all the API
+ * documentation you need. You can also have a look at @ref ppaml_tracer_t and
+ * @ref ppaml_phase_t, the data structures which ppamltracer manipulates.
+ *
+ * ppamltracer writes trace logs in the [Open Trace Format]
+ * (http://tu-dresden.de/zih/otf/), a free and open standard developed by the
+ * Zentrum f&uuml;r Informationsdienste und Hochleistungsrechnen (Center for
+ * Information Services and High-Performance Computing) at the Technical
+ * University of Dresden.
+ *
+ * We developed ppamltracer as part of DARPA's [Probabilistic Programming for
+ * Advancing Machine Learning]
+ * (http://darpa.mil/Our_Work/I2O/Programs/Probabilistic_Programming_for_Advanced_Machine_Learning_(PPAML%29.aspx)
+ * (PPAML) project.
+ *
+ * @example simple.c
+ */
diff --git a/src/require.h b/src/require.h
new file mode 100644
index 0000000..f731c15
--- /dev/null
+++ b/src/require.h
@@ -0,0 +1,46 @@
+/* require.h -- useful error-handling macros
+ * Copyright (C) 2013 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+#ifndef REQUIRE_H
+#define REQUIRE_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define require_not(var, val, ret_val) \
+ do { \
+ if ((var) != val) { \
+ r = ret_val; \
+ goto done; \
+ } \
+ } while (0)
+#define require_zero(var, ret_val) require_not(var, 0, ret_val)
+#define require_one(var, ret_val) require_not(var, 1, ret_val)
+
+#define require_nonnull(ptr, ret_val) \
+ do { \
+ if ((ptr) == NULL) { \
+ r = ret_val; \
+ goto done; \
+ } \
+ } while (0)
+
+#endif
diff --git a/src/timing.c b/src/timing.c
new file mode 100644
index 0000000..25cbba7
--- /dev/null
+++ b/src/timing.c
@@ -0,0 +1,86 @@
+/* timing.c -- cross-platform wall time
+ * Copyright (C) 2013 Galois, Inc. All rights reserved. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#define _POSIX_C_SOURCE 199309L
+
+#include <stdint.h>
+
+#include "timing.h"
+#include "require.h"
+
+#define ignore(var) ((void)(var))
+
+const uint64_t MICRO_PER_BASE = 1000000;
+const uint64_t NANO_PER_MICRO = 1000;
+
+// Try to use the POSIX timers, if possible.
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#if (HAVE_UNISTD_H && _POSIX_TIMERS > 0)
+
+# include <time.h>
+
+# if __linux__
+ /* Hopefully, you're running linux >=2.6.28, and
+ * CLOCK_MONOTONIC_RAW exists. */
+ static const clockid_t CLOCK_ID = CLOCK_MONOTONIC_RAW;
+# elif _POSIX_MONOTONIC_CLOCK
+ // You're not on Linux, but you've got a POSIX monotonic clock.
+ static const clockid_t CLOCK_ID = CLOCK_MONOTONIC;
+# else
+ // Just use the POSIX wall clock.
+ static const clockid_t CLOCK_ID = CLOCK_REALTIME;
+# endif
+
+ int timing_get_wall(uint64_t *const result)
+ {
+ int r = 0;
+ struct timespec now;
+ require_zero(clock_gettime(CLOCK_ID, &now), 1);
+ *result = (uint64_t)now.tv_sec * MICRO_PER_BASE
+ + (uint64_t)now.tv_nsec / NANO_PER_MICRO;
+ done: return r;
+ }
+
+#elif (__APPLE__ && __MACH__)
+
+ /* No POSIX timers, but we're on a Mac, so we can use
+ * 'mach_absolute_time'. */
+# include <mach/mach_time.h>
+
+ int timing_get_wall(uint64_t *const result)
+ {
+ static mach_timebase_info_data_t timebase_info;
+ int r = 0;
+ *result = mach_absolute_time();
+ /* *result is now in units of Mach ticks. Convert that to
+ * nanoseconds using the timebase information that Mach
+ * provides. Note that 'timebase_info' is static, so it got
+ * zeroed out at the start of the program run; if its
+ * denominator is still zero, we've definitely not stored
+ * anything in it yet. */
+ if (timebase_info.denom == 0) {
+ require_zero(mach_timebase_info(&timebase_info), 1);
+ }
+ *result = *result * timebase_info.numer / timebase_info.denom;
+ // Convert nanoseconds to microseconds.
+ *result /= NANO_PER_MICRO;
+ done: return r;
+ }
+
+#else
+
+ // I have no clue what wacky platform you're on.
+# error Unsupported timing platform
+
+ int timing_get_wall(uint64_t *const result)
+ {
+ ignore(result);
+ return -1;
+ }
+
+#endif
diff --git a/src/timing.h b/src/timing.h
new file mode 100644
index 0000000..167e536
--- /dev/null
+++ b/src/timing.h
@@ -0,0 +1,32 @@
+/* timing.h -- cross-platform wall time
+ * Copyright (C) 2013 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+#ifndef TIMING_H
+#define TIMING_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdint.h>
+
+int timing_get_wall(uint64_t *result);
+
+#endif
diff --git a/src/tracer.c b/src/tracer.c
new file mode 100644
index 0000000..be2f3cc
--- /dev/null
+++ b/src/tracer.c
@@ -0,0 +1,133 @@
+/* tracer.c -- PPAML timing instrumentation
+ * Copyright (C) 2013 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <otf.h>
+
+#include <ppaml/tracer.h>
+#include <ppaml/tracer/internal.h>
+
+#include "timing.h"
+#include "require.h"
+
+const size_t ppaml_tracer_t_size = sizeof(ppaml_tracer_t);
+const size_t ppaml_phase_t_size = sizeof(ppaml_phase_t);
+
+int ppaml_tracer_init(
+ ppaml_tracer_t *const tracer,
+ const char report_name_base[])
+{
+ int r = 0;
+ // Initialize the file manager.
+ const uint32_t max_fds = 1024; // TODO: ulimit default on my system
+ tracer->manager = OTF_FileManager_open(max_fds);
+ require_nonnull(tracer->manager, 1);
+ // Initialize the writer.
+ tracer->writer = OTF_Writer_open(report_name_base, 1, tracer->manager);
+ require_nonnull(tracer->writer, 2);
+ // Record that we have a resolution of 1 microsecond.
+ require_one(
+ OTF_Writer_writeDefTimerResolution(tracer->writer, 0, 1000000),
+ 3);
+ // Define an OTF process (i.e., a thread).
+ require_one(
+ OTF_Writer_writeDefProcess(tracer->writer, 0, 1, "main", 0),
+ 4);
+done: return r;
+}
+
+int ppaml_tracer_done(ppaml_tracer_t *const tracer)
+{
+ int r = 0;
+ // Close the writer.
+ require_one(OTF_Writer_close(tracer->writer), 1);
+ tracer->writer = NULL;
+ // Close the file manager.
+ OTF_FileManager_close(tracer->manager);
+ tracer->manager = NULL;
+done: return r;
+}
+
+int ppaml_phase_init(
+ ppaml_tracer_t *const tracer,
+ ppaml_phase_t *const phase,
+ const char name[])
+{
+ static uint32_t next_function_id = 1;
+ int r = 0;
+ require_one(
+ OTF_Writer_writeDefFunction(
+ tracer->writer,
+ 0, // stream id = 1
+ next_function_id,
+ name,
+ 0, // no function group
+ 0), // no source code
+ 1);
+ phase->tracer = tracer;
+ phase->otf_function_id = next_function_id;
+ next_function_id++;
+done: return r;
+}
+
+int ppaml_phase_done(ppaml_phase_t *const phase)
+{
+ phase->tracer = NULL;
+ phase->otf_function_id = 0;
+ return 0;
+}
+
+int ppaml_phase_start(ppaml_phase_t *const phase)
+{
+ int r = 0;
+ uint64_t now;
+ require_zero(timing_get_wall(&now), 1);
+ require_one(
+ OTF_Writer_writeEnter(
+ phase->tracer->writer,
+ now,
+ phase->otf_function_id,
+ 1, // process id = 1
+ 0), // no source code
+ 2);
+done: return r;
+}
+
+int ppaml_phase_stop(ppaml_phase_t *const phase)
+{
+ int r = 0;
+ uint64_t now;
+ require_zero(timing_get_wall(&now), 1);
+ require_one(
+ OTF_Writer_writeLeave(
+ phase->tracer->writer,
+ now,
+ phase->otf_function_id,
+ 1, // process id = 1
+ 0), // no source code
+ 2);
+done: return r;
+}