gem5  v21.1.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules 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 
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 namespace gem5
49 {
50 
51 FDArray::FDArray(std::string const& input, std::string const& output,
52  std::string const& errout)
53  : _fdArray(), _input(input), _output(output), _errout(errout),
54  _imap {{"", -1},
55  {"cin", STDIN_FILENO},
56  {"stdin", STDIN_FILENO}},
57  _oemap{{"", -1},
58  {"cout", STDOUT_FILENO},
59  {"stdout", STDOUT_FILENO},
60  {"cerr", STDERR_FILENO},
61  {"stderr", STDERR_FILENO}}
62 {
63  int sim_fd;
64  std::map<std::string, int>::iterator it;
65 
70  if ((it = _imap.find(input)) != _imap.end())
71  sim_fd = it->second;
72  else
73  sim_fd = openInputFile(input);
74 
75  auto ffd = std::make_shared<FileFDEntry>(sim_fd, O_RDONLY, input, false);
76  _fdArray[STDIN_FILENO] = ffd;
77 
82  if ((it = _oemap.find(output)) != _oemap.end())
83  sim_fd = it->second;
84  else
85  sim_fd = openOutputFile(output);
86 
87  ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
88  output, false);
89  _fdArray[STDOUT_FILENO] = ffd;
90 
91  if (output == errout)
92  ; /* Reuse the same file descriptor if these match. */
93  else if ((it = _oemap.find(errout)) != _oemap.end())
94  sim_fd = it->second;
95  else
96  sim_fd = openOutputFile(errout);
97 
98  ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
99  errout, false);
100  _fdArray[STDERR_FILENO] = ffd;
101 }
102 
103 void
105 {
106  for (auto& fdp : _fdArray) {
112  auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp);
113 
114  if (!ffd)
115  continue;
116 
121  int sim_fd = ffd->getSimFD();
122  ffd->setFileOffset(lseek(sim_fd, 0, SEEK_CUR));
123  }
124 }
125 
126 void
128 {
136  auto seek = [] (std::shared_ptr<FileFDEntry> ffd)
137  {
138  if (lseek(ffd->getSimFD(), ffd->getFileOffset(), SEEK_SET) < 0)
139  fatal("Unable to seek to location in %s", ffd->getFileName());
140  };
141 
142  std::map<std::string, int>::iterator it;
143 
151  std::shared_ptr<FDEntry> stdin_fde = _fdArray[STDIN_FILENO];
152  auto stdin_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdin_fde);
153 
154  if (_input != stdin_ffd->getFileName()) {
155  warn("Using new input file (%s) rather than checkpointed (%s)\n",
156  _input, stdin_ffd->getFileName());
157  stdin_ffd->setFileName(_input);
158  stdin_ffd->setFileOffset(0);
159  }
160 
161  if ((it = _imap.find(stdin_ffd->getFileName())) != _imap.end()) {
162  stdin_ffd->setSimFD(it->second);
163  } else {
164  stdin_ffd->setSimFD(openInputFile(stdin_ffd->getFileName()));
165  seek(stdin_ffd);
166  }
167 
175  std::shared_ptr<FDEntry> stdout_fde = _fdArray[STDOUT_FILENO];
176  auto stdout_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdout_fde);
177 
178  if (_output != stdout_ffd->getFileName()) {
179  warn("Using new output file (%s) rather than checkpointed (%s)\n",
180  _output, stdout_ffd->getFileName());
181  stdout_ffd->setFileName(_output);
182  stdout_ffd->setFileOffset(0);
183  }
184 
185  if ((it = _oemap.find(stdout_ffd->getFileName())) != _oemap.end()) {
186  stdout_ffd->setSimFD(it->second);
187  } else {
188  stdout_ffd->setSimFD(openOutputFile(stdout_ffd->getFileName()));
189  seek(stdout_ffd);
190  }
191 
199  std::shared_ptr<FDEntry> stderr_fde = _fdArray[STDERR_FILENO];
200  auto stderr_ffd = std::dynamic_pointer_cast<FileFDEntry>(stderr_fde);
201 
202  if (_errout != stderr_ffd->getFileName()) {
203  warn("Using new error file (%s) rather than checkpointed (%s)\n",
204  _errout, stderr_ffd->getFileName());
205  stderr_ffd->setFileName(_errout);
206  stderr_ffd->setFileOffset(0);
207  }
208 
209  if (stdout_ffd->getFileName() == stderr_ffd->getFileName()) {
210  /* Reuse the same sim_fd file descriptor if these match. */
211  stderr_ffd->setSimFD(stdout_ffd->getSimFD());
212  } else if ((it = _oemap.find(stderr_ffd->getFileName())) != _oemap.end()) {
213  stderr_ffd->setSimFD(it->second);
214  } else {
215  stderr_ffd->setSimFD(openOutputFile(stderr_ffd->getFileName()));
216  seek(stderr_ffd);
217  }
218 
219  for (int tgt_fd = 3; tgt_fd < _fdArray.size(); tgt_fd++) {
220  std::shared_ptr<FDEntry> fdp = _fdArray[tgt_fd];
221  if (!fdp)
222  continue;
223 
224  /* Need to reconnect pipe ends. */
225  if (auto pfd = std::dynamic_pointer_cast<PipeFDEntry>(fdp)) {
231  if (pfd->getEndType() == PipeFDEntry::EndType::write)
232  continue;
233 
234  /* Setup the pipe or fatal out of the simulation. */
235  int fd_pair[2];
236  if (pipe(fd_pair) < 0)
237  fatal("Unable to create new pipe");
238 
243  pfd->setSimFD(fd_pair[0]);
244 
249  int prs = pfd->getPipeReadSource();
250  std::shared_ptr<FDEntry> write_fdp = _fdArray[prs];
251 
252  /* Now cast it and make sure that we are still sane. */
253  auto write_pfd = std::dynamic_pointer_cast<PipeFDEntry>(write_fdp);
254 
255  /* Hook up the write end back to the right side of the pipe. */
256  write_pfd->setSimFD(fd_pair[1]);
257  }
258 
259  /* Need to reassign 'driver'. */
260  if (auto dfd = std::dynamic_pointer_cast<DeviceFDEntry>(fdp)) {
266  fatal("Unable to restore checkpoints with emulated drivers");
267  }
268 
269  /* Need to open files and seek. */
270  if (auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp)) {
278  int sim_fd = openFile(ffd->getFileName(), ffd->getFlags(), 0664);
279  ffd->setSimFD(sim_fd);
280  seek(ffd);
281  }
282  }
283 }
284 
285 int
286 FDArray::allocFD(std::shared_ptr<FDEntry> in)
287 {
288  for (int i = 0; i < _fdArray.size(); i++) {
289  std::shared_ptr<FDEntry> fdp = _fdArray[i];
290  if (!fdp) {
291  _fdArray[i] = in;
292  return i;
293  }
294  }
295  fatal("Out of target file descriptors");
296 }
297 
298 int
299 FDArray::openFile(std::string const& filename, int flags, mode_t mode) const
300 {
301  int sim_fd = open(filename.c_str(), flags, mode);
302  if (sim_fd != -1)
303  return sim_fd;
304  fatal("Unable to open %s with mode %d", filename, mode);
305 }
306 
307 int
308 FDArray::openInputFile(std::string const& filename) const
309 {
310  return openFile(filename, O_RDONLY, 00);
311 }
312 
313 int
314 FDArray::openOutputFile(std::string const& filename) const
315 {
316  return openFile(simout.resolve(filename),
317  O_WRONLY | O_CREAT | O_TRUNC, 0664);
318 }
319 
320 std::shared_ptr<FDEntry>
322 {
323  assert(0 <= tgt_fd && tgt_fd < _fdArray.size());
324  return _fdArray[tgt_fd];
325 }
326 
327 void
328 FDArray::setFDEntry(int tgt_fd, std::shared_ptr<FDEntry> fdep)
329 {
330  assert(0 <= tgt_fd && tgt_fd < _fdArray.size());
331  _fdArray[tgt_fd] = fdep;
332 }
333 
334 int
336 {
337  if (tgt_fd >= _fdArray.size() || tgt_fd < 0)
338  return -EBADF;
339 
340  int sim_fd = -1;
341  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>(_fdArray[tgt_fd]);
342  if (hbfdp)
343  sim_fd = hbfdp->getSimFD();
344 
345  int status = 0;
346  if (sim_fd > 2)
347  status = close(sim_fd);
348 
349  if (status == 0)
350  _fdArray[tgt_fd] = nullptr;
351 
352  return status;
353 }
354 
355 void
357  ScopedCheckpointSection sec(cp, "fdarray");
358  paramOut(cp, "size", _fdArray.size());
359  for (int tgt_fd = 0; tgt_fd < _fdArray.size(); tgt_fd++) {
360  auto fd = _fdArray[tgt_fd];
361  ScopedCheckpointSection sec(cp, csprintf("Entry%d", tgt_fd));
362  if (!fd) {
363  paramOut(cp, "class", FDEntry::FDClass::fd_null);
364  continue;
365  }
366  paramOut(cp, "class", fd->getClass());
367  fd->serialize(cp);
368  }
369 }
370 
371 void
373  ScopedCheckpointSection sec(cp, "fdarray");
374  uint64_t size;
375  paramIn(cp, "size", size);
376  assert(_fdArray.size() == size &&
377  "FDArray sizes do not match at unserialize!");
378 
379  for (int tgt_fd = 0; tgt_fd < _fdArray.size(); tgt_fd++) {
380  if (tgt_fd == STDIN_FILENO || tgt_fd == STDOUT_FILENO ||
381  tgt_fd == STDERR_FILENO)
382  continue;
383  ScopedCheckpointSection sec(cp, csprintf("Entry%d", tgt_fd));
384  FDEntry::FDClass fd_class;
385  paramIn(cp, "class", fd_class);
386  std::shared_ptr<FDEntry> fdep;
387 
388  switch (fd_class) {
389  case FDEntry::FDClass::fd_base:
390  panic("Abstract fd entry was serialized");
391  break;
392  case FDEntry::FDClass::fd_hb:
393  fdep = std::make_shared<HBFDEntry>(0, 0);
394  break;
395  case FDEntry::FDClass::fd_file:
396  fdep = std::make_shared<FileFDEntry>(0, 0, "", 0, 00);
397  break;
398  case FDEntry::FDClass::fd_device:
399  fdep = std::make_shared<DeviceFDEntry>(nullptr, "");
400  break;
401  case FDEntry::FDClass::fd_pipe:
402  fdep = std::make_shared<PipeFDEntry>(
403  0, 0, PipeFDEntry::EndType::read);
404  break;
405  case FDEntry::FDClass::fd_socket:
406  fdep = std::make_shared<SocketFDEntry>(0, 0, 0, 0);
407  break;
408  case FDEntry::FDClass::fd_null:
409  continue;
410  default:
411  panic("Unrecognized fd class");
412  break;
413  }
414 
415  fdep->unserialize(cp);
416 
417  auto this_ffd = std::dynamic_pointer_cast<FileFDEntry>(fdep);
418  if (!this_ffd)
419  continue;
420  setFDEntry(tgt_fd, fdep);
421 
422  mode_t mode = this_ffd->getFileMode();
423  std::string const& path = this_ffd->getFileName();
424  int flags = this_ffd->getFlags();
425 
426  // Re-open the file and assign a new sim_fd
427  int sim_fd = openFile(path, flags, mode);
428  this_ffd->setSimFD(sim_fd);
429 
430  // Restore the file offset to the proper value
431  uint64_t file_offset = this_ffd->getFileOffset();
432  lseek(sim_fd, file_offset, SEEK_SET);
433  }
434 }
435 
436 } // namespace gem5
gem5::FDArray::restoreFileOffsets
void restoreFileOffsets()
Restore all offsets for currently open files during the unserialize phase for the owning process clas...
Definition: fd_array.cc:127
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:189
gem5::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:286
warn
#define warn(...)
Definition: logging.hh:245
gem5::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:51
fd_entry.hh
gem5::ArmISA::fd
Bitfield< 14, 12 > fd
Definition: types.hh:150
gem5::output
static void output(const char *filename)
Definition: debug.cc:66
gem5::Serializable::path
static std::stack< std::string > path
Definition: serialize.hh:315
gem5::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:164
gem5::CheckpointIn
Definition: serialize.hh:68
gem5::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:328
gem5::FDArray::_output
std::string _output
Definition: fd_array.hh:155
gem5::FDArray::openOutputFile
int openOutputFile(std::string const &file_name) const
Definition: fd_array.cc:314
gem5::simout
OutputDirectory simout
Definition: output.cc:62
gem5::csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
gem5::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:299
fd_array.hh
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:66
output.hh
gem5::FDArray::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: fd_array.cc:372
gem5::FDArray::_fdArray
std::array< std::shared_ptr< FDEntry >, _numFDs > _fdArray
Definition: fd_array.hh:147
gem5::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:154
gem5::FDArray::closeFDEntry
int closeFDEntry(int tgt_fd)
Try to close the host file descriptor.
Definition: fd_array.cc:335
gem5::OutputDirectory::resolve
std::string resolve(const std::string &name) const
Returns relative file names prepended with name of this directory.
Definition: output.cc:204
gem5::FDArray::_oemap
std::map< std::string, int > _oemap
Definition: fd_array.hh:165
gem5::FDArray::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: fd_array.cc:356
gem5::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:104
gem5::FDEntry::FDClass
FDClass
Definition: fd_entry.hh:57
gem5::paramOut
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition: types.cc:40
gem5::paramIn
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition: types.cc:72
logging.hh
gem5::CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:66
gem5::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:321
gem5::FDArray::openInputFile
int openInputFile(std::string const &file_name) const
Definition: fd_array.cc:308
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
gem5::FDArray::_errout
std::string _errout
Definition: fd_array.hh:156
gem5::Serializable::ScopedCheckpointSection
Definition: serialize.hh:172
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:177
gem5::ArmISA::status
Bitfield< 5, 0 > status
Definition: misc_types.hh:422
gem5::ArmISA::mode
Bitfield< 4, 0 > mode
Definition: misc_types.hh:73

Generated on Wed Jul 28 2021 12:10:29 for gem5 by doxygen 1.8.17