#include <unistd.h>
#include <fcntl.h>
-
#include <string>
#include "arch/remote_gdb.hh"
#include "mem/page_table.hh"
#include "mem/physical.hh"
#include "mem/translating_port.hh"
+#include "params/Process.hh"
#include "params/LiveProcess.hh"
+#include "sim/debug.hh"
#include "sim/process.hh"
#include "sim/process_impl.hh"
#include "sim/stats.hh"
#include "arch/sparc/solaris/process.hh"
#elif THE_ISA == MIPS_ISA
#include "arch/mips/linux/process.hh"
+#elif THE_ISA == ARM_ISA
+#include "arch/arm/linux/process.hh"
#elif THE_ISA == X86_ISA
#include "arch/x86/linux/process.hh"
#else
// current number of allocated processes
int num_processes = 0;
-Process::Process(const string &nm,
- System *_system,
- int stdin_fd, // initial I/O descriptors
- int stdout_fd,
- int stderr_fd)
- : SimObject(nm), system(_system)
+Process::Process(ProcessParams * params)
+ : SimObject(params), system(params->system), checkpointRestored(false),
+ max_stack_size(params->max_stack_size)
{
+ string in = params->input;
+ string out = params->output;
+
+ // initialize file descriptors to default: same as simulator
+ int stdin_fd, stdout_fd, stderr_fd;
+
+ if (in == "stdin" || in == "cin")
+ stdin_fd = STDIN_FILENO;
+ else if (in == "None")
+ stdin_fd = -1;
+ else
+ stdin_fd = Process::openInputFile(in);
+
+ if (out == "stdout" || out == "cout")
+ stdout_fd = STDOUT_FILENO;
+ else if (out == "stderr" || out == "cerr")
+ stdout_fd = STDERR_FILENO;
+ else if (out == "None")
+ stdout_fd = -1;
+ else
+ stdout_fd = Process::openOutputFile(out);
+
+ stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO;
+
+ M5_pid = system->allocatePID();
// initialize first 3 fds (stdin, stdout, stderr)
- fd_map[STDIN_FILENO] = stdin_fd;
- fd_map[STDOUT_FILENO] = stdout_fd;
- fd_map[STDERR_FILENO] = stderr_fd;
+ Process::FdMap *fdo = &fd_map[STDIN_FILENO];
+ fdo->fd = stdin_fd;
+ fdo->filename = in;
+ fdo->flags = O_RDONLY;
+ fdo->mode = -1;
+ fdo->fileOffset = 0;
+
+ fdo = &fd_map[STDOUT_FILENO];
+ fdo->fd = stdout_fd;
+ fdo->filename = out;
+ fdo->flags = O_WRONLY | O_CREAT | O_TRUNC;
+ fdo->mode = 0774;
+ fdo->fileOffset = 0;
+
+ fdo = &fd_map[STDERR_FILENO];
+ fdo->fd = stderr_fd;
+ fdo->filename = "STDERR";
+ fdo->flags = O_WRONLY;
+ fdo->mode = -1;
+ fdo->fileOffset = 0;
+
// mark remaining fds as free
for (int i = 3; i <= MAX_FD; ++i) {
- fd_map[i] = -1;
+ Process::FdMap *fdo = &fd_map[i];
+ fdo->fd = -1;
}
mmap_start = mmap_end = 0;
nxm_start = nxm_end = 0;
- pTable = new PageTable(system);
+ pTable = new PageTable(this);
// other parameters will be initialized when the program is loaded
}
int myIndex = threadContexts.size();
threadContexts.push_back(tc);
-// RemoteGDB *rgdb = new RemoteGDB(system, tc);
-// GDBListener *gdbl = new GDBListener(rgdb, 7000 + myIndex);
-// gdbl->listen();
- //gdbl->accept();
+ int port = getRemoteGDBPort();
+ if (port) {
+ RemoteGDB *rgdb = new RemoteGDB(system, tc);
+ GDBListener *gdbl = new GDBListener(rgdb, port + myIndex);
+ gdbl->listen();
-// remoteGDB.push_back(rgdb);
+ remoteGDB.push_back(rgdb);
+ }
// return CPU number to caller
return myIndex;
if (tgt_fd < 0 || tgt_fd > MAX_FD)
panic("Process::dup_fd tried to dup past MAX_FD (%d)", tgt_fd);
- fd_map[tgt_fd] = sim_fd;
+ Process::FdMap *fdo = &fd_map[tgt_fd];
+ fdo->fd = sim_fd;
}
// generate new target fd for sim_fd
int
-Process::alloc_fd(int sim_fd)
+Process::alloc_fd(int sim_fd, string filename, int flags, int mode, bool pipe)
{
// in case open() returns an error, don't allocate a new fd
if (sim_fd == -1)
return -1;
// find first free target fd
- for (int free_fd = 0; free_fd < MAX_FD; ++free_fd) {
- if (fd_map[free_fd] == -1) {
- fd_map[free_fd] = sim_fd;
+ for (int free_fd = 0; free_fd <= MAX_FD; ++free_fd) {
+ Process::FdMap *fdo = &fd_map[free_fd];
+ if (fdo->fd == -1) {
+ fdo->fd = sim_fd;
+ fdo->filename = filename;
+ fdo->mode = mode;
+ fdo->fileOffset = 0;
+ fdo->flags = flags;
+ fdo->isPipe = pipe;
+ fdo->readPipeSource = 0;
return free_fd;
}
}
void
Process::free_fd(int tgt_fd)
{
- if (fd_map[tgt_fd] == -1)
+ Process::FdMap *fdo = &fd_map[tgt_fd];
+ if (fdo->fd == -1)
warn("Process::free_fd: request to free unused fd %d", tgt_fd);
- fd_map[tgt_fd] = -1;
+ fdo->fd = -1;
+ fdo->filename = "NULL";
+ fdo->mode = 0;
+ fdo->fileOffset = 0;
+ fdo->flags = 0;
+ fdo->isPipe = false;
+ fdo->readPipeSource = 0;
}
if (tgt_fd > MAX_FD)
return -1;
- return fd_map[tgt_fd];
+ return fd_map[tgt_fd].fd;
}
+Process::FdMap *
+Process::sim_fd_obj(int tgt_fd)
+{
+ if (tgt_fd > MAX_FD)
+ panic("sim_fd_obj called in fd out of range.");
+
+ return &fd_map[tgt_fd];
+}
bool
Process::checkAndAllocNextPage(Addr vaddr)
{
// We've accessed the next page of the stack, so extend the stack
// to cover it.
- if(vaddr < stack_min && vaddr >= stack_min - TheISA::PageBytes)
- {
- stack_min -= TheISA::PageBytes;
- if(stack_base - stack_min > 8*1024*1024)
- fatal("Over max stack size for one thread\n");
- pTable->allocate(stack_min, TheISA::PageBytes);
- warn("Increasing stack size by one page.");
+ if (vaddr < stack_min && vaddr >= stack_base - max_stack_size) {
+ while (vaddr < stack_min) {
+ stack_min -= TheISA::PageBytes;
+ if(stack_base - stack_min > max_stack_size)
+ fatal("Maximum stack size exceeded\n");
+ if(stack_base - stack_min > 8*1024*1024)
+ fatal("Over max stack size for one thread\n");
+ pTable->allocate(stack_min, TheISA::PageBytes);
+ warn("Increasing stack size by one page.");
+ };
return true;
}
return false;
}
+ // find all offsets for currently open files and save them
+void
+Process::fix_file_offsets() {
+ Process::FdMap *fdo_stdin = &fd_map[STDIN_FILENO];
+ Process::FdMap *fdo_stdout = &fd_map[STDOUT_FILENO];
+ Process::FdMap *fdo_stderr = &fd_map[STDERR_FILENO];
+ string in = fdo_stdin->filename;
+ string out = fdo_stdout->filename;
+
+ // initialize file descriptors to default: same as simulator
+ int stdin_fd, stdout_fd, stderr_fd;
+
+ if (in == "stdin" || in == "cin")
+ stdin_fd = STDIN_FILENO;
+ else if (in == "None")
+ stdin_fd = -1;
+ else{
+ //OPEN standard in and seek to the right location
+ stdin_fd = Process::openInputFile(in);
+ if (lseek(stdin_fd, fdo_stdin->fileOffset, SEEK_SET) < 0)
+ panic("Unable to seek to correct location in file: %s", in);
+ }
+
+ if (out == "stdout" || out == "cout")
+ stdout_fd = STDOUT_FILENO;
+ else if (out == "stderr" || out == "cerr")
+ stdout_fd = STDERR_FILENO;
+ else if (out == "None")
+ stdout_fd = -1;
+ else{
+ stdout_fd = Process::openOutputFile(out);
+ if (lseek(stdin_fd, fdo_stdout->fileOffset, SEEK_SET) < 0)
+ panic("Unable to seek to correct in file: %s", out);
+ }
+
+ stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO;
+
+ fdo_stdin->fd = stdin_fd;
+ fdo_stdout->fd = stdout_fd;
+ fdo_stderr->fd = stderr_fd;
+
+
+ for (int free_fd = 3; free_fd <= MAX_FD; ++free_fd) {
+ Process::FdMap *fdo = &fd_map[free_fd];
+ if (fdo->fd != -1) {
+ if (fdo->isPipe){
+ if (fdo->filename == "PIPE-WRITE")
+ continue;
+ else {
+ assert (fdo->filename == "PIPE-READ");
+ //create a new pipe
+ int fds[2];
+ int pipe_retval = pipe(fds);
+
+ if (pipe_retval < 0) {
+ // error
+ panic("Unable to create new pipe.");
+ }
+ fdo->fd = fds[0]; //set read pipe
+ Process::FdMap *fdo_write = &fd_map[fdo->readPipeSource];
+ if (fdo_write->filename != "PIPE-WRITE")
+ panic ("Couldn't find write end of the pipe");
+
+ fdo_write->fd = fds[1];//set write pipe
+ }
+ } else {
+ //Open file
+ int fd = open(fdo->filename.c_str(), fdo->flags, fdo->mode);
+
+ if (fd == -1)
+ panic("Unable to open file: %s", fdo->filename);
+ fdo->fd = fd;
+
+ //Seek to correct location before checkpoint
+ if (lseek(fd,fdo->fileOffset, SEEK_SET) < 0)
+ panic("Unable to seek to correct location in file: %s", fdo->filename);
+ }
+ }
+ }
+}
+void
+Process::find_file_offsets(){
+ for (int free_fd = 0; free_fd <= MAX_FD; ++free_fd) {
+ Process::FdMap *fdo = &fd_map[free_fd];
+ if (fdo->fd != -1) {
+ fdo->fileOffset = lseek(fdo->fd, 0, SEEK_CUR);
+ } else {
+ fdo->filename = "NULL";
+ fdo->fileOffset = 0;
+ }
+ }
+}
+
+void
+Process::setReadPipeSource(int read_pipe_fd, int source_fd){
+ Process::FdMap *fdo = &fd_map[read_pipe_fd];
+ fdo->readPipeSource = source_fd;
+}
+
+void
+Process::FdMap::serialize(std::ostream &os)
+{
+ SERIALIZE_SCALAR(fd);
+ SERIALIZE_SCALAR(isPipe);
+ SERIALIZE_SCALAR(filename);
+ SERIALIZE_SCALAR(flags);
+ SERIALIZE_SCALAR(readPipeSource);
+ SERIALIZE_SCALAR(fileOffset);
+}
+
+void
+Process::FdMap::unserialize(Checkpoint *cp, const std::string §ion)
+{
+ UNSERIALIZE_SCALAR(fd);
+ UNSERIALIZE_SCALAR(isPipe);
+ UNSERIALIZE_SCALAR(filename);
+ UNSERIALIZE_SCALAR(flags);
+ UNSERIALIZE_SCALAR(readPipeSource);
+ UNSERIALIZE_SCALAR(fileOffset);
+}
+
void
Process::serialize(std::ostream &os)
{
SERIALIZE_SCALAR(mmap_end);
SERIALIZE_SCALAR(nxm_start);
SERIALIZE_SCALAR(nxm_end);
- SERIALIZE_ARRAY(fd_map, MAX_FD);
-
+ find_file_offsets();
pTable->serialize(os);
+ for (int x = 0; x <= MAX_FD; x++) {
+ nameOut(os, csprintf("%s.FdMap%d", name(), x));
+ fd_map[x].serialize(os);
+ }
+
}
void
UNSERIALIZE_SCALAR(mmap_end);
UNSERIALIZE_SCALAR(nxm_start);
UNSERIALIZE_SCALAR(nxm_end);
- UNSERIALIZE_ARRAY(fd_map, MAX_FD);
-
pTable->unserialize(cp, section);
+ for (int x = 0; x <= MAX_FD; x++) {
+ fd_map[x].unserialize(cp, csprintf("%s.FdMap%d", section, x));
+ }
+ fix_file_offsets();
+
+ checkpointRestored = true;
+
}
////////////////////////////////////////////////////////////////////////
-LiveProcess::LiveProcess(const string &nm, ObjectFile *_objFile,
- System *_system,
- int stdin_fd, int stdout_fd, int stderr_fd,
- vector<string> &_argv, vector<string> &_envp,
- const string &_cwd,
- uint64_t _uid, uint64_t _euid,
- uint64_t _gid, uint64_t _egid,
- uint64_t _pid, uint64_t _ppid)
- : Process(nm, _system, stdin_fd, stdout_fd, stderr_fd),
- objFile(_objFile), argv(_argv), envp(_envp), cwd(_cwd)
+LiveProcess::LiveProcess(LiveProcessParams * params, ObjectFile *_objFile)
+ : Process(params), objFile(_objFile),
+ argv(params->cmd), envp(params->env), cwd(params->cwd)
{
- __uid = _uid;
- __euid = _euid;
- __gid = _gid;
- __egid = _egid;
- __pid = _pid;
- __ppid = _ppid;
+ __uid = params->uid;
+ __euid = params->euid;
+ __gid = params->gid;
+ __egid = params->egid;
+ __pid = params->pid;
+ __ppid = params->ppid;
- prog_fname = argv[0];
+ prog_fname = params->cmd[0];
// load up symbols, if any... these may be used for debugging or
// profiling.
}
LiveProcess *
-LiveProcess::create(const std::string &nm, System *system, int stdin_fd,
- int stdout_fd, int stderr_fd, std::string executable,
- std::vector<std::string> &argv,
- std::vector<std::string> &envp,
- const std::string &cwd,
- uint64_t _uid, uint64_t _euid,
- uint64_t _gid, uint64_t _egid,
- uint64_t _pid, uint64_t _ppid)
+LiveProcess::create(LiveProcessParams * params)
{
LiveProcess *process = NULL;
+ string executable =
+ params->executable == "" ? params->cmd[0] : params->executable;
ObjectFile *objFile = createObjectFile(executable);
if (objFile == NULL) {
fatal("Can't load object file %s", executable);
if (objFile->isDynamic())
fatal("Object file is a dynamic executable however only static "
- "executables are supported!\n Please recompile your "
+ "executables are supported!\n Please recompile your "
"executable as a static binary and try again.\n");
#if THE_ISA == ALPHA_ISA
+ if (objFile->hasTLS())
+ fatal("Object file has a TLS section and single threaded TLS is not\n"
+ " currently supported for Alpha! Please recompile your "
+ "executable with \n a non-TLS toolchain.\n");
+
if (objFile->getArch() != ObjectFile::Alpha)
fatal("Object file architecture does not match compiled ISA (Alpha).");
switch (objFile->getOpSys()) {
case ObjectFile::Tru64:
- process = new AlphaTru64Process(nm, objFile, system,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp, cwd,
- _uid, _euid, _gid, _egid, _pid, _ppid);
+ process = new AlphaTru64Process(params, objFile);
break;
case ObjectFile::Linux:
- process = new AlphaLinuxProcess(nm, objFile, system,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp, cwd,
- _uid, _euid, _gid, _egid, _pid, _ppid);
+ process = new AlphaLinuxProcess(params, objFile);
break;
default:
switch (objFile->getOpSys()) {
case ObjectFile::Linux:
if (objFile->getArch() == ObjectFile::SPARC64) {
- process = new Sparc64LinuxProcess(nm, objFile, system,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp, cwd,
- _uid, _euid, _gid,
- _egid, _pid, _ppid);
+ process = new Sparc64LinuxProcess(params, objFile);
} else {
- process = new Sparc32LinuxProcess(nm, objFile, system,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp, cwd,
- _uid, _euid, _gid,
- _egid, _pid, _ppid);
+ process = new Sparc32LinuxProcess(params, objFile);
}
break;
case ObjectFile::Solaris:
- process = new SparcSolarisProcess(nm, objFile, system,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp, cwd,
- _uid, _euid, _gid, _egid, _pid, _ppid);
+ process = new SparcSolarisProcess(params, objFile);
break;
default:
fatal("Unknown/unsupported operating system.");
fatal("Object file architecture does not match compiled ISA (x86).");
switch (objFile->getOpSys()) {
case ObjectFile::Linux:
- process = new X86LinuxProcess(nm, objFile, system,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp, cwd,
- _uid, _euid, _gid,
- _egid, _pid, _ppid);
+ process = new X86LinuxProcess(params, objFile);
break;
default:
fatal("Unknown/unsupported operating system.");
fatal("Object file architecture does not match compiled ISA (MIPS).");
switch (objFile->getOpSys()) {
case ObjectFile::Linux:
- process = new MipsLinuxProcess(nm, objFile, system,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp, cwd,
- _uid, _euid, _gid, _egid, _pid, _ppid);
+ process = new MipsLinuxProcess(params, objFile);
+ break;
+
+ default:
+ fatal("Unknown/unsupported operating system.");
+ }
+#elif THE_ISA == ARM_ISA
+ if (objFile->getArch() != ObjectFile::Arm)
+ fatal("Object file architecture does not match compiled ISA (ARM).");
+ switch (objFile->getOpSys()) {
+ case ObjectFile::Linux:
+ process = new ArmLinuxProcess(params, objFile);
break;
default:
LiveProcess *
LiveProcessParams::create()
{
- string in = input;
- string out = output;
-
- // initialize file descriptors to default: same as simulator
- int stdin_fd, stdout_fd, stderr_fd;
-
- if (in == "stdin" || in == "cin")
- stdin_fd = STDIN_FILENO;
- else
- stdin_fd = Process::openInputFile(input);
-
- if (out == "stdout" || out == "cout")
- stdout_fd = STDOUT_FILENO;
- else if (out == "stderr" || out == "cerr")
- stdout_fd = STDERR_FILENO;
- else
- stdout_fd = Process::openOutputFile(out);
-
- stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO;
-
- return LiveProcess::create(name, system,
- stdin_fd, stdout_fd, stderr_fd,
- (string)executable == "" ? cmd[0] : executable,
- cmd, env, cwd,
- uid, euid, gid, egid, pid, ppid);
+ return LiveProcess::create(this);
}