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:
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");
+ }
+};