gem5  v20.1.0.0
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 
34 #include "sim/fd_array.hh"
35 
36 #include <fcntl.h>
37 #include <unistd.h>
38 
39 #include <array>
40 #include <memory>
41 #include <string>
42 
43 #include "base/logging.hh"
44 #include "base/output.hh"
45 #include "params/Process.hh"
46 #include "sim/fd_entry.hh"
47 
48 FDArray::FDArray(std::string const& input, std::string const& output,
49  std::string const& errout)
50  : _fdArray(), _input(input), _output(output), _errout(errout),
51  _imap {{"", -1},
52  {"cin", STDIN_FILENO},
53  {"stdin", STDIN_FILENO}},
54  _oemap{{"", -1},
55  {"cout", STDOUT_FILENO},
56  {"stdout", STDOUT_FILENO},
57  {"cerr", STDERR_FILENO},
58  {"stderr", STDERR_FILENO}}
59 {
60  int sim_fd;
61  std::map<std::string, int>::iterator it;
62 
67  if ((it = _imap.find(input)) != _imap.end())
68  sim_fd = it->second;
69  else
70  sim_fd = openInputFile(input);
71 
72  auto ffd = std::make_shared<FileFDEntry>(sim_fd, O_RDONLY, input, false);
73  _fdArray[STDIN_FILENO] = ffd;
74 
79  if ((it = _oemap.find(output)) != _oemap.end())
80  sim_fd = it->second;
81  else
82  sim_fd = openOutputFile(output);
83 
84  ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
85  output, false);
86  _fdArray[STDOUT_FILENO] = ffd;
87 
88  if (output == errout)
89  ; /* Reuse the same file descriptor if these match. */
90  else if ((it = _oemap.find(errout)) != _oemap.end())
91  sim_fd = it->second;
92  else
93  sim_fd = openOutputFile(errout);
94 
95  ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
96  errout, false);
97  _fdArray[STDERR_FILENO] = ffd;
98 }
99 
100 void
102 {
103  for (auto& fdp : _fdArray) {
109  auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp);
110 
111  if (!ffd)
112  continue;
113 
118  int sim_fd = ffd->getSimFD();
119  ffd->setFileOffset(lseek(sim_fd, 0, SEEK_CUR));
120  }
121 }
122 
123 void
125 {
133  auto seek = [] (std::shared_ptr<FileFDEntry> ffd)
134  {
135  if (lseek(ffd->getSimFD(), ffd->getFileOffset(), SEEK_SET) < 0)
136  fatal("Unable to seek to location in %s", ffd->getFileName());
137  };
138 
139  std::map<std::string, int>::iterator it;
140 
148  std::shared_ptr<FDEntry> stdin_fde = _fdArray[STDIN_FILENO];
149  auto stdin_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdin_fde);
150 
151  if (_input != stdin_ffd->getFileName()) {
152  warn("Using new input file (%s) rather than checkpointed (%s)\n",
153  _input, stdin_ffd->getFileName());
154  stdin_ffd->setFileName(_input);
155  stdin_ffd->setFileOffset(0);
156  }
157 
158  if ((it = _imap.find(stdin_ffd->getFileName())) != _imap.end()) {
159  stdin_ffd->setSimFD(it->second);
160  } else {
161  stdin_ffd->setSimFD(openInputFile(stdin_ffd->getFileName()));
162  seek(stdin_ffd);
163  }
164 
172  std::shared_ptr<FDEntry> stdout_fde = _fdArray[STDOUT_FILENO];
173  auto stdout_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdout_fde);
174 
175  if (_output != stdout_ffd->getFileName()) {
176  warn("Using new output file (%s) rather than checkpointed (%s)\n",
177  _output, stdout_ffd->getFileName());
178  stdout_ffd->setFileName(_output);
179  stdout_ffd->setFileOffset(0);
180  }
181 
182  if ((it = _oemap.find(stdout_ffd->getFileName())) != _oemap.end()) {
183  stdout_ffd->setSimFD(it->second);
184  } else {
185  stdout_ffd->setSimFD(openOutputFile(stdout_ffd->getFileName()));
186  seek(stdout_ffd);
187  }
188 
196  std::shared_ptr<FDEntry> stderr_fde = _fdArray[STDERR_FILENO];
197  auto stderr_ffd = std::dynamic_pointer_cast<FileFDEntry>(stderr_fde);
198 
199  if (_errout != stderr_ffd->getFileName()) {
200  warn("Using new error file (%s) rather than checkpointed (%s)\n",
201  _errout, stderr_ffd->getFileName());
202  stderr_ffd->setFileName(_errout);
203  stderr_ffd->setFileOffset(0);
204  }
205 
206  if (stdout_ffd->getFileName() == stderr_ffd->getFileName()) {
207  /* Reuse the same sim_fd file descriptor if these match. */
208  stderr_ffd->setSimFD(stdout_ffd->getSimFD());
209  } else if ((it = _oemap.find(stderr_ffd->getFileName())) != _oemap.end()) {
210  stderr_ffd->setSimFD(it->second);
211  } else {
212  stderr_ffd->setSimFD(openOutputFile(stderr_ffd->getFileName()));
213  seek(stderr_ffd);
214  }
215 
216  for (int tgt_fd = 3; tgt_fd < _fdArray.size(); tgt_fd++) {
217  std::shared_ptr<FDEntry> fdp = _fdArray[tgt_fd];
218  if (!fdp)
219  continue;
220 
221  /* Need to reconnect pipe ends. */
222  if (auto pfd = std::dynamic_pointer_cast<PipeFDEntry>(fdp)) {
228  if (pfd->getEndType() == PipeFDEntry::EndType::write)
229  continue;
230 
231  /* Setup the pipe or fatal out of the simulation. */
232  int fd_pair[2];
233  if (pipe(fd_pair) < 0)
234  fatal("Unable to create new pipe");
235 
240  pfd->setSimFD(fd_pair[0]);
241 
246  int prs = pfd->getPipeReadSource();
247  std::shared_ptr<FDEntry> write_fdp = _fdArray[prs];
248 
249  /* Now cast it and make sure that we are still sane. */
250  auto write_pfd = std::dynamic_pointer_cast<PipeFDEntry>(write_fdp);
251 
252  /* Hook up the write end back to the right side of the pipe. */
253  write_pfd->setSimFD(fd_pair[1]);
254  }
255 
256  /* Need to reassign 'driver'. */
257  if (auto dfd = std::dynamic_pointer_cast<DeviceFDEntry>(fdp)) {
263  fatal("Unable to restore checkpoints with emulated drivers");
264  }
265 
266  /* Need to open files and seek. */
267  if (auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp)) {
275  int sim_fd = openFile(ffd->getFileName(), ffd->getFlags(), 0664);
276  ffd->setSimFD(sim_fd);
277  seek(ffd);
278  }
279  }
280 }
281 
282 int
283 FDArray::allocFD(std::shared_ptr<FDEntry> in)
284 {
285  for (int i = 0; i < _fdArray.size(); i++) {
286  std::shared_ptr<FDEntry> fdp = _fdArray[i];
287  if (!fdp) {
288  _fdArray[i] = in;
289  return i;
290  }
291  }
292  fatal("Out of target file descriptors");
293 }
294 
295 int
296 FDArray::openFile(std::string const& filename, int flags, mode_t mode) const
297 {
298  int sim_fd = open(filename.c_str(), flags, mode);
299  if (sim_fd != -1)
300  return sim_fd;
301  fatal("Unable to open %s with mode %O", filename, mode);
302 }
303 
304 int
305 FDArray::openInputFile(std::string const& filename) const
306 {
307  return openFile(filename, O_RDONLY, 00);
308 }
309 
310 int
311 FDArray::openOutputFile(std::string const& filename) const
312 {
313  return openFile(simout.resolve(filename),
314  O_WRONLY | O_CREAT | O_TRUNC, 0664);
315 }
316 
317 std::shared_ptr<FDEntry>
319 {
320  assert(0 <= tgt_fd && tgt_fd < _fdArray.size());
321  return _fdArray[tgt_fd];
322 }
323 
324 void
325 FDArray::setFDEntry(int tgt_fd, std::shared_ptr<FDEntry> fdep)
326 {
327  assert(0 <= tgt_fd && tgt_fd < _fdArray.size());
328  _fdArray[tgt_fd] = fdep;
329 }
330 
331 int
333 {
334  if (tgt_fd >= _fdArray.size() || tgt_fd < 0)
335  return -EBADF;
336 
337  int sim_fd = -1;
338  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>(_fdArray[tgt_fd]);
339  if (hbfdp)
340  sim_fd = hbfdp->getSimFD();
341 
342  int status = 0;
343  if (sim_fd > 2)
344  status = close(sim_fd);
345 
346  if (status == 0)
347  _fdArray[tgt_fd] = nullptr;
348 
349  return status;
350 }
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:183
ArmISA::status
Bitfield< 5, 0 > status
Definition: miscregs_types.hh:417
output
static void output(const char *filename)
Definition: debug.cc:60
FDArray::openFile
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.
Definition: fd_array.cc:296
warn
#define warn(...)
Definition: logging.hh:239
FDArray::_output
std::string _output
Definition: fd_array.hh:144
fd_entry.hh
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
fd_array.hh
OutputDirectory::resolve
std::string resolve(const std::string &name) const
Returns relative file names prepended with name of this directory.
Definition: output.cc:203
output.hh
FDArray::FDArray
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:48
FDArray::_input
std::string _input
Hold param strings passed from the Process class which indicate the filename for each of the correspo...
Definition: fd_array.hh:143
FDArray::_fdArray
std::array< std::shared_ptr< FDEntry >, _numFDs > _fdArray
Definition: fd_array.hh:136
ArmISA::mode
Bitfield< 4, 0 > mode
Definition: miscregs_types.hh:70
FDArray::_errout
std::string _errout
Definition: fd_array.hh:145
FDArray::openInputFile
int openInputFile(std::string const &file_name) const
Definition: fd_array.cc:305
FDArray::updateFileOffsets
void updateFileOffsets()
Figure out the file offsets for all currently open files and save them the offsets during the calls t...
Definition: fd_array.cc:101
FDArray::allocFD
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...
Definition: fd_array.cc:283
FDArray::_oemap
std::map< std::string, int > _oemap
Definition: fd_array.hh:154
FDArray::setFDEntry
void setFDEntry(int tgt_fd, std::shared_ptr< FDEntry > fdep)
Put the pointer specified by fdep into the _fdArray entry indexed by tgt_fd.
Definition: fd_array.cc:325
FDArray::_imap
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:153
logging.hh
FDArray::getFDEntry
std::shared_ptr< FDEntry > getFDEntry(int tgt_fd)
Return the file descriptor entry object associated with the index provided.
Definition: fd_array.cc:318
simout
OutputDirectory simout
Definition: output.cc:61
FDArray::restoreFileOffsets
void restoreFileOffsets()
Restore all offsets for currently open files during the unserialize phase for the owning process clas...
Definition: fd_array.cc:124
FDArray::closeFDEntry
int closeFDEntry(int tgt_fd)
Try to close the host file descriptor.
Definition: fd_array.cc:332
FDArray::openOutputFile
int openOutputFile(std::string const &file_name) const
Definition: fd_array.cc:311

Generated on Wed Sep 30 2020 14:02:14 for gem5 by doxygen 1.8.17