111856Sbrandon.potter@amd.com/*
211856Sbrandon.potter@amd.com * Copyright (c) 2016 Advanced Micro Devices, Inc.
311856Sbrandon.potter@amd.com * All rights reserved.
411856Sbrandon.potter@amd.com *
511856Sbrandon.potter@amd.com * For use for simulation and test purposes only
611856Sbrandon.potter@amd.com *
711856Sbrandon.potter@amd.com * Redistribution and use in source and binary forms, with or without
811856Sbrandon.potter@amd.com * modification, are permitted provided that the following conditions are met:
911856Sbrandon.potter@amd.com *
1011856Sbrandon.potter@amd.com * 1. Redistributions of source code must retain the above copyright notice,
1111856Sbrandon.potter@amd.com * this list of conditions and the following disclaimer.
1211856Sbrandon.potter@amd.com *
1311856Sbrandon.potter@amd.com * 2. Redistributions in binary form must reproduce the above copyright notice,
1411856Sbrandon.potter@amd.com * this list of conditions and the following disclaimer in the documentation
1511856Sbrandon.potter@amd.com * and/or other materials provided with the distribution.
1611856Sbrandon.potter@amd.com *
1711856Sbrandon.potter@amd.com * 3. Neither the name of the copyright holder nor the names of its
1811856Sbrandon.potter@amd.com * contributors may be used to endorse or promote products derived from this
1911856Sbrandon.potter@amd.com * software without specific prior written permission.
2011856Sbrandon.potter@amd.com *
2111856Sbrandon.potter@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2211856Sbrandon.potter@amd.com * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2311856Sbrandon.potter@amd.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2411856Sbrandon.potter@amd.com * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2511856Sbrandon.potter@amd.com * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2611856Sbrandon.potter@amd.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2711856Sbrandon.potter@amd.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2811856Sbrandon.potter@amd.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2911856Sbrandon.potter@amd.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3011856Sbrandon.potter@amd.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3111856Sbrandon.potter@amd.com * POSSIBILITY OF SUCH DAMAGE.
3211856Sbrandon.potter@amd.com *
3312697Santhony.gutierrez@amd.com * Authors: Brandon Potter
3411856Sbrandon.potter@amd.com */
3511856Sbrandon.potter@amd.com
3611856Sbrandon.potter@amd.com#include "sim/fd_array.hh"
3711856Sbrandon.potter@amd.com
3811856Sbrandon.potter@amd.com#include <fcntl.h>
3911856Sbrandon.potter@amd.com#include <unistd.h>
4011856Sbrandon.potter@amd.com
4111856Sbrandon.potter@amd.com#include <array>
4211856Sbrandon.potter@amd.com#include <memory>
4311856Sbrandon.potter@amd.com#include <string>
4411856Sbrandon.potter@amd.com
4512334Sgabeblack@google.com#include "base/logging.hh"
4613897Ssteve.reinhardt@amd.com#include "base/output.hh"
4711856Sbrandon.potter@amd.com#include "params/Process.hh"
4811856Sbrandon.potter@amd.com#include "sim/fd_entry.hh"
4911856Sbrandon.potter@amd.com
5011856Sbrandon.potter@amd.comFDArray::FDArray(std::string const& input, std::string const& output,
5111856Sbrandon.potter@amd.com                 std::string const& errout)
5213029Sbrandon.potter@amd.com    :  _fdArray(), _input(input), _output(output), _errout(errout),
5313029Sbrandon.potter@amd.com      _imap {{"",       -1},
5413029Sbrandon.potter@amd.com             {"cin",    STDIN_FILENO},
5513029Sbrandon.potter@amd.com             {"stdin",  STDIN_FILENO}},
5613029Sbrandon.potter@amd.com      _oemap{{"",       -1},
5713029Sbrandon.potter@amd.com             {"cout",   STDOUT_FILENO},
5813029Sbrandon.potter@amd.com             {"stdout", STDOUT_FILENO},
5913029Sbrandon.potter@amd.com             {"cerr",   STDERR_FILENO},
6013029Sbrandon.potter@amd.com             {"stderr", STDERR_FILENO}}
6111856Sbrandon.potter@amd.com{
6211856Sbrandon.potter@amd.com    int sim_fd;
6311856Sbrandon.potter@amd.com    std::map<std::string, int>::iterator it;
6411856Sbrandon.potter@amd.com
6511856Sbrandon.potter@amd.com    /**
6611856Sbrandon.potter@amd.com     * Search through the input options and setup the default fd if match is
6711856Sbrandon.potter@amd.com     * found; otherwise, open an input file and seek to location.
6811856Sbrandon.potter@amd.com     */
6913029Sbrandon.potter@amd.com    if ((it = _imap.find(input)) != _imap.end())
7011856Sbrandon.potter@amd.com        sim_fd = it->second;
7111856Sbrandon.potter@amd.com    else
7211856Sbrandon.potter@amd.com        sim_fd = openInputFile(input);
7311856Sbrandon.potter@amd.com
7411856Sbrandon.potter@amd.com    auto ffd = std::make_shared<FileFDEntry>(sim_fd, O_RDONLY, input, false);
7511856Sbrandon.potter@amd.com    _fdArray[STDIN_FILENO] = ffd;
7611856Sbrandon.potter@amd.com
7711856Sbrandon.potter@amd.com    /**
7811856Sbrandon.potter@amd.com     * Search through the output/error options and setup the default fd if
7911856Sbrandon.potter@amd.com     * match is found; otherwise, open an output file and seek to location.
8011856Sbrandon.potter@amd.com     */
8113029Sbrandon.potter@amd.com    if ((it = _oemap.find(output)) != _oemap.end())
8211856Sbrandon.potter@amd.com        sim_fd = it->second;
8311856Sbrandon.potter@amd.com    else
8411856Sbrandon.potter@amd.com        sim_fd = openOutputFile(output);
8511856Sbrandon.potter@amd.com
8611856Sbrandon.potter@amd.com    ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
8711856Sbrandon.potter@amd.com                                        output, false);
8811856Sbrandon.potter@amd.com    _fdArray[STDOUT_FILENO] = ffd;
8911856Sbrandon.potter@amd.com
9011856Sbrandon.potter@amd.com    if (output == errout)
9111856Sbrandon.potter@amd.com        ; /* Reuse the same file descriptor if these match. */
9213029Sbrandon.potter@amd.com    else if ((it = _oemap.find(errout)) != _oemap.end())
9311856Sbrandon.potter@amd.com        sim_fd = it->second;
9411856Sbrandon.potter@amd.com    else
9511856Sbrandon.potter@amd.com        sim_fd = openOutputFile(errout);
9611856Sbrandon.potter@amd.com
9711856Sbrandon.potter@amd.com    ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
9811856Sbrandon.potter@amd.com                                        errout, false);
9911856Sbrandon.potter@amd.com    _fdArray[STDERR_FILENO] = ffd;
10011856Sbrandon.potter@amd.com}
10111856Sbrandon.potter@amd.com
10211856Sbrandon.potter@amd.comvoid
10311856Sbrandon.potter@amd.comFDArray::updateFileOffsets()
10411856Sbrandon.potter@amd.com{
10511856Sbrandon.potter@amd.com    for (auto& fdp : _fdArray) {
10611856Sbrandon.potter@amd.com        /**
10711856Sbrandon.potter@amd.com         * It only makes sense to check the offsets if the file descriptor
10811856Sbrandon.potter@amd.com         * type is 'File' (which indicates that this file is backed by a
10911856Sbrandon.potter@amd.com         * file on the host). If the type is File, then record the offset.
11011856Sbrandon.potter@amd.com         */
11111856Sbrandon.potter@amd.com        auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp);
11211856Sbrandon.potter@amd.com
11311856Sbrandon.potter@amd.com        if (!ffd)
11411856Sbrandon.potter@amd.com            continue;
11511856Sbrandon.potter@amd.com
11611856Sbrandon.potter@amd.com        /**
11711856Sbrandon.potter@amd.com         * Use lseek with SEEK_CUR with offset 0 to figure out where the
11811856Sbrandon.potter@amd.com         * offset currently resides and pass that back to our setter.
11911856Sbrandon.potter@amd.com         */
12011856Sbrandon.potter@amd.com        int sim_fd = ffd->getSimFD();
12111856Sbrandon.potter@amd.com        ffd->setFileOffset(lseek(sim_fd, 0, SEEK_CUR));
12211856Sbrandon.potter@amd.com    }
12311856Sbrandon.potter@amd.com}
12411856Sbrandon.potter@amd.com
12511856Sbrandon.potter@amd.comvoid
12611856Sbrandon.potter@amd.comFDArray::restoreFileOffsets()
12711856Sbrandon.potter@amd.com{
12811856Sbrandon.potter@amd.com    /**
12911856Sbrandon.potter@amd.com     * Use this lambda to highlight what we mean to do with the seek.
13011856Sbrandon.potter@amd.com     * Notice that this either seeks correctly (sets the file location on the
13111856Sbrandon.potter@amd.com     * host) or it fails with a fatal. The error is fatal because it's not
13211856Sbrandon.potter@amd.com     * possible to guarantee that the simulation will proceed as it should
13311856Sbrandon.potter@amd.com     * have in the same way that it would have proceeded sans checkpoints.
13411856Sbrandon.potter@amd.com     */
13512392Sjason@lowepower.com    auto seek = [] (std::shared_ptr<FileFDEntry> ffd)
13611856Sbrandon.potter@amd.com    {
13711856Sbrandon.potter@amd.com        if (lseek(ffd->getSimFD(), ffd->getFileOffset(), SEEK_SET) < 0)
13811856Sbrandon.potter@amd.com            fatal("Unable to seek to location in %s", ffd->getFileName());
13911856Sbrandon.potter@amd.com    };
14011856Sbrandon.potter@amd.com
14111856Sbrandon.potter@amd.com    std::map<std::string, int>::iterator it;
14211856Sbrandon.potter@amd.com
14311856Sbrandon.potter@amd.com    /**
14411856Sbrandon.potter@amd.com     * Search through the input options and set fd if match is found;
14511856Sbrandon.potter@amd.com     * otherwise, open an input file and seek to location.
14611856Sbrandon.potter@amd.com     * Check if user has specified a different input file, and if so, use it
14711856Sbrandon.potter@amd.com     * instead of the file specified in the checkpoint. This also resets the
14811856Sbrandon.potter@amd.com     * file offset from the checkpointed value
14911856Sbrandon.potter@amd.com     */
15011856Sbrandon.potter@amd.com    std::shared_ptr<FDEntry> stdin_fde = _fdArray[STDIN_FILENO];
15111856Sbrandon.potter@amd.com    auto stdin_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdin_fde);
15211856Sbrandon.potter@amd.com
15311856Sbrandon.potter@amd.com    if (_input != stdin_ffd->getFileName()) {
15411856Sbrandon.potter@amd.com        warn("Using new input file (%s) rather than checkpointed (%s)\n",
15511856Sbrandon.potter@amd.com             _input, stdin_ffd->getFileName());
15611856Sbrandon.potter@amd.com        stdin_ffd->setFileName(_input);
15711856Sbrandon.potter@amd.com        stdin_ffd->setFileOffset(0);
15811856Sbrandon.potter@amd.com    }
15911856Sbrandon.potter@amd.com
16013029Sbrandon.potter@amd.com    if ((it = _imap.find(stdin_ffd->getFileName())) != _imap.end()) {
16111856Sbrandon.potter@amd.com        stdin_ffd->setSimFD(it->second);
16211856Sbrandon.potter@amd.com    } else {
16311856Sbrandon.potter@amd.com        stdin_ffd->setSimFD(openInputFile(stdin_ffd->getFileName()));
16411856Sbrandon.potter@amd.com        seek(stdin_ffd);
16511856Sbrandon.potter@amd.com    }
16611856Sbrandon.potter@amd.com
16711856Sbrandon.potter@amd.com    /**
16811856Sbrandon.potter@amd.com     * Search through the output options and set fd if match is found;
16911856Sbrandon.potter@amd.com     * otherwise, open an output file and seek to location.
17011856Sbrandon.potter@amd.com     * Check if user has specified a different output file, and if so, use it
17111856Sbrandon.potter@amd.com     * instead of the file specified in the checkpoint. This also resets the
17211856Sbrandon.potter@amd.com     * file offset from the checkpointed value
17311856Sbrandon.potter@amd.com     */
17411856Sbrandon.potter@amd.com    std::shared_ptr<FDEntry> stdout_fde = _fdArray[STDOUT_FILENO];
17511856Sbrandon.potter@amd.com    auto stdout_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdout_fde);
17611856Sbrandon.potter@amd.com
17711856Sbrandon.potter@amd.com    if (_output != stdout_ffd->getFileName()) {
17811856Sbrandon.potter@amd.com        warn("Using new output file (%s) rather than checkpointed (%s)\n",
17911856Sbrandon.potter@amd.com             _output, stdout_ffd->getFileName());
18011856Sbrandon.potter@amd.com        stdout_ffd->setFileName(_output);
18111856Sbrandon.potter@amd.com        stdout_ffd->setFileOffset(0);
18211856Sbrandon.potter@amd.com    }
18311856Sbrandon.potter@amd.com
18413029Sbrandon.potter@amd.com    if ((it = _oemap.find(stdout_ffd->getFileName())) != _oemap.end()) {
18511856Sbrandon.potter@amd.com        stdout_ffd->setSimFD(it->second);
18611856Sbrandon.potter@amd.com    } else {
18711856Sbrandon.potter@amd.com        stdout_ffd->setSimFD(openOutputFile(stdout_ffd->getFileName()));
18811856Sbrandon.potter@amd.com        seek(stdout_ffd);
18911856Sbrandon.potter@amd.com    }
19011856Sbrandon.potter@amd.com
19111856Sbrandon.potter@amd.com    /**
19211856Sbrandon.potter@amd.com     * Search through the error options and set fd if match is found;
19311856Sbrandon.potter@amd.com     * otherwise, open an error file and seek to location.
19411856Sbrandon.potter@amd.com     * Check if user has specified a different error file, and if so, use it
19511856Sbrandon.potter@amd.com     * instead of the file specified in the checkpoint. This also resets the
19611856Sbrandon.potter@amd.com     * file offset from the checkpointed value
19711856Sbrandon.potter@amd.com     */
19811856Sbrandon.potter@amd.com    std::shared_ptr<FDEntry> stderr_fde = _fdArray[STDERR_FILENO];
19911856Sbrandon.potter@amd.com    auto stderr_ffd = std::dynamic_pointer_cast<FileFDEntry>(stderr_fde);
20011856Sbrandon.potter@amd.com
20111856Sbrandon.potter@amd.com    if (_errout != stderr_ffd->getFileName()) {
20211856Sbrandon.potter@amd.com        warn("Using new error file (%s) rather than checkpointed (%s)\n",
20311856Sbrandon.potter@amd.com             _errout, stderr_ffd->getFileName());
20411856Sbrandon.potter@amd.com        stderr_ffd->setFileName(_errout);
20511856Sbrandon.potter@amd.com        stderr_ffd->setFileOffset(0);
20611856Sbrandon.potter@amd.com    }
20711856Sbrandon.potter@amd.com
20811856Sbrandon.potter@amd.com    if (stdout_ffd->getFileName() == stderr_ffd->getFileName()) {
20911856Sbrandon.potter@amd.com        /* Reuse the same sim_fd file descriptor if these match. */
21011856Sbrandon.potter@amd.com        stderr_ffd->setSimFD(stdout_ffd->getSimFD());
21113029Sbrandon.potter@amd.com    } else if ((it = _oemap.find(stderr_ffd->getFileName())) != _oemap.end()) {
21211856Sbrandon.potter@amd.com        stderr_ffd->setSimFD(it->second);
21311856Sbrandon.potter@amd.com    } else {
21411856Sbrandon.potter@amd.com        stderr_ffd->setSimFD(openOutputFile(stderr_ffd->getFileName()));
21511856Sbrandon.potter@amd.com        seek(stderr_ffd);
21611856Sbrandon.potter@amd.com    }
21711856Sbrandon.potter@amd.com
21811856Sbrandon.potter@amd.com    for (int tgt_fd = 3; tgt_fd < _fdArray.size(); tgt_fd++) {
21911856Sbrandon.potter@amd.com        std::shared_ptr<FDEntry> fdp = _fdArray[tgt_fd];
22011856Sbrandon.potter@amd.com        if (!fdp)
22111856Sbrandon.potter@amd.com            continue;
22211856Sbrandon.potter@amd.com
22311856Sbrandon.potter@amd.com        /* Need to reconnect pipe ends. */
22411856Sbrandon.potter@amd.com        if (auto pfd = std::dynamic_pointer_cast<PipeFDEntry>(fdp)) {
22511856Sbrandon.potter@amd.com            /**
22611856Sbrandon.potter@amd.com             * Check which end of the pipe we are looking at; we only want
22711856Sbrandon.potter@amd.com             * to setup the pipe once so we arbitrarily choose the read
22811856Sbrandon.potter@amd.com             * end to be the end that sets up the pipe.
22911856Sbrandon.potter@amd.com             */
23011856Sbrandon.potter@amd.com            if (pfd->getEndType() == PipeFDEntry::EndType::write)
23111856Sbrandon.potter@amd.com                continue;
23211856Sbrandon.potter@amd.com
23311856Sbrandon.potter@amd.com            /* Setup the pipe or fatal out of the simulation. */
23411856Sbrandon.potter@amd.com            int fd_pair[2];
23511856Sbrandon.potter@amd.com            if (pipe(fd_pair) < 0)
23611856Sbrandon.potter@amd.com                fatal("Unable to create new pipe");
23711856Sbrandon.potter@amd.com
23811856Sbrandon.potter@amd.com            /**
23911856Sbrandon.potter@amd.com             * Reconstruct the ends of the pipe by reassigning the pipe
24011856Sbrandon.potter@amd.com             * that we created on the host. This one is the read end.
24111856Sbrandon.potter@amd.com             */
24211856Sbrandon.potter@amd.com            pfd->setSimFD(fd_pair[0]);
24311856Sbrandon.potter@amd.com
24411856Sbrandon.potter@amd.com            /**
24511856Sbrandon.potter@amd.com             * Grab the write end by referencing the read ends source and
24611856Sbrandon.potter@amd.com             * using that tgt_fd to index the array.
24711856Sbrandon.potter@amd.com             */
24811856Sbrandon.potter@amd.com            int prs = pfd->getPipeReadSource();
24911856Sbrandon.potter@amd.com            std::shared_ptr<FDEntry> write_fdp = _fdArray[prs];
25011856Sbrandon.potter@amd.com
25111856Sbrandon.potter@amd.com            /* Now cast it and make sure that we are still sane. */
25211856Sbrandon.potter@amd.com            auto write_pfd = std::dynamic_pointer_cast<PipeFDEntry>(write_fdp);
25311856Sbrandon.potter@amd.com
25411856Sbrandon.potter@amd.com            /* Hook up the write end back to the right side of the pipe. */
25511856Sbrandon.potter@amd.com            write_pfd->setSimFD(fd_pair[1]);
25611856Sbrandon.potter@amd.com        }
25711856Sbrandon.potter@amd.com
25811856Sbrandon.potter@amd.com        /* Need to reassign 'driver'. */
25911856Sbrandon.potter@amd.com        if (auto dfd = std::dynamic_pointer_cast<DeviceFDEntry>(fdp)) {
26011856Sbrandon.potter@amd.com            /**
26111856Sbrandon.potter@amd.com             * Yeah, how does one retain the entire driver state from this
26211856Sbrandon.potter@amd.com             * particular set of code? If you figure it out, add some code
26311856Sbrandon.potter@amd.com             * here to rectify the issue.
26411856Sbrandon.potter@amd.com             */
26511856Sbrandon.potter@amd.com            fatal("Unable to restore checkpoints with emulated drivers");
26611856Sbrandon.potter@amd.com        }
26711856Sbrandon.potter@amd.com
26811856Sbrandon.potter@amd.com        /* Need to open files and seek. */
26911856Sbrandon.potter@amd.com        if (auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp)) {
27011856Sbrandon.potter@amd.com            /**
27111856Sbrandon.potter@amd.com             * Assume that this has the mode of an output file so there's no
27211856Sbrandon.potter@amd.com             * need to worry about properly recording the mode. If you're
27311856Sbrandon.potter@amd.com             * reading this and this happens to be your issue, at least be
27411856Sbrandon.potter@amd.com             * happy that you've discovered the issue (and not mad at me).
27511856Sbrandon.potter@amd.com             * Onward ho!
27611856Sbrandon.potter@amd.com             */
27711856Sbrandon.potter@amd.com            int sim_fd = openFile(ffd->getFileName(), ffd->getFlags(), 0664);
27811856Sbrandon.potter@amd.com            ffd->setSimFD(sim_fd);
27911856Sbrandon.potter@amd.com            seek(ffd);
28011856Sbrandon.potter@amd.com        }
28111856Sbrandon.potter@amd.com    }
28211856Sbrandon.potter@amd.com}
28311856Sbrandon.potter@amd.com
28411856Sbrandon.potter@amd.comint
28511856Sbrandon.potter@amd.comFDArray::allocFD(std::shared_ptr<FDEntry> in)
28611856Sbrandon.potter@amd.com{
28711856Sbrandon.potter@amd.com    for (int i = 0; i < _fdArray.size(); i++) {
28811856Sbrandon.potter@amd.com        std::shared_ptr<FDEntry> fdp = _fdArray[i];
28911856Sbrandon.potter@amd.com        if (!fdp) {
29011856Sbrandon.potter@amd.com            _fdArray[i] = in;
29111856Sbrandon.potter@amd.com            return i;
29211856Sbrandon.potter@amd.com        }
29311856Sbrandon.potter@amd.com    }
29411856Sbrandon.potter@amd.com    fatal("Out of target file descriptors");
29511856Sbrandon.potter@amd.com}
29611856Sbrandon.potter@amd.com
29711856Sbrandon.potter@amd.comint
29811856Sbrandon.potter@amd.comFDArray::openFile(std::string const& filename, int flags, mode_t mode) const
29911856Sbrandon.potter@amd.com{
30011856Sbrandon.potter@amd.com    int sim_fd = open(filename.c_str(), flags, mode);
30111856Sbrandon.potter@amd.com    if (sim_fd != -1)
30211856Sbrandon.potter@amd.com        return sim_fd;
30311856Sbrandon.potter@amd.com    fatal("Unable to open %s with mode %O", filename, mode);
30411856Sbrandon.potter@amd.com}
30511856Sbrandon.potter@amd.com
30611856Sbrandon.potter@amd.comint
30711856Sbrandon.potter@amd.comFDArray::openInputFile(std::string const& filename) const
30811856Sbrandon.potter@amd.com{
30911856Sbrandon.potter@amd.com    return openFile(filename, O_RDONLY, 00);
31011856Sbrandon.potter@amd.com}
31111856Sbrandon.potter@amd.com
31211856Sbrandon.potter@amd.comint
31311856Sbrandon.potter@amd.comFDArray::openOutputFile(std::string const& filename) const
31411856Sbrandon.potter@amd.com{
31513897Ssteve.reinhardt@amd.com    return openFile(simout.resolve(filename),
31613897Ssteve.reinhardt@amd.com                    O_WRONLY | O_CREAT | O_TRUNC, 0664);
31711856Sbrandon.potter@amd.com}
31811856Sbrandon.potter@amd.com
31911856Sbrandon.potter@amd.comstd::shared_ptr<FDEntry>
32011856Sbrandon.potter@amd.comFDArray::getFDEntry(int tgt_fd)
32111856Sbrandon.potter@amd.com{
32211856Sbrandon.potter@amd.com    assert(0 <= tgt_fd && tgt_fd < _fdArray.size());
32311856Sbrandon.potter@amd.com    return _fdArray[tgt_fd];
32411856Sbrandon.potter@amd.com}
32511856Sbrandon.potter@amd.com
32611886Sbrandon.potter@amd.comvoid
32711886Sbrandon.potter@amd.comFDArray::setFDEntry(int tgt_fd, std::shared_ptr<FDEntry> fdep)
32811886Sbrandon.potter@amd.com{
32911886Sbrandon.potter@amd.com    assert(0 <= tgt_fd && tgt_fd < _fdArray.size());
33011886Sbrandon.potter@amd.com    _fdArray[tgt_fd] = fdep;
33111886Sbrandon.potter@amd.com}
33211886Sbrandon.potter@amd.com
33311856Sbrandon.potter@amd.comint
33411856Sbrandon.potter@amd.comFDArray::closeFDEntry(int tgt_fd)
33511856Sbrandon.potter@amd.com{
33611856Sbrandon.potter@amd.com    if (tgt_fd >= _fdArray.size() || tgt_fd < 0)
33711856Sbrandon.potter@amd.com        return -EBADF;
33811856Sbrandon.potter@amd.com
33911856Sbrandon.potter@amd.com    int sim_fd = -1;
34011856Sbrandon.potter@amd.com    auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>(_fdArray[tgt_fd]);
34111856Sbrandon.potter@amd.com    if (hbfdp)
34211856Sbrandon.potter@amd.com        sim_fd = hbfdp->getSimFD();
34311856Sbrandon.potter@amd.com
34411856Sbrandon.potter@amd.com    int status = 0;
34511856Sbrandon.potter@amd.com    if (sim_fd > 2)
34611856Sbrandon.potter@amd.com        status = close(sim_fd);
34711856Sbrandon.potter@amd.com
34811856Sbrandon.potter@amd.com    if (status == 0)
34911856Sbrandon.potter@amd.com        _fdArray[tgt_fd] = nullptr;
35011856Sbrandon.potter@amd.com
35111856Sbrandon.potter@amd.com    return status;
35211856Sbrandon.potter@amd.com}
353