summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpu-compute/cl_driver.cc11
-rw-r--r--src/sim/SConscript1
-rw-r--r--src/sim/fd_array.cc344
-rw-r--r--src/sim/fd_array.hh148
-rw-r--r--src/sim/fd_entry.cc133
-rw-r--r--src/sim/fd_entry.hh248
-rw-r--r--src/sim/process.cc276
-rw-r--r--src/sim/process.hh49
-rw-r--r--src/sim/syscall_emul.cc176
-rw-r--r--src/sim/syscall_emul.hh152
10 files changed, 960 insertions, 578 deletions
diff --git a/src/gpu-compute/cl_driver.cc b/src/gpu-compute/cl_driver.cc
index 41ae3ab9a..119091fc5 100644
--- a/src/gpu-compute/cl_driver.cc
+++ b/src/gpu-compute/cl_driver.cc
@@ -35,6 +35,8 @@
#include "gpu-compute/cl_driver.hh"
+#include <memory>
+
#include "base/intmath.hh"
#include "cpu/thread_context.hh"
#include "gpu-compute/dispatcher.hh"
@@ -93,11 +95,10 @@ ClDriver::handshake(GpuDispatcher *_dispatcher)
int
ClDriver::open(Process *p, ThreadContext *tc, int mode, int flags)
{
- int fd = p->allocFD(-1, filename, 0, 0, false);
- FDEntry *fde = p->getFDEntry(fd);
- fde->driver = this;
-
- return fd;
+ std::shared_ptr<DeviceFDEntry> fdp;
+ fdp = std::make_shared<DeviceFDEntry>(this, filename);
+ int tgt_fd = p->fds->allocFD(fdp);
+ return tgt_fd;
}
int
diff --git a/src/sim/SConscript b/src/sim/SConscript
index 6b0b8430b..c36b33b51 100644
--- a/src/sim/SConscript
+++ b/src/sim/SConscript
@@ -78,6 +78,7 @@ if env['TARGET_ISA'] != 'null':
Source('aux_vector.cc')
Source('faults.cc')
Source('process.cc')
+ Source('fd_array.cc')
Source('fd_entry.cc')
Source('pseudo_inst.cc')
Source('syscall_emul.cc')
diff --git a/src/sim/fd_array.cc b/src/sim/fd_array.cc
new file mode 100644
index 000000000..d73707054
--- /dev/null
+++ b/src/sim/fd_array.cc
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Brandon Potter
+ */
+
+#include "sim/fd_array.hh"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <array>
+#include <memory>
+#include <string>
+
+#include "base/misc.hh"
+#include "params/Process.hh"
+#include "sim/fd_entry.hh"
+
+FDArray::FDArray(std::string const& input, std::string const& output,
+ std::string const& errout)
+ : _input(input), _output(output), _errout(errout), _fdArray(),
+ imap {{"", -1},
+ {"cin", STDIN_FILENO},
+ {"stdin", STDIN_FILENO}},
+ oemap{{"", -1},
+ {"cout", STDOUT_FILENO},
+ {"stdout", STDOUT_FILENO},
+ {"cerr", STDERR_FILENO},
+ {"stderr", STDERR_FILENO}}
+{
+ int sim_fd;
+ std::map<std::string, int>::iterator it;
+
+ /**
+ * Search through the input options and setup the default fd if match is
+ * found; otherwise, open an input file and seek to location.
+ */
+ if ((it = imap.find(input)) != imap.end())
+ sim_fd = it->second;
+ else
+ sim_fd = openInputFile(input);
+
+ auto ffd = std::make_shared<FileFDEntry>(sim_fd, O_RDONLY, input, false);
+ _fdArray[STDIN_FILENO] = ffd;
+
+ /**
+ * Search through the output/error options and setup the default fd if
+ * match is found; otherwise, open an output file and seek to location.
+ */
+ if ((it = oemap.find(output)) != oemap.end())
+ sim_fd = it->second;
+ else
+ sim_fd = openOutputFile(output);
+
+ ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
+ output, false);
+ _fdArray[STDOUT_FILENO] = ffd;
+
+ if (output == errout)
+ ; /* Reuse the same file descriptor if these match. */
+ else if ((it = oemap.find(errout)) != oemap.end())
+ sim_fd = it->second;
+ else
+ sim_fd = openOutputFile(errout);
+
+ ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
+ errout, false);
+ _fdArray[STDERR_FILENO] = ffd;
+}
+
+void
+FDArray::updateFileOffsets()
+{
+ for (auto& fdp : _fdArray) {
+ /**
+ * It only makes sense to check the offsets if the file descriptor
+ * type is 'File' (which indicates that this file is backed by a
+ * file on the host). If the type is File, then record the offset.
+ */
+ auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp);
+
+ if (!ffd)
+ continue;
+
+ /**
+ * Use lseek with SEEK_CUR with offset 0 to figure out where the
+ * offset currently resides and pass that back to our setter.
+ */
+ int sim_fd = ffd->getSimFD();
+ ffd->setFileOffset(lseek(sim_fd, 0, SEEK_CUR));
+ }
+}
+
+void
+FDArray::restoreFileOffsets()
+{
+ /**
+ * Use this lambda to highlight what we mean to do with the seek.
+ * Notice that this either seeks correctly (sets the file location on the
+ * host) or it fails with a fatal. The error is fatal because it's not
+ * possible to guarantee that the simulation will proceed as it should
+ * have in the same way that it would have proceeded sans checkpoints.
+ */
+ void (*seek)(std::shared_ptr<FileFDEntry>)
+ = [] (std::shared_ptr<FileFDEntry> ffd)
+ {
+ if (lseek(ffd->getSimFD(), ffd->getFileOffset(), SEEK_SET) < 0)
+ fatal("Unable to seek to location in %s", ffd->getFileName());
+ };
+
+ std::map<std::string, int>::iterator it;
+
+ /**
+ * Search through the input options and set fd if match is found;
+ * otherwise, open an input file and seek to location.
+ * Check if user has specified a different input file, and if so, use it
+ * instead of the file specified in the checkpoint. This also resets the
+ * file offset from the checkpointed value
+ */
+ std::shared_ptr<FDEntry> stdin_fde = _fdArray[STDIN_FILENO];
+ auto stdin_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdin_fde);
+
+ if (_input != stdin_ffd->getFileName()) {
+ warn("Using new input file (%s) rather than checkpointed (%s)\n",
+ _input, stdin_ffd->getFileName());
+ stdin_ffd->setFileName(_input);
+ stdin_ffd->setFileOffset(0);
+ }
+
+ if ((it = imap.find(stdin_ffd->getFileName())) != imap.end()) {
+ stdin_ffd->setSimFD(it->second);
+ } else {
+ stdin_ffd->setSimFD(openInputFile(stdin_ffd->getFileName()));
+ seek(stdin_ffd);
+ }
+
+ /**
+ * Search through the output options and set fd if match is found;
+ * otherwise, open an output file and seek to location.
+ * Check if user has specified a different output file, and if so, use it
+ * instead of the file specified in the checkpoint. This also resets the
+ * file offset from the checkpointed value
+ */
+ std::shared_ptr<FDEntry> stdout_fde = _fdArray[STDOUT_FILENO];
+ auto stdout_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdout_fde);
+
+ if (_output != stdout_ffd->getFileName()) {
+ warn("Using new output file (%s) rather than checkpointed (%s)\n",
+ _output, stdout_ffd->getFileName());
+ stdout_ffd->setFileName(_output);
+ stdout_ffd->setFileOffset(0);
+ }
+
+ if ((it = oemap.find(stdout_ffd->getFileName())) != oemap.end()) {
+ stdout_ffd->setSimFD(it->second);
+ } else {
+ stdout_ffd->setSimFD(openOutputFile(stdout_ffd->getFileName()));
+ seek(stdout_ffd);
+ }
+
+ /**
+ * Search through the error options and set fd if match is found;
+ * otherwise, open an error file and seek to location.
+ * Check if user has specified a different error file, and if so, use it
+ * instead of the file specified in the checkpoint. This also resets the
+ * file offset from the checkpointed value
+ */
+ std::shared_ptr<FDEntry> stderr_fde = _fdArray[STDERR_FILENO];
+ auto stderr_ffd = std::dynamic_pointer_cast<FileFDEntry>(stderr_fde);
+
+ if (_errout != stderr_ffd->getFileName()) {
+ warn("Using new error file (%s) rather than checkpointed (%s)\n",
+ _errout, stderr_ffd->getFileName());
+ stderr_ffd->setFileName(_errout);
+ stderr_ffd->setFileOffset(0);
+ }
+
+ if (stdout_ffd->getFileName() == stderr_ffd->getFileName()) {
+ /* Reuse the same sim_fd file descriptor if these match. */
+ stderr_ffd->setSimFD(stdout_ffd->getSimFD());
+ } else if ((it = oemap.find(stderr_ffd->getFileName())) != oemap.end()) {
+ stderr_ffd->setSimFD(it->second);
+ } else {
+ stderr_ffd->setSimFD(openOutputFile(stderr_ffd->getFileName()));
+ seek(stderr_ffd);
+ }
+
+ for (int tgt_fd = 3; tgt_fd < _fdArray.size(); tgt_fd++) {
+ std::shared_ptr<FDEntry> fdp = _fdArray[tgt_fd];
+ if (!fdp)
+ continue;
+
+ /* Need to reconnect pipe ends. */
+ if (auto pfd = std::dynamic_pointer_cast<PipeFDEntry>(fdp)) {
+ /**
+ * Check which end of the pipe we are looking at; we only want
+ * to setup the pipe once so we arbitrarily choose the read
+ * end to be the end that sets up the pipe.
+ */
+ if (pfd->getEndType() == PipeFDEntry::EndType::write)
+ continue;
+
+ /* Setup the pipe or fatal out of the simulation. */
+ int fd_pair[2];
+ if (pipe(fd_pair) < 0)
+ fatal("Unable to create new pipe");
+
+ /**
+ * Reconstruct the ends of the pipe by reassigning the pipe
+ * that we created on the host. This one is the read end.
+ */
+ pfd->setSimFD(fd_pair[0]);
+
+ /**
+ * Grab the write end by referencing the read ends source and
+ * using that tgt_fd to index the array.
+ */
+ int prs = pfd->getPipeReadSource();
+ std::shared_ptr<FDEntry> write_fdp = _fdArray[prs];
+
+ /* Now cast it and make sure that we are still sane. */
+ auto write_pfd = std::dynamic_pointer_cast<PipeFDEntry>(write_fdp);
+
+ /* Hook up the write end back to the right side of the pipe. */
+ write_pfd->setSimFD(fd_pair[1]);
+ }
+
+ /* Need to reassign 'driver'. */
+ if (auto dfd = std::dynamic_pointer_cast<DeviceFDEntry>(fdp)) {
+ /**
+ * Yeah, how does one retain the entire driver state from this
+ * particular set of code? If you figure it out, add some code
+ * here to rectify the issue.
+ */
+ fatal("Unable to restore checkpoints with emulated drivers");
+ }
+
+ /* Need to open files and seek. */
+ if (auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp)) {
+ /**
+ * Assume that this has the mode of an output file so there's no
+ * need to worry about properly recording the mode. If you're
+ * reading this and this happens to be your issue, at least be
+ * happy that you've discovered the issue (and not mad at me).
+ * Onward ho!
+ */
+ int sim_fd = openFile(ffd->getFileName(), ffd->getFlags(), 0664);
+ ffd->setSimFD(sim_fd);
+ seek(ffd);
+ }
+ }
+}
+
+int
+FDArray::allocFD(std::shared_ptr<FDEntry> in)
+{
+ for (int i = 0; i < _fdArray.size(); i++) {
+ std::shared_ptr<FDEntry> fdp = _fdArray[i];
+ if (!fdp) {
+ _fdArray[i] = in;
+ return i;
+ }
+ }
+ fatal("Out of target file descriptors");
+}
+
+int
+FDArray::openFile(std::string const& filename, int flags, mode_t mode) const
+{
+ int sim_fd = open(filename.c_str(), flags, mode);
+ if (sim_fd != -1)
+ return sim_fd;
+ fatal("Unable to open %s with mode %O", filename, mode);
+}
+
+int
+FDArray::openInputFile(std::string const& filename) const
+{
+ return openFile(filename, O_RDONLY, 00);
+}
+
+int
+FDArray::openOutputFile(std::string const& filename) const
+{
+ return openFile(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
+}
+
+std::shared_ptr<FDEntry>
+FDArray::getFDEntry(int tgt_fd)
+{
+ assert(0 <= tgt_fd && tgt_fd < _fdArray.size());
+ return _fdArray[tgt_fd];
+}
+
+int
+FDArray::closeFDEntry(int tgt_fd)
+{
+ if (tgt_fd >= _fdArray.size() || tgt_fd < 0)
+ return -EBADF;
+
+ int sim_fd = -1;
+ auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>(_fdArray[tgt_fd]);
+ if (hbfdp)
+ sim_fd = hbfdp->getSimFD();
+
+ int status = 0;
+ if (sim_fd > 2)
+ status = close(sim_fd);
+
+ if (status == 0)
+ _fdArray[tgt_fd] = nullptr;
+
+ return status;
+}
diff --git a/src/sim/fd_array.hh b/src/sim/fd_array.hh
new file mode 100644
index 000000000..1d57c4654
--- /dev/null
+++ b/src/sim/fd_array.hh
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Brandon Potter
+ */
+
+#ifndef __FD_ARRAY_HH__
+#define __FD_ARRAY_HH__
+
+#include <array>
+#include <memory>
+#include <string>
+
+#include "sim/fd_entry.hh"
+
+class FDArray
+{
+ private:
+ static const int NUM_FDS = 1024;
+
+ public:
+ /**
+ * Initialize the file descriptor array and set the standard file
+ * descriptors to defaults or values passed in with the process
+ * params.
+ * @param input Used to initialize the stdin file descriptor
+ * @param output Used to initialize the stdout file descriptor
+ * @param errout Used to initialize the stderr file descriptor
+ */
+ FDArray(std::string const& input, std::string const& output,
+ std::string const& errout);
+
+ std::string _input;
+ std::string _output;
+ std::string _errout;
+
+ /**
+ * Figure out the file offsets for all currently open files and save them
+ * the offsets during the calls to drain by the owning process.
+ */
+ void updateFileOffsets();
+
+ /**
+ * Restore all offsets for currently open files during the unserialize
+ * phase for the owning process class.
+ */
+ void restoreFileOffsets();
+
+ /**
+ * Treat this object like a normal array in using the subscript operator
+ * to pull entries out of it.
+ * @param tgt_fd Use target file descriptors to index the array.
+ */
+ inline std::shared_ptr<FDEntry>
+ operator[](int tgt_fd)
+ {
+ return getFDEntry(tgt_fd);
+ }
+
+ /**
+ * Step through the file descriptor array and find the first available
+ * entry which is denoted as being free by being a 'nullptr'. That file
+ * descriptor entry is the new target file descriptor entry that we
+ * return as the return parameter.
+ * @param fdp Allocated beforehand and passed into this method;
+ * the fdp is meant to be a generic pointer capable of pointing to
+ * different types of file descriptors. Must cast the pointer to the
+ * correct type before dereferencing to access the needed fields.
+ */
+ int allocFD(std::shared_ptr<FDEntry> fdp);
+
+ /**
+ * Return the size of the _fdArray field
+ */
+ int getSize() const { return _fdArray.size(); }
+
+ /**
+ * Try to close the host file descriptor. If successful, set the
+ * specified file descriptor entry object pointer to nullptr.
+ * Used to "close" the target file descriptor.
+ * @param tgt_fd Use target file descriptors to index the array.
+ */
+ int closeFDEntry(int tgt_fd);
+
+ private:
+ /**
+ * Help clarify our intention when opening files in the init and
+ * restoration code. These are helper functions which are not meant to
+ * be exposed to other objects or files.
+ */
+ int openFile(std::string const& file_name, int flags, mode_t mode) const;
+ int openInputFile(std::string const& file_name) const;
+ int openOutputFile(std::string const& file_name) const;
+
+ /**
+ * Return the file descriptor entry object associated with the index
+ * provided. (The index is protected with bounds checking on the array
+ * size without the use of the array's at operator.)
+ * @param tgt_fd Use target file descriptors to index the array.
+ */
+ std::shared_ptr<FDEntry> getFDEntry(int tgt_fd);
+
+ /**
+ * Hold pointers to the file descriptor entries. The array size is
+ * statically defined by the operating system.
+ */
+ std::array<std::shared_ptr<FDEntry>, NUM_FDS> _fdArray;
+
+ /**
+ * Hold strings which represent the default values which are checked
+ * against to initialize the standard file descriptors. If the string
+ * provided doesn't hit against these maps, then a file is opened on the
+ * host instead of using the host's standard file descriptors.
+ */
+ std::map<std::string, int> imap;
+ std::map<std::string, int> oemap;
+};
+
+#endif // __FD_ARRAY_HH__
diff --git a/src/sim/fd_entry.cc b/src/sim/fd_entry.cc
index 72975a7a6..65bf7a81c 100644
--- a/src/sim/fd_entry.cc
+++ b/src/sim/fd_entry.cc
@@ -1,91 +1,100 @@
/*
- * Copyright (c) 2015 Advanced Micro Devices, Inc.
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
*
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
*
- * Authors: Nathan Binkert
- * Steve Reinhardt
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Brandon Potter
*/
-#include "base/misc.hh"
-#include "fd_entry.hh"
+#include "sim/fd_entry.hh"
-using namespace std;
+#include "sim/serialize.hh"
void
FDEntry::serialize(CheckpointOut &cp) const
{
- SERIALIZE_SCALAR(fd);
- if (fd != -1) {
- SERIALIZE_SCALAR(mode);
- SERIALIZE_SCALAR(flags);
- SERIALIZE_SCALAR(isPipe);
- SERIALIZE_SCALAR(readPipeSource);
- SERIALIZE_SCALAR(fileOffset);
- SERIALIZE_SCALAR(filename);
- }
- if (driver)
- warn("EmulatedDriver objects do not currently support checkpoints");
+ SERIALIZE_SCALAR(_closeOnExec);
}
void
FDEntry::unserialize(CheckpointIn &cp)
{
- UNSERIALIZE_SCALAR(fd);
- if (fd != -1) {
- UNSERIALIZE_SCALAR(mode);
- UNSERIALIZE_SCALAR(flags);
- UNSERIALIZE_SCALAR(isPipe);
- UNSERIALIZE_SCALAR(readPipeSource);
- UNSERIALIZE_SCALAR(fileOffset);
- UNSERIALIZE_SCALAR(filename);
- }
- driver = NULL;
+ UNSERIALIZE_SCALAR(_closeOnExec);
}
-bool
-FDEntry::isFree()
+void
+FileFDEntry::serialize(CheckpointOut &cp) const
+{
+ SERIALIZE_SCALAR(_closeOnExec);
+ SERIALIZE_SCALAR(_flags);
+ SERIALIZE_SCALAR(_fileName);
+ SERIALIZE_SCALAR(_fileOffset);
+}
+
+void
+FileFDEntry::unserialize(CheckpointIn &cp)
+{
+ UNSERIALIZE_SCALAR(_closeOnExec);
+ UNSERIALIZE_SCALAR(_flags);
+ UNSERIALIZE_SCALAR(_fileName);
+ UNSERIALIZE_SCALAR(_fileOffset);
+}
+
+void
+PipeFDEntry::serialize(CheckpointOut &cp) const
+{
+ SERIALIZE_SCALAR(_closeOnExec);
+ SERIALIZE_SCALAR(_flags);
+ //SERIALIZE_SCALAR(_pipeEndType);
+}
+
+void
+PipeFDEntry::unserialize(CheckpointIn &cp)
{
- return (fd == -1 && driver == NULL);
+ UNSERIALIZE_SCALAR(_closeOnExec);
+ UNSERIALIZE_SCALAR(_flags);
+ //UNSERIALIZE_SCALAR(_pipeEndType);
}
void
-FDEntry::set(int sim_fd, const string name, int flags, int mode, bool pipe)
+DeviceFDEntry::serialize(CheckpointOut &cp) const
{
- fd = sim_fd;
- filename = name;
- this->flags = flags;
- this->mode = mode;
- isPipe = pipe;
- fileOffset = 0;
- readPipeSource = 0;
- driver = NULL;
+ SERIALIZE_SCALAR(_closeOnExec);
+ //SERIALIZE_SCALAR(_driver);
+ SERIALIZE_SCALAR(_fileName);
}
void
-FDEntry::reset()
+DeviceFDEntry::unserialize(CheckpointIn &cp)
{
- set(-1, "", 0, 0, false);
+ UNSERIALIZE_SCALAR(_closeOnExec);
+ //UNSERIALIZE_SCALAR(_driver);
+ UNSERIALIZE_SCALAR(_fileName);
}
diff --git a/src/sim/fd_entry.hh b/src/sim/fd_entry.hh
index fd68ba50b..950d1b740 100644
--- a/src/sim/fd_entry.hh
+++ b/src/sim/fd_entry.hh
@@ -1,37 +1,42 @@
/*
- * Copyright (c) 2015 Advanced Micro Devices, Inc.
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
*
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*
- * Authors: Nathan Binkert
- * Steve Reinhardt
+ * Author: Brandon Potter
*/
#ifndef __FD_ENTRY_HH__
#define __FD_ENTRY_HH__
+#include <memory>
#include <ostream>
#include <string>
@@ -40,55 +45,170 @@
class EmulatedDriver;
/**
- * FDEntry is used to manage a single file descriptor mapping and metadata
- * for processes.
- * Note that the fields are all declared publicly since system calls have a
- * habit of only needing to access a single field at a time and accessor
- * methods seem like overkill.
+ * Holds a single file descriptor mapping and that mapping's data for
+ * processes running in syscall emulation mode.
*/
class FDEntry : public Serializable
{
public:
- /**
- * Constructor contains default values
- * The file descriptor is free.
- */
- FDEntry()
- : fd(-1), mode(0), flags(0), isPipe(false), readPipeSource(0),
- fileOffset(0), filename(""), driver(NULL)
+ FDEntry(bool close_on_exec = false)
+ : _closeOnExec(close_on_exec)
+ { }
+
+ virtual std::shared_ptr<FDEntry> clone() const = 0;
+
+ inline bool getCOE() const { return _closeOnExec; }
+
+ inline void setCOE(bool close_on_exec) { _closeOnExec = close_on_exec; }
+
+ virtual void serialize(CheckpointOut &cp) const;
+ virtual void unserialize(CheckpointIn &cp);
+
+ protected:
+ bool _closeOnExec;
+};
+
+/**
+ * Extends the base class to include a host-backed file descriptor field
+ * that records the integer used to represent the file descriptor on the host
+ * and the file's flags.
+ */
+class HBFDEntry: public FDEntry
+{
+ public:
+ HBFDEntry(int flags, int sim_fd, bool close_on_exec = false)
+ : FDEntry(close_on_exec), _flags(flags), _simFD(sim_fd)
{ }
+ inline int getFlags() const { return _flags; }
+ inline int getSimFD() const { return _simFD; }
+
+ inline void setFlags(int flags) { _flags = flags; }
+ inline void setSimFD(int sim_fd) { _simFD = sim_fd; }
+
+ protected:
+ int _flags;
+ int _simFD;
+};
+
+/**
+ * Holds file descriptors for host-backed files; host-backed files are
+ * files which were opened on the physical machine where the simulation
+ * is running (probably the thing on/under your desk). All regular files
+ * are redirected to make it appear that the file descriptor assignment
+ * starts at file descriptor '3' (not including stdin, stdout, stderr) and
+ * then grows upward.
+ */
+class FileFDEntry: public HBFDEntry
+{
+ public:
+ FileFDEntry(int sim_fd, int flags, std::string const& file_name,
+ uint64_t file_offset, bool close_on_exec = false)
+ : HBFDEntry(flags, sim_fd, close_on_exec),
+ _fileName(file_name), _fileOffset(file_offset)
+ { }
+
+ FileFDEntry(FileFDEntry const& reg, bool close_on_exec = false)
+ : HBFDEntry(reg._flags, reg._simFD, close_on_exec),
+ _fileName(reg._fileName), _fileOffset(reg._fileOffset)
+ { }
+
+ inline std::shared_ptr<FDEntry>
+ clone() const override
+ {
+ return std::make_shared<FileFDEntry>(*this);
+ }
+
+ inline std::string getFileName() const { return _fileName; }
+ inline uint64_t getFileOffset() const { return _fileOffset; }
+
+ inline void setFileName(std::string file_name) { _fileName = file_name; }
+ inline void setFileOffset (uint64_t f_off) { _fileOffset = f_off; }
+
+ void serialize(CheckpointOut &cp) const override;
+ void unserialize(CheckpointIn &cp) override;
+
+ private:
+ std::string _fileName;
+ uint64_t _fileOffset;
+};
+
+/**
+ * Holds the metadata needed to maintain the mappings for file descriptors
+ * allocated with the pipe() system calls and its variants.
+ */
+class PipeFDEntry: public HBFDEntry
+{
+ public:
+ enum EndType {
+ read = 0,
+ write = 1
+ };
+
+ PipeFDEntry(int sim_fd, int flags, EndType pipe_end_type,
+ bool close_on_exec = false)
+ : HBFDEntry(flags, sim_fd, close_on_exec), _pipeReadSource(-1),
+ _pipeEndType(pipe_end_type)
+ { }
+
+ PipeFDEntry(PipeFDEntry const& pipe, bool close_on_exec = false)
+ : HBFDEntry(pipe._flags, pipe._simFD, close_on_exec),
+ _pipeReadSource(pipe._pipeReadSource),
+ _pipeEndType(pipe._pipeEndType)
+ { }
+
+ inline std::shared_ptr<FDEntry>
+ clone() const override
+ {
+ return std::make_shared<PipeFDEntry>(*this);
+ }
+
+ inline EndType getEndType() const { return _pipeEndType; }
+ inline int getPipeReadSource() const { return _pipeReadSource; }
+
+ inline void setPipeReadSource(int tgt_fd) { _pipeReadSource = tgt_fd; }
+ inline void setEndType(EndType type) { _pipeEndType = type; }
+
+ void serialize(CheckpointOut &cp) const override;
+ void unserialize(CheckpointIn &cp) override;
+
+ private:
+ int _pipeReadSource;
+ EndType _pipeEndType;
+};
+
+/**
+ * Holds file descriptors needed to simulate devices opened with pseudo
+ * files (commonly with calls to ioctls).
+ */
+class DeviceFDEntry : public FDEntry
+{
+ public:
+ DeviceFDEntry(EmulatedDriver *driver, std::string const& file_name,
+ bool close_on_exec = false)
+ : FDEntry(close_on_exec), _driver(driver), _fileName(file_name)
+ { }
+
+ DeviceFDEntry(DeviceFDEntry const& dev, bool close_on_exec = false)
+ : FDEntry(close_on_exec), _driver(dev._driver),
+ _fileName(dev._fileName)
+ { }
+
+ std::shared_ptr<FDEntry>
+ clone() const override
+ {
+ return std::make_shared<DeviceFDEntry>(*this);
+ }
+
+ inline EmulatedDriver *getDriver() const { return _driver; }
+ inline std::string getFileName() const { return _fileName; }
+
void serialize(CheckpointOut &cp) const override;
void unserialize(CheckpointIn &cp) override;
- /**
- * Check if the target file descriptor is in use.
- * @return value denoting if target file descriptor already used
- */
- bool isFree();
-
- /**
- * Fill in members for this file descriptor entry.
- * @param sim_fd host file descriptor
- * @param name filename string
- * @param flags current flags of the file descriptor
- * @param mode current mode of the file descriptor
- * @param pipe denotes whether the file descriptor belongs to a pipe
- */
- void set(int sim_fd, const std::string name, int flags, int mode,
- bool pipe);
-
- /** Reset members to their default values. */
- void reset();
-
- int fd;
- int mode;
- int flags;
- bool isPipe;
- int readPipeSource;
- uint64_t fileOffset;
- std::string filename;
- EmulatedDriver *driver;
+ private:
+ EmulatedDriver *_driver;
+ std::string _fileName;
};
#endif // __FD_ENTRY_HH__
diff --git a/src/sim/process.cc b/src/sim/process.cc
index 9510fd71d..4c44f4086 100644
--- a/src/sim/process.cc
+++ b/src/sim/process.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Advanced Micro Devices, Inc.
+ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
* Copyright (c) 2012 ARM Limited
* All rights reserved
*
@@ -41,6 +41,7 @@
* Authors: Nathan Binkert
* Steve Reinhardt
* Ali Saidi
+ * Brandon Potter
*/
#include "sim/process.hh"
@@ -63,6 +64,8 @@
#include "mem/se_translating_port_proxy.hh"
#include "params/Process.hh"
#include "sim/emul_driver.hh"
+#include "sim/fd_array.hh"
+#include "sim/fd_entry.hh"
#include "sim/syscall_desc.hh"
#include "sim/system.hh"
@@ -90,27 +93,6 @@
using namespace std;
using namespace TheISA;
-static int
-openFile(const string& filename, int flags, mode_t mode)
-{
- int sim_fd = open(filename.c_str(), flags, mode);
- if (sim_fd != -1)
- return sim_fd;
- fatal("Unable to open %s with mode %O", filename, mode);
-}
-
-static int
-openInputFile(const string &filename)
-{
- return openFile(filename, O_RDONLY, 0);
-}
-
-static int
-openOutputFile(const string &filename)
-{
- return openFile(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
-}
-
Process::Process(ProcessParams * params, ObjectFile * obj_file)
: SimObject(params), system(params->system),
brk_point(0), stack_base(0), stack_size(0), stack_min(0),
@@ -124,58 +106,16 @@ Process::Process(ProcessParams * params, ObjectFile * obj_file)
static_cast<PageTableBase *>(new FuncPageTable(name(), params->pid))),
initVirtMem(system->getSystemPort(), this,
SETranslatingPortProxy::Always),
- fd_array(make_shared<array<FDEntry, NUM_FDS>>()),
- imap {{"", -1},
- {"cin", STDIN_FILENO},
- {"stdin", STDIN_FILENO}},
- oemap{{"", -1},
- {"cout", STDOUT_FILENO},
- {"stdout", STDOUT_FILENO},
- {"cerr", STDERR_FILENO},
- {"stderr", STDERR_FILENO}},
objFile(obj_file),
argv(params->cmd), envp(params->env), cwd(params->cwd),
executable(params->executable),
_uid(params->uid), _euid(params->euid),
_gid(params->gid), _egid(params->egid),
_pid(params->pid), _ppid(params->ppid),
- drivers(params->drivers)
+ drivers(params->drivers),
+ fds(make_shared<FDArray>(params->input, params->output, params->errout))
{
- int sim_fd;
- std::map<string,int>::iterator it;
-
- // Search through the input options and set fd if match is found;
- // otherwise, open an input file and seek to location.
- FDEntry *fde_stdin = getFDEntry(STDIN_FILENO);
- if ((it = imap.find(params->input)) != imap.end())
- sim_fd = it->second;
- else
- sim_fd = openInputFile(params->input);
- fde_stdin->set(sim_fd, params->input, O_RDONLY, -1, false);
-
- // Search through the output/error options and set fd if match is found;
- // otherwise, open an output file and seek to location.
- FDEntry *fde_stdout = getFDEntry(STDOUT_FILENO);
- if ((it = oemap.find(params->output)) != oemap.end())
- sim_fd = it->second;
- else
- sim_fd = openOutputFile(params->output);
- fde_stdout->set(sim_fd, params->output, O_WRONLY | O_CREAT | O_TRUNC,
- 0664, false);
-
- FDEntry *fde_stderr = getFDEntry(STDERR_FILENO);
- if (params->output == params->errout)
- // Reuse the same file descriptor if these match.
- sim_fd = fde_stdout->fd;
- else if ((it = oemap.find(params->errout)) != oemap.end())
- sim_fd = it->second;
- else
- sim_fd = openOutputFile(params->errout);
- fde_stderr->set(sim_fd, params->errout, O_WRONLY | O_CREAT | O_TRUNC,
- 0664, false);
-
mmap_end = 0;
- // other parameters will be initialized when the program is loaded
// load up symbols, if any... these may be used for debugging or
// profiling.
@@ -204,12 +144,6 @@ Process::regStats()
;
}
-void
-Process::inheritFDArray(Process *p)
-{
- fd_array = p->fd_array;
-}
-
ThreadContext *
Process::findFreeContext()
{
@@ -239,57 +173,10 @@ Process::initState()
DrainState
Process::drain()
{
- findFileOffsets();
+ fds->updateFileOffsets();
return DrainState::Drained;
}
-int
-Process::allocFD(int sim_fd, const string& filename, int flags, int mode,
- bool pipe)
-{
- for (int free_fd = 0; free_fd < fd_array->size(); free_fd++) {
- FDEntry *fde = getFDEntry(free_fd);
- if (fde->isFree()) {
- fde->set(sim_fd, filename, flags, mode, pipe);
- return free_fd;
- }
- }
-
- fatal("Out of target file descriptors");
-}
-
-void
-Process::resetFDEntry(int tgt_fd)
-{
- FDEntry *fde = getFDEntry(tgt_fd);
- assert(fde->fd > -1);
-
- fde->reset();
-}
-
-int
-Process::getSimFD(int tgt_fd)
-{
- FDEntry *entry = getFDEntry(tgt_fd);
- return entry ? entry->fd : -1;
-}
-
-FDEntry *
-Process::getFDEntry(int tgt_fd)
-{
- assert(0 <= tgt_fd && tgt_fd < fd_array->size());
- return &(*fd_array)[tgt_fd];
-}
-
-int
-Process::getTgtFD(int sim_fd)
-{
- for (int index = 0; index < fd_array->size(); index++)
- if ((*fd_array)[index].fd == sim_fd)
- return index;
- return -1;
-}
-
void
Process::allocateMem(Addr vaddr, int64_t size, bool clobber)
{
@@ -325,127 +212,6 @@ Process::fixupStackFault(Addr vaddr)
}
void
-Process::fixFileOffsets()
-{
- auto seek = [] (FDEntry *fde)
- {
- if (lseek(fde->fd, fde->fileOffset, SEEK_SET) < 0)
- fatal("Unable to see to location in %s", fde->filename);
- };
-
- std::map<string,int>::iterator it;
-
- // Search through the input options and set fd if match is found;
- // otherwise, open an input file and seek to location.
- FDEntry *fde_stdin = getFDEntry(STDIN_FILENO);
-
- // Check if user has specified a different input file, and if so, use it
- // instead of the file specified in the checkpoint. This also resets the
- // file offset from the checkpointed value
- string new_in = ((ProcessParams*)params())->input;
- if (new_in != fde_stdin->filename) {
- warn("Using new input file (%s) rather than checkpointed (%s)\n",
- new_in, fde_stdin->filename);
- fde_stdin->filename = new_in;
- fde_stdin->fileOffset = 0;
- }
-
- if ((it = imap.find(fde_stdin->filename)) != imap.end()) {
- fde_stdin->fd = it->second;
- } else {
- fde_stdin->fd = openInputFile(fde_stdin->filename);
- seek(fde_stdin);
- }
-
- // Search through the output/error options and set fd if match is found;
- // otherwise, open an output file and seek to location.
- FDEntry *fde_stdout = getFDEntry(STDOUT_FILENO);
-
- // Check if user has specified a different output file, and if so, use it
- // instead of the file specified in the checkpoint. This also resets the
- // file offset from the checkpointed value
- string new_out = ((ProcessParams*)params())->output;
- if (new_out != fde_stdout->filename) {
- warn("Using new output file (%s) rather than checkpointed (%s)\n",
- new_out, fde_stdout->filename);
- fde_stdout->filename = new_out;
- fde_stdout->fileOffset = 0;
- }
-
- if ((it = oemap.find(fde_stdout->filename)) != oemap.end()) {
- fde_stdout->fd = it->second;
- } else {
- fde_stdout->fd = openOutputFile(fde_stdout->filename);
- seek(fde_stdout);
- }
-
- FDEntry *fde_stderr = getFDEntry(STDERR_FILENO);
-
- // Check if user has specified a different error file, and if so, use it
- // instead of the file specified in the checkpoint. This also resets the
- // file offset from the checkpointed value
- string new_err = ((ProcessParams*)params())->errout;
- if (new_err != fde_stderr->filename) {
- warn("Using new error file (%s) rather than checkpointed (%s)\n",
- new_err, fde_stderr->filename);
- fde_stderr->filename = new_err;
- fde_stderr->fileOffset = 0;
- }
-
- if (fde_stdout->filename == fde_stderr->filename) {
- // Reuse the same file descriptor if these match.
- fde_stderr->fd = fde_stdout->fd;
- } else if ((it = oemap.find(fde_stderr->filename)) != oemap.end()) {
- fde_stderr->fd = it->second;
- } else {
- fde_stderr->fd = openOutputFile(fde_stderr->filename);
- seek(fde_stderr);
- }
-
- for (int tgt_fd = 3; tgt_fd < fd_array->size(); tgt_fd++) {
- FDEntry *fde = getFDEntry(tgt_fd);
- if (fde->fd == -1)
- continue;
-
- if (fde->isPipe) {
- if (fde->filename == "PIPE-WRITE")
- continue;
- assert(fde->filename == "PIPE-READ");
-
- int fds[2];
- if (pipe(fds) < 0)
- fatal("Unable to create new pipe");
-
- fde->fd = fds[0];
-
- FDEntry *fde_write = getFDEntry(fde->readPipeSource);
- assert(fde_write->filename == "PIPE-WRITE");
- fde_write->fd = fds[1];
- } else {
- fde->fd = openFile(fde->filename.c_str(), fde->flags, fde->mode);
- seek(fde);
- }
- }
-}
-
-void
-Process::findFileOffsets()
-{
- for (auto& fde : *fd_array) {
- if (fde.fd != -1)
- fde.fileOffset = lseek(fde.fd, 0, SEEK_CUR);
- }
-}
-
-void
-Process::setReadPipeSource(int read_pipe_fd, int source_fd)
-{
- FDEntry *fde = getFDEntry(read_pipe_fd);
- assert(source_fd >= -1);
- fde->readPipeSource = source_fd;
-}
-
-void
Process::serialize(CheckpointOut &cp) const
{
SERIALIZE_SCALAR(brk_point);
@@ -455,9 +221,16 @@ Process::serialize(CheckpointOut &cp) const
SERIALIZE_SCALAR(next_thread_stack_base);
SERIALIZE_SCALAR(mmap_end);
pTable->serialize(cp);
- for (int x = 0; x < fd_array->size(); x++) {
- (*fd_array)[x].serializeSection(cp, csprintf("FDEntry%d", x));
- }
+ /**
+ * Checkpoints for file descriptors currently do not work. Need to
+ * come back and fix them at a later date.
+ */
+
+ warn("Checkpoints for file descriptors currently do not work.");
+#if 0
+ for (int x = 0; x < fds->getSize(); x++)
+ (*fds)[x].serializeSection(cp, csprintf("FDEntry%d", x));
+#endif
}
@@ -471,11 +244,16 @@ Process::unserialize(CheckpointIn &cp)
UNSERIALIZE_SCALAR(next_thread_stack_base);
UNSERIALIZE_SCALAR(mmap_end);
pTable->unserialize(cp);
- for (int x = 0; x < fd_array->size(); x++) {
- FDEntry *fde = getFDEntry(x);
- fde->unserializeSection(cp, csprintf("FDEntry%d", x));
- }
- fixFileOffsets();
+ /**
+ * Checkpoints for file descriptors currently do not work. Need to
+ * come back and fix them at a later date.
+ */
+ warn("Checkpoints for file descriptors currently do not work.");
+#if 0
+ for (int x = 0; x < fds->getSize(); x++)
+ (*fds)[x]->unserializeSection(cp, csprintf("FDEntry%d", x));
+ fds->restoreFileOffsets();
+#endif
// The above returns a bool so that you could do something if you don't
// find the param in the checkpoint if you wanted to, like set a default
// but in this case we'll just stick with the instantiated value if not
diff --git a/src/sim/process.hh b/src/sim/process.hh
index dde131628..2191c3cd0 100644
--- a/src/sim/process.hh
+++ b/src/sim/process.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Advanced Micro Devices, Inc.
+ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
* Copyright (c) 2001-2005 The Regents of The University of Michigan
* All rights reserved.
*
@@ -28,6 +28,7 @@
*
* Authors: Nathan Binkert
* Steve Reinhardt
+ * Brandon Potter
*/
#ifndef __PROCESS_HH__
@@ -35,7 +36,6 @@
#include <inttypes.h>
-#include <array>
#include <map>
#include <string>
#include <vector>
@@ -45,6 +45,7 @@
#include "base/types.hh"
#include "config/the_isa.hh"
#include "mem/se_translating_port_proxy.hh"
+#include "sim/fd_array.hh"
#include "sim/fd_entry.hh"
#include "sim/sim_object.hh"
@@ -115,42 +116,9 @@ class Process : public SimObject
Addr getStartPC();
ObjectFile *getInterpreter();
- // inherit file descriptor map from another process (necessary for clone)
- void inheritFDArray(Process *p);
-
// override of virtual SimObject method: register statistics
void regStats() override;
- // generate new target fd for sim_fd
- int allocFD(int sim_fd, const std::string& filename, int flags, int mode,
- bool pipe);
-
- // disassociate target fd with simulator fd and cleanup subsidiary fields
- void resetFDEntry(int tgt_fd);
-
- // look up simulator fd for given target fd
- int getSimFD(int tgt_fd);
-
- // look up fd entry for a given target fd
- FDEntry *getFDEntry(int tgt_fd);
-
- // look up target fd for given host fd
- // Assumes a 1:1 mapping between target file descriptor and host file
- // descriptor. Given the current API, this must be true given that it's
- // not possible to map multiple target file descriptors to the same host
- // file descriptor
- int getTgtFD(int sim_fd);
-
- // fix all offsets for currently open files and save them
- void fixFileOffsets();
-
- // find all offsets for currently open files and save them
- void findFileOffsets();
-
- // set the source of this read pipe for a checkpoint resume
- void setReadPipeSource(int read_pipe_fd, int source_fd);
-
-
void allocateMem(Addr vaddr, int64_t size, bool clobber = false);
/// Attempt to fix up a fault at vaddr by allocating a page on the stack.
@@ -216,15 +184,6 @@ class Process : public SimObject
SETranslatingPortProxy initVirtMem; // memory proxy for initial image load
- static const int NUM_FDS = 1024;
-
- // File descriptor remapping support.
- std::shared_ptr<std::array<FDEntry, NUM_FDS>> fd_array;
-
- // Standard file descriptor options for initialization and checkpoints.
- std::map<std::string, int> imap;
- std::map<std::string, int> oemap;
-
ObjectFile *objFile;
std::vector<std::string> argv;
std::vector<std::string> envp;
@@ -243,6 +202,8 @@ class Process : public SimObject
// Emulated drivers available to this process
std::vector<EmulatedDriver *> drivers;
+
+ std::shared_ptr<FDArray> fds;
};
#endif // __PROCESS_HH__
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
index d77901fa7..f4bfca6c2 100644
--- a/src/sim/syscall_emul.cc
+++ b/src/sim/syscall_emul.cc
@@ -172,16 +172,7 @@ closeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
int index = 0;
int tgt_fd = p->getSyscallArg(tc, index);
- int sim_fd = p->getSimFD(tgt_fd);
- if (sim_fd < 0)
- return -EBADF;
-
- int status = 0;
- if (sim_fd > 2)
- status = close(sim_fd);
- if (status >= 0)
- p->resetFDEntry(tgt_fd);
- return status;
+ return p->fds->closeFDEntry(tgt_fd);
}
@@ -192,12 +183,13 @@ readFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
int tgt_fd = p->getSyscallArg(tc, index);
Addr bufPtr = p->getSyscallArg(tc, index);
int nbytes = p->getSyscallArg(tc, index);
- BufferArg bufArg(bufPtr, nbytes);
- int sim_fd = p->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
+ if (!hbfdp)
return -EBADF;
+ int sim_fd = hbfdp->getSimFD();
+ BufferArg bufArg(bufPtr, nbytes);
int bytes_read = read(sim_fd, bufArg.bufferPtr(), nbytes);
if (bytes_read > 0)
@@ -213,12 +205,13 @@ writeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
int tgt_fd = p->getSyscallArg(tc, index);
Addr bufPtr = p->getSyscallArg(tc, index);
int nbytes = p->getSyscallArg(tc, index);
- BufferArg bufArg(bufPtr, nbytes);
- int sim_fd = p->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
+ if (!hbfdp)
return -EBADF;
+ int sim_fd = hbfdp->getSimFD();
+ BufferArg bufArg(bufPtr, nbytes);
bufArg.copyIn(tc->getMemProxy());
int bytes_written = write(sim_fd, bufArg.bufferPtr(), nbytes);
@@ -237,9 +230,10 @@ lseekFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
uint64_t offs = p->getSyscallArg(tc, index);
int whence = p->getSyscallArg(tc, index);
- int sim_fd = p->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
+ if (!ffdp)
return -EBADF;
+ int sim_fd = ffdp->getSimFD();
off_t result = lseek(sim_fd, offs, whence);
@@ -257,9 +251,10 @@ _llseekFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Addr result_ptr = p->getSyscallArg(tc, index);
int whence = p->getSyscallArg(tc, index);
- int sim_fd = p->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
+ if (!ffdp)
return -EBADF;
+ int sim_fd = ffdp->getSimFD();
uint64_t offset = (offset_high << 32) | offset_low;
@@ -322,7 +317,7 @@ getcwdFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
strncpy((char *)buf.bufferPtr(), cwd.c_str(), size);
result = cwd.length();
} else {
- if (getcwd((char *)buf.bufferPtr(), size) != NULL) {
+ if (getcwd((char *)buf.bufferPtr(), size)) {
result = strlen((char *)buf.bufferPtr());
} else {
result = -1;
@@ -484,16 +479,16 @@ truncateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
}
SyscallReturn
-ftruncateFunc(SyscallDesc *desc, int num,
- Process *process, ThreadContext *tc)
+ftruncateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
{
int index = 0;
- int tgt_fd = process->getSyscallArg(tc, index);
- off_t length = process->getSyscallArg(tc, index);
+ int tgt_fd = p->getSyscallArg(tc, index);
+ off_t length = p->getSyscallArg(tc, index);
- int sim_fd = process->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
+ if (!ffdp)
return -EBADF;
+ int sim_fd = ffdp->getSimFD();
int result = ftruncate(sim_fd, length);
return (result == -1) ? -errno : result;
@@ -523,16 +518,16 @@ truncate64Func(SyscallDesc *desc, int num,
}
SyscallReturn
-ftruncate64Func(SyscallDesc *desc, int num,
- Process *process, ThreadContext *tc)
+ftruncate64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
{
int index = 0;
- int tgt_fd = process->getSyscallArg(tc, index);
- int64_t length = process->getSyscallArg(tc, index, 64);
+ int tgt_fd = p->getSyscallArg(tc, index);
+ int64_t length = p->getSyscallArg(tc, index, 64);
- int sim_fd = process->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
+ if (!ffdp)
return -EBADF;
+ int sim_fd = ffdp->getSimFD();
#if NO_STAT64
int result = ftruncate(sim_fd, length);
@@ -576,19 +571,20 @@ chownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
}
SyscallReturn
-fchownFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
+fchownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
{
int index = 0;
- int tgt_fd = process->getSyscallArg(tc, index);
+ int tgt_fd = p->getSyscallArg(tc, index);
- int sim_fd = process->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
+ if (!ffdp)
return -EBADF;
+ int sim_fd = ffdp->getSimFD();
/* XXX endianess */
- uint32_t owner = process->getSyscallArg(tc, index);
+ uint32_t owner = p->getSyscallArg(tc, index);
uid_t hostOwner = owner;
- uint32_t group = process->getSyscallArg(tc, index);
+ uint32_t group = p->getSyscallArg(tc, index);
gid_t hostGroup = group;
int result = fchown(sim_fd, hostOwner, hostGroup);
@@ -596,36 +592,47 @@ fchownFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
}
+/**
+ * TODO: there's a bit more involved here since file descriptors created with
+ * dup are supposed to share a file description. So, there is a problem with
+ * maintaining fields like file offset or flags since an update to such a
+ * field won't be reflected in the metadata for the fd entries that we
+ * maintain to hold metadata for checkpoint restoration.
+ */
SyscallReturn
-dupFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
+dupFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
{
int index = 0;
- int tgt_fd = process->getSyscallArg(tc, index);
+ int tgt_fd = p->getSyscallArg(tc, index);
- int sim_fd = process->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto old_hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
+ if (!old_hbfdp)
return -EBADF;
-
- FDEntry *fde = process->getFDEntry(tgt_fd);
+ int sim_fd = old_hbfdp->getSimFD();
int result = dup(sim_fd);
- return (result == -1) ? -errno :
- process->allocFD(result, fde->filename, fde->flags, fde->mode, false);
+ int local_errno = errno;
+
+ std::shared_ptr<FDEntry> new_fdep = old_hbfdp->clone();
+ auto new_hbfdp = std::dynamic_pointer_cast<HBFDEntry>(new_fdep);
+ new_hbfdp->setSimFD(result);
+
+ return (result == -1) ? -local_errno : p->fds->allocFD(new_fdep);
}
SyscallReturn
-fcntlFunc(SyscallDesc *desc, int num, Process *process,
- ThreadContext *tc)
+fcntlFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
{
int index = 0;
- int tgt_fd = process->getSyscallArg(tc, index);
+ int tgt_fd = p->getSyscallArg(tc, index);
- int sim_fd = process->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
+ if (!hbfdp)
return -EBADF;
+ int sim_fd = hbfdp->getSimFD();
- int cmd = process->getSyscallArg(tc, index);
+ int cmd = p->getSyscallArg(tc, index);
switch (cmd) {
case 0: // F_DUPFD
// if we really wanted to support this, we'd need to do it
@@ -659,17 +666,17 @@ fcntlFunc(SyscallDesc *desc, int num, Process *process,
}
SyscallReturn
-fcntl64Func(SyscallDesc *desc, int num, Process *process,
- ThreadContext *tc)
+fcntl64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
{
int index = 0;
- int tgt_fd = process->getSyscallArg(tc, index);
+ int tgt_fd = p->getSyscallArg(tc, index);
- int sim_fd = process->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
+ if (!hbfdp)
return -EBADF;
+ int sim_fd = hbfdp->getSimFD();
- int cmd = process->getSyscallArg(tc, index);
+ int cmd = p->getSyscallArg(tc, index);
switch (cmd) {
case 33: //F_GETLK64
warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd);
@@ -694,21 +701,32 @@ SyscallReturn
pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
- int fds[2], sim_fds[2];
- int pipe_retval = pipe(fds);
+ int sim_fds[2], tgt_fds[2];
- if (pipe_retval < 0) {
- // error
+ int pipe_retval = pipe(sim_fds);
+ if (pipe_retval < 0)
return pipe_retval;
- }
- sim_fds[0] = process->allocFD(fds[0], "PIPE-READ", O_WRONLY, -1, true);
- sim_fds[1] = process->allocFD(fds[1], "PIPE-WRITE", O_RDONLY, -1, true);
+ auto rend = PipeFDEntry::EndType::read;
+ auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
+
+ auto wend = PipeFDEntry::EndType::write;
+ auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
+
+ tgt_fds[0] = process->fds->allocFD(rpfd);
+ tgt_fds[1] = process->fds->allocFD(wpfd);
- process->setReadPipeSource(sim_fds[0], sim_fds[1]);
- // Alpha Linux convention for pipe() is that fd[0] is returned as
- // the return value of the function, and fd[1] is returned in r20.
- tc->setIntReg(SyscallPseudoReturnReg, sim_fds[1]);
+ /**
+ * Now patch the read object to record the target file descriptor chosen
+ * as the write end of the pipe.
+ */
+ rpfd->setPipeReadSource(tgt_fds[1]);
+
+ /**
+ * Alpha Linux convention for pipe() is that fd[0] is returned as
+ * the return value of the function, and fd[1] is returned in r20.
+ */
+ tc->setIntReg(SyscallPseudoReturnReg, tgt_fds[1]);
return sim_fds[0];
}
@@ -828,7 +846,7 @@ cloneFunc(SyscallDesc *desc, int callnum, Process *process,
}
ThreadContext* ctc; // child thread context
- if ( ( ctc = process->findFreeContext() ) != NULL ) {
+ if ((ctc = process->findFreeContext())) {
DPRINTF(SyscallVerbose, " Found unallocated thread context\n");
ctc->clearArchRegs();
@@ -890,21 +908,21 @@ cloneFunc(SyscallDesc *desc, int callnum, Process *process,
}
SyscallReturn
-fallocateFunc(SyscallDesc *desc, int callnum, Process *process,
- ThreadContext *tc)
+fallocateFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
{
#if NO_FALLOCATE
warn("Host OS cannot support calls to fallocate. Ignoring syscall");
#else
int index = 0;
- int tgt_fd = process->getSyscallArg(tc, index);
- int mode = process->getSyscallArg(tc, index);
- off_t offset = process->getSyscallArg(tc, index);
- off_t len = process->getSyscallArg(tc, index);
+ int tgt_fd = p->getSyscallArg(tc, index);
+ int mode = p->getSyscallArg(tc, index);
+ off_t offset = p->getSyscallArg(tc, index);
+ off_t len = p->getSyscallArg(tc, index);
- int sim_fd = process->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
+ if (!ffdp)
return -EBADF;
+ int sim_fd = ffdp->getSimFD();
int result = fallocate(sim_fd, mode, offset, len);
if (result < 0)
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index c75784f79..376ae6f32 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -78,6 +78,7 @@
#include <unistd.h>
#include <cerrno>
+#include <memory>
#include <string>
#include "base/intmath.hh"
@@ -570,31 +571,35 @@ copyOutStatfsBuf(SETranslatingPortProxy &mem, Addr addr,
/// not TTYs to provide repeatable results.
template <class OS>
SyscallReturn
-ioctlFunc(SyscallDesc *desc, int callnum, Process *process,
- ThreadContext *tc)
+ioctlFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
{
int index = 0;
- int tgt_fd = process->getSyscallArg(tc, index);
- unsigned req = process->getSyscallArg(tc, index);
+ int tgt_fd = p->getSyscallArg(tc, index);
+ unsigned req = p->getSyscallArg(tc, index);
DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", tgt_fd, req);
- FDEntry *fde = process->getFDEntry(tgt_fd);
+ if (OS::isTtyReq(req))
+ return -ENOTTY;
- if (fde == NULL) {
- // doesn't map to any simulator fd: not a valid target fd
+ auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*p->fds)[tgt_fd]);
+ if (!dfdp)
return -EBADF;
- }
- if (fde->driver != NULL) {
- return fde->driver->ioctl(process, tc, req);
- }
-
- if (OS::isTtyReq(req)) {
- return -ENOTTY;
- }
+ /**
+ * If the driver is valid, issue the ioctl through it. Otherwise,
+ * there's an implicit assumption that the device is a TTY type and we
+ * return that we do not have a valid TTY.
+ */
+ EmulatedDriver *emul_driver = dfdp->getDriver();
+ if (emul_driver)
+ return emul_driver->ioctl(p, tc, req);
- warn("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n",
+ /**
+ * For lack of a better return code, return ENOTTY. Ideally, we should
+ * return something better here, but at least we issue the warning.
+ */
+ warn("Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
tgt_fd, req, tc->pcState());
return -ENOTTY;
}
@@ -645,7 +650,7 @@ openFunc(SyscallDesc *desc, int callnum, Process *process,
}
EmulatedDriver *drv = process->findDriver(filename);
- if (drv != NULL) {
+ if (drv) {
// the driver's open method will allocate a fd from the
// process if necessary.
return drv->open(process, tc, mode, hostFlags);
@@ -671,7 +676,9 @@ openFunc(SyscallDesc *desc, int callnum, Process *process,
if (fd == -1)
return -local_errno;
- return process->allocFD(fd, path.c_str(), hostFlags, mode, false);
+ std::shared_ptr<FileFDEntry> ffdp =
+ std::make_shared<FileFDEntry>(fd, hostFlags, path.c_str(), false);
+ return process->fds->allocFD(ffdp);
}
/// Target open() handler.
@@ -827,28 +834,22 @@ chmodFunc(SyscallDesc *desc, int callnum, Process *process,
/// Target fchmod() handler.
template <class OS>
SyscallReturn
-fchmodFunc(SyscallDesc *desc, int callnum, Process *process,
- ThreadContext *tc)
+fchmodFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
{
int index = 0;
- int tgt_fd = process->getSyscallArg(tc, index);
- uint32_t mode = process->getSyscallArg(tc, index);
+ int tgt_fd = p->getSyscallArg(tc, index);
+ uint32_t mode = p->getSyscallArg(tc, index);
- int sim_fd = process->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
+ if (!ffdp)
return -EBADF;
+ int sim_fd = ffdp->getSimFD();
- mode_t hostMode = 0;
+ mode_t hostMode = mode;
- // XXX translate mode flags via OS::someting???
- hostMode = mode;
-
- // do the fchmod
int result = fchmod(sim_fd, hostMode);
- if (result < 0)
- return -errno;
- return 0;
+ return (result < 0) ? -errno : 0;
}
/// Target mremap() handler.
@@ -1021,16 +1022,16 @@ fstatat64Func(SyscallDesc *desc, int callnum, Process *process,
/// Target fstat64() handler.
template <class OS>
SyscallReturn
-fstat64Func(SyscallDesc *desc, int callnum, Process *process,
- ThreadContext *tc)
+fstat64Func(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
{
int index = 0;
- int tgt_fd = process->getSyscallArg(tc, index);
- Addr bufPtr = process->getSyscallArg(tc, index);
+ int tgt_fd = p->getSyscallArg(tc, index);
+ Addr bufPtr = p->getSyscallArg(tc, index);
- int sim_fd = process->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
+ if (!ffdp)
return -EBADF;
+ int sim_fd = ffdp->getSimFD();
#if NO_STAT64
struct stat hostBuf;
@@ -1115,18 +1116,18 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process,
/// Target fstat() handler.
template <class OS>
SyscallReturn
-fstatFunc(SyscallDesc *desc, int callnum, Process *process,
- ThreadContext *tc)
+fstatFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
{
int index = 0;
- int tgt_fd = process->getSyscallArg(tc, index);
- Addr bufPtr = process->getSyscallArg(tc, index);
+ int tgt_fd = p->getSyscallArg(tc, index);
+ Addr bufPtr = p->getSyscallArg(tc, index);
DPRINTF_SYSCALL(Verbose, "fstat(%d, ...)\n", tgt_fd);
- int sim_fd = process->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
+ if (!ffdp)
return -EBADF;
+ int sim_fd = ffdp->getSimFD();
struct stat hostBuf;
int result = fstat(sim_fd, &hostBuf);
@@ -1176,16 +1177,16 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process,
/// Target fstatfs() handler.
template <class OS>
SyscallReturn
-fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
- ThreadContext *tc)
+fstatfsFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
{
int index = 0;
- int tgt_fd = process->getSyscallArg(tc, index);
- Addr bufPtr = process->getSyscallArg(tc, index);
+ int tgt_fd = p->getSyscallArg(tc, index);
+ Addr bufPtr = p->getSyscallArg(tc, index);
- int sim_fd = process->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
+ if (!ffdp)
return -EBADF;
+ int sim_fd = ffdp->getSimFD();
struct statfs hostBuf;
int result = fstatfs(sim_fd, &hostBuf);
@@ -1202,29 +1203,29 @@ fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
/// Target writev() handler.
template <class OS>
SyscallReturn
-writevFunc(SyscallDesc *desc, int callnum, Process *process,
- ThreadContext *tc)
+writevFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
{
int index = 0;
- int tgt_fd = process->getSyscallArg(tc, index);
+ int tgt_fd = p->getSyscallArg(tc, index);
- int sim_fd = process->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
+ if (!hbfdp)
return -EBADF;
+ int sim_fd = hbfdp->getSimFD();
- SETranslatingPortProxy &p = tc->getMemProxy();
- uint64_t tiov_base = process->getSyscallArg(tc, index);
- size_t count = process->getSyscallArg(tc, index);
+ SETranslatingPortProxy &prox = tc->getMemProxy();
+ uint64_t tiov_base = p->getSyscallArg(tc, index);
+ size_t count = p->getSyscallArg(tc, index);
struct iovec hiov[count];
for (size_t i = 0; i < count; ++i) {
typename OS::tgt_iovec tiov;
- p.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
- (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
+ prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
+ (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
hiov[i].iov_len = TheISA::gtoh(tiov.iov_len);
hiov[i].iov_base = new char [hiov[i].iov_len];
- p.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
- hiov[i].iov_len);
+ prox.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
+ hiov[i].iov_len);
}
int result = writev(sim_fd, hiov, count);
@@ -1296,19 +1297,19 @@ mmapImpl(SyscallDesc *desc, int num, Process *p, ThreadContext *tc,
int sim_fd = -1;
uint8_t *pmap = nullptr;
if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
- // Check for EmulatedDriver mmap
- FDEntry *fde = p->getFDEntry(tgt_fd);
- if (fde == NULL)
- return -EBADF;
+ std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
- if (fde->driver != NULL) {
- return fde->driver->mmap(p, tc, start, length, prot,
+ auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
+ if (dfdp) {
+ EmulatedDriver *emul_driver = dfdp->getDriver();
+ return emul_driver->mmap(p, tc, start, length, prot,
tgt_flags, tgt_fd, offset);
}
- sim_fd = fde->fd;
- if (sim_fd < 0)
+ auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
+ if (!ffdp)
return -EBADF;
+ sim_fd = ffdp->getSimFD();
pmap = (decltype(pmap))mmap(NULL, length, PROT_READ, MAP_PRIVATE,
sim_fd, offset);
@@ -1393,9 +1394,9 @@ mmapImpl(SyscallDesc *desc, int num, Process *p, ThreadContext *tc,
Addr pc = tc->pcState().pc();
if (pc >= text_start && pc < text_end) {
- FDEntry *fde = p->getFDEntry(tgt_fd);
-
- ObjectFile *lib = createObjectFile(fde->filename);
+ std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
+ auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
+ ObjectFile *lib = createObjectFile(ffdp->getFileName());
if (lib) {
lib->loadAllSymbols(debugSymbolTable,
@@ -1422,9 +1423,10 @@ pwrite64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
int nbytes = p->getSyscallArg(tc, index);
int offset = p->getSyscallArg(tc, index);
- int sim_fd = p->getSimFD(tgt_fd);
- if (sim_fd < 0)
+ auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
+ if (!ffdp)
return -EBADF;
+ int sim_fd = ffdp->getSimFD();
BufferArg bufArg(bufPtr, nbytes);
bufArg.copyIn(tc->getMemProxy());