OnDemand.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file OnDemand.h
3 /// \brief Utilities for mapping in library files on-demand
4 /// \author Christopher Backhouse - bckhouse@caltech.edu
5 ////////////////////////////////////////////////////////////////////////
6 
7 #include "LEM/func/OnDemand.h"
8 
9 #include <cassert>
10 #include <cstring>
11 #include <deque>
12 #include <vector>
13 
14 #include <sys/mman.h>
15 #include <sys/stat.h>
16 
17 #include <signal.h>
18 #include <cstdio>
19 #include <cstdlib>
20 
21 
22 // There's no way to pass any context to sigaction, so we have to keep our
23 // state globally here. That's OK. It lets us check for overlapping mappings at
24 // least...
25 
26 // Private to this file
27 namespace
28 {
29  unsigned int gMemoryLimit = 0; // Bytes
30  const int kPageSize = 10*1024*1024; // Our internal pages (10MB)
31 
32  /// Definition of a memory mapping
33  struct Mapping
34  {
35  Mapping(const std::string& f, const char* b, size_t l)
36  : fname(f), base(b), length(l) {}
37 
38  std::string fname; ///< Name of file to map in
39  const char* base; ///< Where the start of the file should go
40  size_t length; ///< How long the file is (bytes)
41  };
42 
43  /// All the mappings we've been asked to make
44  std::vector<Mapping> gMappings;
45 
46  /// The addresses of all pages we currently have mapped in, oldest first
47  std::deque<void*> gMappedList;
48 
49  /// Handler for segfault, maps in the required part of a file, if possible
50  void segfault_sigaction(int signal, siginfo_t* si, void* /*arg*/)
51  {
52  assert(si->si_signo == SIGSEGV);
53 
54  // Find what mapping this address is in
55  int mappingIdx = -1;
56  for(unsigned int n = 0; n < gMappings.size(); ++n){
57  if(si->si_addr >= gMappings[n].base &&
58  si->si_addr < gMappings[n].base+gMappings[n].length){
59  assert(mappingIdx == -1); // No overlapping mappings
60  mappingIdx = n;
61  }
62  }
63 
64  // Out of range of our mappings
65  if(mappingIdx < 0){
66  // Reset the handler to nothing and resume. The program will die at the
67  // correct point without our fingerprints all over it.
68  struct sigaction sa;
69  memset(&sa, 0, sizeof(sa));
70  sigemptyset(&sa.sa_mask);
71 
72  sa.sa_sigaction = 0;
73 
74  sigaction(SIGSEGV, &sa, NULL);
75  return;
76  }
77 
78 
79  // If there's a memory limit set
80  if(gMemoryLimit > 0){
81  // Keep discarding memory until we're below it
82  while(gMappedList.size()*kPageSize >= gMemoryLimit){
83  // Discard least recently used
84  munmap(gMappedList.front(), kPageSize);
85  gMappedList.pop_front();
86  }
87  }
88 
89 
90  Mapping map = gMappings[mappingIdx];
91 
92  FILE* f = fopen(map.fname.c_str(), "r");
93  assert(f);
94 
95  // Where are we in the file?
96  long offset = long((char*)si->si_addr-(char*)map.base);
97  // Round down to the start of the page this is in
98  offset = (offset/kPageSize)*kPageSize;
99 
100  void* ret = mmap((char*)map.base+offset,
101  kPageSize,
102  PROT_READ,
103  MAP_SHARED | MAP_FIXED,
104  fileno(f),
105  offset);
106 
107  fclose(f);
108  // Make sure we got our mapping
109  assert(ret != (void*)-1);
110 
111  gMappedList.push_back((char*)map.base+offset);
112  }
113 }
114 
115 namespace lem
116 {
117  void SetOnDemandMemoryLimit(long limit_mb)
118  {
119  // Convert to bytes
120  gMemoryLimit = limit_mb<<20;
121  }
122 
123  void CreateOnDemandMapping(const std::string& fname, const char* base)
124  {
125  // Must be aligned on OS pages
126  assert(long(base)%(4*1024) == 0);
127 
128  // Open the file to check it exists and find out its length
129  FILE* f = fopen(fname.c_str(), "r");
130  assert(f);
131 
132  struct stat st;
133  fstat(fileno(f), &st);
134  const long fsize = st.st_size;
135  fclose(f);
136 
137 
138  gMappings.push_back(Mapping(fname, base, fsize));
139 
140  // Set up signal handler to fault this file (and others) in on demand. It
141  // should be OK to do this multiple times.
142  struct sigaction sa;
143  memset(&sa, 0, sizeof(sa));
144  sigemptyset(&sa.sa_mask);
145 
146  sa.sa_sigaction = segfault_sigaction;
147  sa.sa_flags = SA_SIGINFO;
148 
149  sigaction(SIGSEGV, &sa, NULL);
150  }
151 }
const XML_Char int const XML_Char int const XML_Char * base
Definition: expat.h:331
PID
Definition: FillPIDs.h:14
fclose(fg1)
length
Definition: demo0.py:21
std::void_t< T > n
Utilities for mapping in library files on-demand.
void SetOnDemandMemoryLimit(long limit_mb)
Definition: OnDemand.cxx:117
const hit & b
Definition: hits.cxx:21
assert(nhit_max >=nhit_nbins)
unsigned int fileno
Definition: runWimpSim.h:102
void CreateOnDemandMapping(const std::string &fname, const char *base)
Definition: OnDemand.cxx:123
enum BeamMode string