process.cc

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 719 行 · 第 1/2 页

CC
719
字号
/* * Copyright (c) 2001, 2002, 2003, 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. * * Authors: Nathan L. Binkert *          Steven K. Reinhardt *          Ali G. Saidi */#include <unistd.h>#include <fcntl.h>#include <string>#include "arch/remote_gdb.hh"#include "base/intmath.hh"#include "base/loader/object_file.hh"#include "base/loader/symtab.hh"#include "base/statistics.hh"#include "config/full_system.hh"#include "cpu/thread_context.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/process.hh"#include "sim/process_impl.hh"#include "sim/stats.hh"#include "sim/syscall_emul.hh"#include "sim/system.hh"#include "arch/isa_specific.hh"#if THE_ISA == ALPHA_ISA#include "arch/alpha/linux/process.hh"#include "arch/alpha/tru64/process.hh"#elif THE_ISA == SPARC_ISA#include "arch/sparc/linux/process.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"#else#error "THE_ISA not set"#endifusing namespace std;using namespace TheISA;//// The purpose of this code is to fake the loader & syscall mechanism// when there's no OS: thus there's no resone to use it in FULL_SYSTEM// mode when we do have an OS//#if FULL_SYSTEM#error "process.cc not compatible with FULL_SYSTEM"#endif// current number of allocated processesint num_processes = 0;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)    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) {        Process::FdMap *fdo = &fd_map[i];        fdo->fd = -1;    }    mmap_start = mmap_end = 0;    nxm_start = nxm_end = 0;    pTable = new PageTable(this);    // other parameters will be initialized when the program is loaded}voidProcess::regStats(){    using namespace Stats;    num_syscalls        .name(name() + ".PROG:num_syscalls")        .desc("Number of system calls")        ;}//// static helper functions//intProcess::openInputFile(const string &filename){    int fd = open(filename.c_str(), O_RDONLY);    if (fd == -1) {        perror(NULL);        cerr << "unable to open \"" << filename << "\" for reading\n";        fatal("can't open input file");    }    return fd;}intProcess::openOutputFile(const string &filename){    int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0774);    if (fd == -1) {        perror(NULL);        cerr << "unable to open \"" << filename << "\" for writing\n";        fatal("can't open output file");    }    return fd;}intProcess::registerThreadContext(ThreadContext *tc){    // add to list    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();    remoteGDB.push_back(rgdb);    // return CPU number to caller    return myIndex;}voidProcess::startup(){    if (threadContexts.empty())        fatal("Process %s is not associated with any CPUs!\n", name());    // first thread context for this process... initialize & enable    ThreadContext *tc = threadContexts[0];    // mark this context as active so it will start ticking.    tc->activate(0);    Port *mem_port;    mem_port = system->physmem->getPort("functional");    initVirtMem = new TranslatingPort("process init port", this,            TranslatingPort::Always);    mem_port->setPeer(initVirtMem);    initVirtMem->setPeer(mem_port);}voidProcess::replaceThreadContext(ThreadContext *tc, int tcIndex){    if (tcIndex >= threadContexts.size()) {        panic("replaceThreadContext: bad tcIndex, %d >= %d\n",              tcIndex, threadContexts.size());    }    threadContexts[tcIndex] = tc;}// map simulator fd sim_fd to target fd tgt_fdvoidProcess::dup_fd(int sim_fd, int tgt_fd){    if (tgt_fd < 0 || tgt_fd > MAX_FD)        panic("Process::dup_fd tried to dup past MAX_FD (%d)", tgt_fd);    Process::FdMap *fdo = &fd_map[tgt_fd];    fdo->fd = sim_fd;}// generate new target fd for sim_fdintProcess::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) {        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;        }    }    panic("Process::alloc_fd: out of file descriptors!");}// free target fd (e.g., after close)voidProcess::free_fd(int tgt_fd){    Process::FdMap *fdo = &fd_map[tgt_fd];    if (fdo->fd == -1)        warn("Process::free_fd: request to free unused fd %d", tgt_fd);    fdo->fd = -1;    fdo->filename = "NULL";    fdo->mode = 0;    fdo->fileOffset = 0;    fdo->flags = 0;    fdo->isPipe = false;    fdo->readPipeSource = 0;}// look up simulator fd for given target fdintProcess::sim_fd(int tgt_fd){    if (tgt_fd > MAX_FD)        return -1;    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];}boolProcess::checkAndAllocNextPage(Addr vaddr){    // if this is an initial write we might not have    if (vaddr >= stack_min && vaddr < stack_base) {        pTable->allocate(roundDown(vaddr, VMPageSize), VMPageSize);        return true;    }    // We've accessed the next page of the stack, so extend the stack    // to cover it.    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 themvoidProcess::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;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?