gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
fd_array.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Advanced Micro Devices, Inc.
3  * All rights reserved.
4  *
5  * For use for simulation and test purposes only
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived from this
19  * software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Author: Brandon Potter
34  */
35 
36 #include "sim/fd_array.hh"
37 
38 #include <fcntl.h>
39 #include <unistd.h>
40 
41 #include <array>
42 #include <memory>
43 #include <string>
44 
45 #include "base/misc.hh"
46 #include "params/Process.hh"
47 #include "sim/fd_entry.hh"
48 
49 FDArray::FDArray(std::string const& input, std::string const& output,
50  std::string const& errout)
51  : _input(input), _output(output), _errout(errout), _fdArray(),
52  imap {{"", -1},
53  {"cin", STDIN_FILENO},
54  {"stdin", STDIN_FILENO}},
55  oemap{{"", -1},
56  {"cout", STDOUT_FILENO},
57  {"stdout", STDOUT_FILENO},
58  {"cerr", STDERR_FILENO},
59  {"stderr", STDERR_FILENO}}
60 {
61  int sim_fd;
62  std::map<std::string, int>::iterator it;
63 
68  if ((it = imap.find(input)) != imap.end())
69  sim_fd = it->second;
70  else
71  sim_fd = openInputFile(input);
72 
73  auto ffd = std::make_shared<FileFDEntry>(sim_fd, O_RDONLY, input, false);
74  _fdArray[STDIN_FILENO] = ffd;
75 
80  if ((it = oemap.find(output)) != oemap.end())
81  sim_fd = it->second;
82  else
83  sim_fd = openOutputFile(output);
84 
85  ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
86  output, false);
87  _fdArray[STDOUT_FILENO] = ffd;
88 
89  if (output == errout)
90  ; /* Reuse the same file descriptor if these match. */
91  else if ((it = oemap.find(errout)) != oemap.end())
92  sim_fd = it->second;
93  else
94  sim_fd = openOutputFile(errout);
95 
96  ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
97  errout, false);
98  _fdArray[STDERR_FILENO] = ffd;
99 }
100 
101 void
103 {
104  for (auto& fdp : _fdArray) {
110  auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp);
111 
112  if (!ffd)
113  continue;
114 
119  int sim_fd = ffd->getSimFD();
120  ffd->setFileOffset(lseek(sim_fd, 0, SEEK_CUR));
121  }
122 }
123 
124 void
126 {
134  void (*seek)(std::shared_ptr<FileFDEntry>)
135  = [] (std::shared_ptr<FileFDEntry> ffd)
136  {
137  if (lseek(ffd->getSimFD(), ffd->getFileOffset(), SEEK_SET) < 0)
138  fatal("Unable to seek to location in %s", ffd->getFileName());
139  };
140 
141  std::map<std::string, int>::iterator it;
142 
150  std::shared_ptr<FDEntry> stdin_fde = _fdArray[STDIN_FILENO];
151  auto stdin_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdin_fde);
152 
153  if (_input != stdin_ffd->getFileName()) {
154  warn("Using new input file (%s) rather than checkpointed (%s)\n",
155  _input, stdin_ffd->getFileName());
156  stdin_ffd->setFileName(_input);
157  stdin_ffd->setFileOffset(0);
158  }
159 
160  if ((it = imap.find(stdin_ffd->getFileName())) != imap.end()) {
161  stdin_ffd->setSimFD(it->second);
162  } else {
163  stdin_ffd->setSimFD(openInputFile(stdin_ffd->getFileName()));
164  seek(stdin_ffd);
165  }
166 
174  std::shared_ptr<FDEntry> stdout_fde = _fdArray[STDOUT_FILENO];
175  auto stdout_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdout_fde);
176 
177  if (_output != stdout_ffd->getFileName()) {
178  warn("Using new output file (%s) rather than checkpointed (%s)\n",
179  _output, stdout_ffd->getFileName());
180  stdout_ffd->setFileName(_output);
181  stdout_ffd->setFileOffset(0);
182  }
183 
184  if ((it = oemap.find(stdout_ffd->getFileName())) != oemap.end()) {
185  stdout_ffd->setSimFD(it->second);
186  } else {
187  stdout_ffd->setSimFD(openOutputFile(stdout_ffd->getFileName()));
188  seek(stdout_ffd);
189  }
190 
198  std::shared_ptr<FDEntry> stderr_fde = _fdArray[STDERR_FILENO];
199  auto stderr_ffd = std::dynamic_pointer_cast<FileFDEntry>(stderr_fde);
200 
201  if (_errout != stderr_ffd->getFileName()) {
202  warn("Using new error file (%s) rather than checkpointed (%s)\n",
203  _errout, stderr_ffd->getFileName());
204  stderr_ffd->setFileName(_errout);
205  stderr_ffd->setFileOffset(0);
206  }
207 
208  if (stdout_ffd->getFileName() == stderr_ffd->getFileName()) {
209  /* Reuse the same sim_fd file descriptor if these match. */
210  stderr_ffd->setSimFD(stdout_ffd->getSimFD());
211  } else if ((it = oemap.find(stderr_ffd->getFileName())) != oemap.end()) {
212  stderr_ffd->setSimFD(it->second);
213  } else {
214  stderr_ffd->setSimFD(openOutputFile(stderr_ffd->getFileName()));
215  seek(stderr_ffd);
216  }
217 
218  for (int tgt_fd = 3; tgt_fd < _fdArray.size(); tgt_fd++) {
219  std::shared_ptr<FDEntry> fdp = _fdArray[tgt_fd];
220  if (!fdp)
221  continue;
222 
223  /* Need to reconnect pipe ends. */
224  if (auto pfd = std::dynamic_pointer_cast<PipeFDEntry>(fdp)) {
230  if (pfd->getEndType() == PipeFDEntry::EndType::write)
231  continue;
232 
233  /* Setup the pipe or fatal out of the simulation. */
234  int fd_pair[2];
235  if (pipe(fd_pair) < 0)
236  fatal("Unable to create new pipe");
237 
242  pfd->setSimFD(fd_pair[0]);
243 
248  int prs = pfd->getPipeReadSource();
249  std::shared_ptr<FDEntry> write_fdp = _fdArray[prs];
250 
251  /* Now cast it and make sure that we are still sane. */
252  auto write_pfd = std::dynamic_pointer_cast<PipeFDEntry>(write_fdp);
253 
254  /* Hook up the write end back to the right side of the pipe. */
255  write_pfd->setSimFD(fd_pair[1]);
256  }
257 
258  /* Need to reassign 'driver'. */
259  if (auto dfd = std::dynamic_pointer_cast<DeviceFDEntry>(fdp)) {
265  fatal("Unable to restore checkpoints with emulated drivers");
266  }
267 
268  /* Need to open files and seek. */
269  if (auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp)) {
277  int sim_fd = openFile(ffd->getFileName(), ffd->getFlags(), 0664);
278  ffd->setSimFD(sim_fd);
279  seek(ffd);
280  }
281  }
282 }
283 
284 int
285 FDArray::allocFD(std::shared_ptr<FDEntry> in)
286 {
287  for (int i = 0; i < _fdArray.size(); i++) {
288  std::shared_ptr<FDEntry> fdp = _fdArray[i];
289  if (!fdp) {
290  _fdArray[i] = in;
291  return i;
292  }
293  }
294  fatal("Out of target file descriptors");
295 }
296 
297 int
298 FDArray::openFile(std::string const& filename, int flags, mode_t mode) const
299 {
300  int sim_fd = open(filename.c_str(), flags, mode);
301  if (sim_fd != -1)
302  return sim_fd;
303  fatal("Unable to open %s with mode %O", filename, mode);
304 }
305 
306 int
307 FDArray::openInputFile(std::string const& filename) const
308 {
309  return openFile(filename, O_RDONLY, 00);
310 }
311 
312 int
313 FDArray::openOutputFile(std::string const& filename) const
314 {
315  return openFile(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
316 }
317 
318 std::shared_ptr<FDEntry>
319 FDArray::getFDEntry(int tgt_fd)
320 {
321  assert(0 <= tgt_fd && tgt_fd < _fdArray.size());
322  return _fdArray[tgt_fd];
323 }
324 
325 void
326 FDArray::setFDEntry(int tgt_fd, std::shared_ptr<FDEntry> fdep)
327 {
328  assert(0 <= tgt_fd && tgt_fd < _fdArray.size());
329  _fdArray[tgt_fd] = fdep;
330 }
331 
332 int
333 FDArray::closeFDEntry(int tgt_fd)
334 {
335  if (tgt_fd >= _fdArray.size() || tgt_fd < 0)
336  return -EBADF;
337 
338  int sim_fd = -1;
339  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>(_fdArray[tgt_fd]);
340  if (hbfdp)
341  sim_fd = hbfdp->getSimFD();
342 
343  int status = 0;
344  if (sim_fd > 2)
345  status = close(sim_fd);
346 
347  if (status == 0)
348  _fdArray[tgt_fd] = nullptr;
349 
350  return status;
351 }
std::string _output
Definition: fd_array.hh:63
int openOutputFile(std::string const &file_name) const
static void output(const char *filename)
Definition: debug.cc:63
Bitfield< 7 > i
Definition: miscregs.hh:1378
void setFDEntry(int tgt_fd, std::shared_ptr< FDEntry > fdep)
Put the pointer specified by fdep into the _fdArray entry indexed by tgt_fd.
Holds file descriptors for host-backed files; host-backed files are files which were opened on the ph...
Definition: fd_entry.hh:102
void setSimFD(int sim_fd)
Definition: fd_entry.hh:87
int getSimFD() const
Definition: fd_entry.hh:84
int openInputFile(std::string const &file_name) const
Bitfield< 4, 0 > mode
Definition: miscregs.hh:1385
int closeFDEntry(int tgt_fd)
Try to close the host file descriptor.
void restoreFileOffsets()
Restore all offsets for currently open files during the unserialize phase for the owning process clas...
#define warn(...)
Definition: misc.hh:219
Bitfield< 5, 0 > status
Definition: miscregs.hh:1604
int allocFD(std::shared_ptr< FDEntry > fdp)
Step through the file descriptor array and find the first available entry which is denoted as being f...
int openFile(std::string const &file_name, int flags, mode_t mode) const
Help clarify our intention when opening files in the init and restoration code.
FDArray(std::string const &input, std::string const &output, std::string const &errout)
Initialize the file descriptor array and set the standard file descriptors to defaults or values pass...
Definition: fd_array.cc:49
std::string _input
Definition: fd_array.hh:62
#define fatal(...)
Definition: misc.hh:163
Extends the base class to include a host-backed file descriptor field that records the integer used t...
Definition: fd_entry.hh:76
std::map< std::string, int > oemap
Definition: fd_array.hh:153
Holds the metadata needed to maintain the mappings for file descriptors allocated with the pipe() sys...
Definition: fd_entry.hh:140
void updateFileOffsets()
Figure out the file offsets for all currently open files and save them the offsets during the calls t...
std::string _errout
Definition: fd_array.hh:64
std::map< std::string, int > imap
Hold strings which represent the default values which are checked against to initialize the standard ...
Definition: fd_array.hh:152
std::shared_ptr< FDEntry > getFDEntry(int tgt_fd)
Return the file descriptor entry object associated with the index provided.

Generated on Fri Jun 9 2017 13:03:51 for gem5 by doxygen 1.8.6