citrun

watch C/C++ source code execute
Log | Files | Refs | LICENSE

commit 7cd6a6f21651f2e98d1b9a1449eeeda13f904600
parent 42d862e255af9b7d7cc2a0a7167feb8104bdd1a5
Author: Kyle Milz <kyle@0x30.net>
Date:   Sat, 14 Jan 2017 13:45:23 -0700

gl: break out shared memory handling into an os-indep class

Diffstat:
Mgl_procfile.cc | 47++++++++++-------------------------------------
Mgl_procfile.h | 17++++++++++-------
Mgl_transunit.cc | 25++++++++++---------------
Mgl_transunit.h | 9+++++----
Amem.h | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amem_unix.h | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 154 insertions(+), 63 deletions(-)

diff --git a/gl_procfile.cc b/gl_procfile.cc @@ -13,16 +13,10 @@ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // -#include <sys/mman.h> // mmap -#include <sys/stat.h> // S_IRUSR, S_IWUSR - -#include <cassert> +#include <cassert> // assert #include <csignal> // kill -#include <cstring> // strncmp -#include <err.h> -#include <fcntl.h> // O_RDONLY -#include <sstream> -#include <unistd.h> // getpagesize +#include <cstring> // std::strncmp +#include <sstream> // std::stringstream #include "gl_procfile.h" #include "lib.h" // citrun_major, struct citrun_{node,header} @@ -33,30 +27,11 @@ // structure on top of it. // GlProcessFile::GlProcessFile(std::string const &path, demo_font_t *font) : - m_path(path), - m_fd(0) + m_mem(path) { - struct stat sb; - void *mem, *end; - - if ((m_fd = open(m_path.c_str(), O_RDONLY, S_IRUSR | S_IWUSR)) < 0) - err(1, "open"); - - if (fstat(m_fd, &sb) < 0) - err(1, "fstat"); - - // Explicitly check 0 here otherwise mmap barfs. - if (sb.st_size == 0 || sb.st_size > 1024 * 1024 * 1024) - errx(1, "invalid file size %lli", sb.st_size); - - m_size = sb.st_size; - - mem = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, m_fd, 0); - if (mem == MAP_FAILED) - err(1, "mmap"); - - // Header is always at offset 0 and always one page long. - m_header = static_cast<struct citrun_header *>(mem); + // Header is always at offset 0. + m_header = static_cast<struct citrun_header *>(m_mem.get_ptr()); + m_mem.increment(sizeof(struct citrun_header)); assert(std::strncmp(m_header->magic, "ctrn", 4) == 0); assert(m_header->major == citrun_major); @@ -71,13 +46,11 @@ GlProcessFile::GlProcessFile(std::string const &path, demo_font_t *font) : glyphy_point_t cur_pos; m_glbuffer.current_point(&cur_pos); - end = (char *)mem + m_size; - mem = (char *)mem + getpagesize(); + while (!m_mem.at_end()) + m_tus.emplace_back(m_mem, font, cur_pos); - while (mem < end) - m_tus.emplace_back(mem, font, cur_pos); // Make sure internal increment in TranslationUnit works as intended. - assert(mem == end); + assert(m_mem.at_end_exactly()); } // diff --git a/gl_procfile.h b/gl_procfile.h @@ -1,8 +1,9 @@ -#include <string> -#include <vector> +#include <string> // std::string +#include <vector> // std::vector -#include "gl_buffer.h" -#include "gl_transunit.h" +#include "gl_buffer.h" // GlBuffer +#include "gl_transunit.h" // GlTranslationUnit +#include "mem_unix.h" // MemUnix // @@ -12,10 +13,12 @@ class GlProcessFile { struct citrun_header *m_header; - std::string m_path; - int m_fd; - size_t m_size; GlBuffer m_glbuffer; +#ifdef _WIN32 + MemWin32 m_mem; +#else + MemUnix m_mem; +#endif public: GlProcessFile(std::string const &, demo_font_t *); diff --git a/gl_transunit.cc b/gl_transunit.cc @@ -13,11 +13,9 @@ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // -#include <cstring> // memcpy -#include <err.h> -#include <fstream> -#include <iostream> -#include <unistd.h> // getpagesize +#include <cstring> // std::memcpy +#include <fstream> // std::ifstream +#include <iostream> // std::cerr #include "gl_transunit.h" #include "lib.h" // struct citrun_node @@ -27,21 +25,18 @@ // Take a pointer to a shared memory region and map data structures on top. // Automatically increments the pointer once we know how big this region is. // -GlTranslationUnit::GlTranslationUnit(void* &mem, demo_font_t *font, +GlTranslationUnit::GlTranslationUnit(Mem &m_mem, demo_font_t *font, glyphy_point_t &cur_pos) : - m_node(static_cast<struct citrun_node *>(mem)), + m_node(static_cast<struct citrun_node *>(m_mem.get_ptr())), m_data((unsigned long long *)(m_node + 1)), m_data_buffer(m_node->size) { - unsigned int size, page_mask; + unsigned int size; // Total size is node size plus live execution data size. size = sizeof(struct citrun_node); size += m_node->size * sizeof(unsigned long long); - - // Increment passed in pointer to next page. - page_mask = getpagesize() - 1; - mem = (char *)mem + ((size + page_mask) & ~page_mask); + m_mem.increment(size); glyphy_point_t next_pos = cur_pos; next_pos.x += 80; @@ -51,7 +46,7 @@ GlTranslationUnit::GlTranslationUnit(void* &mem, demo_font_t *font, std::ifstream file_stream(m_node->abs_file_path); if (file_stream.is_open() == 0) { - warnx("ifstream.open(%s)", m_node->abs_file_path); + std::cerr << "ifstream.open: " << m_node->abs_file_path << std::endl; return; } @@ -66,8 +61,8 @@ GlTranslationUnit::GlTranslationUnit(void* &mem, demo_font_t *font, } if (i != m_node->size) - warnx("%s size mismatch: %u vs %u", m_node->abs_file_path, i, - m_node->size); + std::cerr << m_node->abs_file_path << " size mismatch: " + << i << " vs " << m_node->size << std::endl; } // diff --git a/gl_transunit.h b/gl_transunit.h @@ -1,7 +1,8 @@ -#include <string> -#include <vector> +#include <string> // std::string +#include <vector> // std::vector -#include "gl_buffer.h" +#include "gl_buffer.h" // GlBuffer +#include "mem.h" // Mem // @@ -15,7 +16,7 @@ class GlTranslationUnit GlBuffer m_glbuffer; public: - GlTranslationUnit(void* &, demo_font_t *, glyphy_point_t &); + GlTranslationUnit(Mem &, demo_font_t *, glyphy_point_t &); std::string comp_file_path() const; unsigned int num_lines() const; diff --git a/mem.h b/mem.h @@ -0,0 +1,58 @@ +#ifndef MEM_H +#define MEM_H + +#include <string> // std::string + +// +// Class that handles operating system independent access to blocks of memory +// that are efficiently sized for the underlying system. +// +class Mem +{ + size_t m_off; + + // Allocation size is system dependent. + virtual size_t alloc_size() = 0; + +protected: + void *m_base; + size_t m_size; + +public: + Mem() : + m_off(0) + {}; + + void + increment(size_t size) + { + size_t page_mask; + size_t rounded_size; + + // Round up to next allocation size. + page_mask = alloc_size() - 1; + rounded_size = (size + page_mask) & ~page_mask; + + m_off += rounded_size; + } + + void * + get_ptr() + { + return (char *)m_base + m_off; + } + + bool + at_end() + { + return m_off >= m_size; + } + + bool + at_end_exactly() + { + return m_off == m_size; + } + +}; +#endif // MEM_H diff --git a/mem_unix.h b/mem_unix.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2016 Kyle Milz <kyle@0x30.net> +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +#include <sys/mman.h> // mmap +#include <sys/stat.h> // S_IRUSR, S_IWUSR + +#include <err.h> +#include <fcntl.h> // O_RDONLY +#include <unistd.h> // getpagesize + +#include "mem.h" // Mem + + +class MemUnix : public Mem +{ + std::string m_path; + int m_fd; + + // Mandatory implementation. + size_t + alloc_size() + { + return getpagesize(); + } + +public: + MemUnix(std::string const &path) : + m_path(path), + m_fd(0) + { + struct stat sb; + + if ((m_fd = open(m_path.c_str(), O_RDONLY, S_IRUSR | S_IWUSR)) < 0) + err(1, "open"); + + if (fstat(m_fd, &sb) < 0) + err(1, "fstat"); + + // Explicitly check 0 here otherwise mmap barfs. + if (sb.st_size == 0 || sb.st_size > 1024 * 1024 * 1024) + errx(1, "invalid file size %lli", sb.st_size); + + m_size = sb.st_size; + + m_base = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, m_fd, 0); + if (m_base == MAP_FAILED) + err(1, "mmap"); + } +};