diff options
author | Benjamin Barenblat <bbarenblat@galois.com> | 2014-01-13 15:56:57 -0800 |
---|---|---|
committer | Benjamin Barenblat <bbarenblat@galois.com> | 2014-01-13 15:56:57 -0800 |
commit | b69ec3f6d953e67422dd32b72688cba850fd1b2e (patch) | |
tree | a24e664807c19bd3b50f504ce0d33df24f135a23 /src |
Initial commit
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 35 | ||||
-rw-r--r-- | src/index.dox | 45 | ||||
-rw-r--r-- | src/require.h | 46 | ||||
-rw-r--r-- | src/timing.c | 86 | ||||
-rw-r--r-- | src/timing.h | 32 | ||||
-rw-r--r-- | src/tracer.c | 133 |
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ü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; +} |