process.cc (11855:c706f4ab5dd7) | process.cc (11856:103e2f92c965) |
---|---|
1/* | 1/* |
2 * Copyright (c) 2014 Advanced Micro Devices, Inc. | 2 * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. |
3 * Copyright (c) 2012 ARM Limited 4 * All rights reserved 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating 9 * to a hardware implementation of the functionality of the software 10 * licensed hereunder. You may use the software subject to the license --- 25 unchanged lines hidden (view full) --- 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Nathan Binkert 42 * Steve Reinhardt 43 * Ali Saidi | 3 * Copyright (c) 2012 ARM Limited 4 * All rights reserved 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating 9 * to a hardware implementation of the functionality of the software 10 * licensed hereunder. You may use the software subject to the license --- 25 unchanged lines hidden (view full) --- 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Nathan Binkert 42 * Steve Reinhardt 43 * Ali Saidi |
44 * Brandon Potter |
|
44 */ 45 46#include "sim/process.hh" 47 48#include <fcntl.h> 49#include <unistd.h> 50 51#include <array> --- 6 unchanged lines hidden (view full) --- 58#include "base/loader/symtab.hh" 59#include "base/statistics.hh" 60#include "config/the_isa.hh" 61#include "cpu/thread_context.hh" 62#include "mem/page_table.hh" 63#include "mem/se_translating_port_proxy.hh" 64#include "params/Process.hh" 65#include "sim/emul_driver.hh" | 45 */ 46 47#include "sim/process.hh" 48 49#include <fcntl.h> 50#include <unistd.h> 51 52#include <array> --- 6 unchanged lines hidden (view full) --- 59#include "base/loader/symtab.hh" 60#include "base/statistics.hh" 61#include "config/the_isa.hh" 62#include "cpu/thread_context.hh" 63#include "mem/page_table.hh" 64#include "mem/se_translating_port_proxy.hh" 65#include "params/Process.hh" 66#include "sim/emul_driver.hh" |
67#include "sim/fd_array.hh" 68#include "sim/fd_entry.hh" |
|
66#include "sim/syscall_desc.hh" 67#include "sim/system.hh" 68 69#if THE_ISA == ALPHA_ISA 70#include "arch/alpha/linux/process.hh" 71#elif THE_ISA == SPARC_ISA 72#include "arch/sparc/linux/process.hh" 73#include "arch/sparc/solaris/process.hh" --- 11 unchanged lines hidden (view full) --- 85#else 86#error "THE_ISA not set" 87#endif 88 89 90using namespace std; 91using namespace TheISA; 92 | 69#include "sim/syscall_desc.hh" 70#include "sim/system.hh" 71 72#if THE_ISA == ALPHA_ISA 73#include "arch/alpha/linux/process.hh" 74#elif THE_ISA == SPARC_ISA 75#include "arch/sparc/linux/process.hh" 76#include "arch/sparc/solaris/process.hh" --- 11 unchanged lines hidden (view full) --- 88#else 89#error "THE_ISA not set" 90#endif 91 92 93using namespace std; 94using namespace TheISA; 95 |
93static int 94openFile(const string& filename, int flags, mode_t mode) 95{ 96 int sim_fd = open(filename.c_str(), flags, mode); 97 if (sim_fd != -1) 98 return sim_fd; 99 fatal("Unable to open %s with mode %O", filename, mode); 100} 101 102static int 103openInputFile(const string &filename) 104{ 105 return openFile(filename, O_RDONLY, 0); 106} 107 108static int 109openOutputFile(const string &filename) 110{ 111 return openFile(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664); 112} 113 | |
114Process::Process(ProcessParams * params, ObjectFile * obj_file) 115 : SimObject(params), system(params->system), 116 brk_point(0), stack_base(0), stack_size(0), stack_min(0), 117 max_stack_size(params->max_stack_size), 118 next_thread_stack_base(0), 119 useArchPT(params->useArchPT), 120 kvmInSE(params->kvmInSE), 121 pTable(useArchPT ? 122 static_cast<PageTableBase *>(new ArchPageTable(name(), params->pid, 123 system)) : 124 static_cast<PageTableBase *>(new FuncPageTable(name(), params->pid))), 125 initVirtMem(system->getSystemPort(), this, 126 SETranslatingPortProxy::Always), | 96Process::Process(ProcessParams * params, ObjectFile * obj_file) 97 : SimObject(params), system(params->system), 98 brk_point(0), stack_base(0), stack_size(0), stack_min(0), 99 max_stack_size(params->max_stack_size), 100 next_thread_stack_base(0), 101 useArchPT(params->useArchPT), 102 kvmInSE(params->kvmInSE), 103 pTable(useArchPT ? 104 static_cast<PageTableBase *>(new ArchPageTable(name(), params->pid, 105 system)) : 106 static_cast<PageTableBase *>(new FuncPageTable(name(), params->pid))), 107 initVirtMem(system->getSystemPort(), this, 108 SETranslatingPortProxy::Always), |
127 fd_array(make_shared<array<FDEntry, NUM_FDS>>()), 128 imap {{"", -1}, 129 {"cin", STDIN_FILENO}, 130 {"stdin", STDIN_FILENO}}, 131 oemap{{"", -1}, 132 {"cout", STDOUT_FILENO}, 133 {"stdout", STDOUT_FILENO}, 134 {"cerr", STDERR_FILENO}, 135 {"stderr", STDERR_FILENO}}, | |
136 objFile(obj_file), 137 argv(params->cmd), envp(params->env), cwd(params->cwd), 138 executable(params->executable), 139 _uid(params->uid), _euid(params->euid), 140 _gid(params->gid), _egid(params->egid), 141 _pid(params->pid), _ppid(params->ppid), | 109 objFile(obj_file), 110 argv(params->cmd), envp(params->env), cwd(params->cwd), 111 executable(params->executable), 112 _uid(params->uid), _euid(params->euid), 113 _gid(params->gid), _egid(params->egid), 114 _pid(params->pid), _ppid(params->ppid), |
142 drivers(params->drivers) | 115 drivers(params->drivers), 116 fds(make_shared<FDArray>(params->input, params->output, params->errout)) |
143{ | 117{ |
144 int sim_fd; 145 std::map<string,int>::iterator it; 146 147 // Search through the input options and set fd if match is found; 148 // otherwise, open an input file and seek to location. 149 FDEntry *fde_stdin = getFDEntry(STDIN_FILENO); 150 if ((it = imap.find(params->input)) != imap.end()) 151 sim_fd = it->second; 152 else 153 sim_fd = openInputFile(params->input); 154 fde_stdin->set(sim_fd, params->input, O_RDONLY, -1, false); 155 156 // Search through the output/error options and set fd if match is found; 157 // otherwise, open an output file and seek to location. 158 FDEntry *fde_stdout = getFDEntry(STDOUT_FILENO); 159 if ((it = oemap.find(params->output)) != oemap.end()) 160 sim_fd = it->second; 161 else 162 sim_fd = openOutputFile(params->output); 163 fde_stdout->set(sim_fd, params->output, O_WRONLY | O_CREAT | O_TRUNC, 164 0664, false); 165 166 FDEntry *fde_stderr = getFDEntry(STDERR_FILENO); 167 if (params->output == params->errout) 168 // Reuse the same file descriptor if these match. 169 sim_fd = fde_stdout->fd; 170 else if ((it = oemap.find(params->errout)) != oemap.end()) 171 sim_fd = it->second; 172 else 173 sim_fd = openOutputFile(params->errout); 174 fde_stderr->set(sim_fd, params->errout, O_WRONLY | O_CREAT | O_TRUNC, 175 0664, false); 176 | |
177 mmap_end = 0; | 118 mmap_end = 0; |
178 // other parameters will be initialized when the program is loaded | |
179 180 // load up symbols, if any... these may be used for debugging or 181 // profiling. 182 if (!debugSymbolTable) { 183 debugSymbolTable = new SymbolTable(); 184 if (!objFile->loadGlobalSymbols(debugSymbolTable) || 185 !objFile->loadLocalSymbols(debugSymbolTable) || 186 !objFile->loadWeakSymbols(debugSymbolTable)) { --- 12 unchanged lines hidden (view full) --- 199 using namespace Stats; 200 201 num_syscalls 202 .name(name() + ".num_syscalls") 203 .desc("Number of system calls") 204 ; 205} 206 | 119 120 // load up symbols, if any... these may be used for debugging or 121 // profiling. 122 if (!debugSymbolTable) { 123 debugSymbolTable = new SymbolTable(); 124 if (!objFile->loadGlobalSymbols(debugSymbolTable) || 125 !objFile->loadLocalSymbols(debugSymbolTable) || 126 !objFile->loadWeakSymbols(debugSymbolTable)) { --- 12 unchanged lines hidden (view full) --- 139 using namespace Stats; 140 141 num_syscalls 142 .name(name() + ".num_syscalls") 143 .desc("Number of system calls") 144 ; 145} 146 |
207void 208Process::inheritFDArray(Process *p) 209{ 210 fd_array = p->fd_array; 211} 212 | |
213ThreadContext * 214Process::findFreeContext() 215{ 216 for (int id : contextIds) { 217 ThreadContext *tc = system->getThreadContext(id); 218 if (tc->status() == ThreadContext::Halted) 219 return tc; 220 } --- 13 unchanged lines hidden (view full) --- 234 tc->activate(); 235 236 pTable->initState(tc); 237} 238 239DrainState 240Process::drain() 241{ | 147ThreadContext * 148Process::findFreeContext() 149{ 150 for (int id : contextIds) { 151 ThreadContext *tc = system->getThreadContext(id); 152 if (tc->status() == ThreadContext::Halted) 153 return tc; 154 } --- 13 unchanged lines hidden (view full) --- 168 tc->activate(); 169 170 pTable->initState(tc); 171} 172 173DrainState 174Process::drain() 175{ |
242 findFileOffsets(); | 176 fds->updateFileOffsets(); |
243 return DrainState::Drained; 244} 245 | 177 return DrainState::Drained; 178} 179 |
246int 247Process::allocFD(int sim_fd, const string& filename, int flags, int mode, 248 bool pipe) 249{ 250 for (int free_fd = 0; free_fd < fd_array->size(); free_fd++) { 251 FDEntry *fde = getFDEntry(free_fd); 252 if (fde->isFree()) { 253 fde->set(sim_fd, filename, flags, mode, pipe); 254 return free_fd; 255 } 256 } 257 258 fatal("Out of target file descriptors"); 259} 260 | |
261void | 180void |
262Process::resetFDEntry(int tgt_fd) 263{ 264 FDEntry *fde = getFDEntry(tgt_fd); 265 assert(fde->fd > -1); 266 267 fde->reset(); 268} 269 270int 271Process::getSimFD(int tgt_fd) 272{ 273 FDEntry *entry = getFDEntry(tgt_fd); 274 return entry ? entry->fd : -1; 275} 276 277FDEntry * 278Process::getFDEntry(int tgt_fd) 279{ 280 assert(0 <= tgt_fd && tgt_fd < fd_array->size()); 281 return &(*fd_array)[tgt_fd]; 282} 283 284int 285Process::getTgtFD(int sim_fd) 286{ 287 for (int index = 0; index < fd_array->size(); index++) 288 if ((*fd_array)[index].fd == sim_fd) 289 return index; 290 return -1; 291} 292 293void | |
294Process::allocateMem(Addr vaddr, int64_t size, bool clobber) 295{ 296 int npages = divCeil(size, (int64_t)PageBytes); 297 Addr paddr = system->allocPhysPages(npages); 298 pTable->map(vaddr, paddr, size, 299 clobber ? PageTableBase::Clobber : PageTableBase::Zero); 300} 301 --- 18 unchanged lines hidden (view full) --- 320 inform("Increasing stack size by one page."); 321 }; 322 return true; 323 } 324 return false; 325} 326 327void | 181Process::allocateMem(Addr vaddr, int64_t size, bool clobber) 182{ 183 int npages = divCeil(size, (int64_t)PageBytes); 184 Addr paddr = system->allocPhysPages(npages); 185 pTable->map(vaddr, paddr, size, 186 clobber ? PageTableBase::Clobber : PageTableBase::Zero); 187} 188 --- 18 unchanged lines hidden (view full) --- 207 inform("Increasing stack size by one page."); 208 }; 209 return true; 210 } 211 return false; 212} 213 214void |
328Process::fixFileOffsets() 329{ 330 auto seek = [] (FDEntry *fde) 331 { 332 if (lseek(fde->fd, fde->fileOffset, SEEK_SET) < 0) 333 fatal("Unable to see to location in %s", fde->filename); 334 }; 335 336 std::map<string,int>::iterator it; 337 338 // Search through the input options and set fd if match is found; 339 // otherwise, open an input file and seek to location. 340 FDEntry *fde_stdin = getFDEntry(STDIN_FILENO); 341 342 // Check if user has specified a different input file, and if so, use it 343 // instead of the file specified in the checkpoint. This also resets the 344 // file offset from the checkpointed value 345 string new_in = ((ProcessParams*)params())->input; 346 if (new_in != fde_stdin->filename) { 347 warn("Using new input file (%s) rather than checkpointed (%s)\n", 348 new_in, fde_stdin->filename); 349 fde_stdin->filename = new_in; 350 fde_stdin->fileOffset = 0; 351 } 352 353 if ((it = imap.find(fde_stdin->filename)) != imap.end()) { 354 fde_stdin->fd = it->second; 355 } else { 356 fde_stdin->fd = openInputFile(fde_stdin->filename); 357 seek(fde_stdin); 358 } 359 360 // Search through the output/error options and set fd if match is found; 361 // otherwise, open an output file and seek to location. 362 FDEntry *fde_stdout = getFDEntry(STDOUT_FILENO); 363 364 // Check if user has specified a different output file, and if so, use it 365 // instead of the file specified in the checkpoint. This also resets the 366 // file offset from the checkpointed value 367 string new_out = ((ProcessParams*)params())->output; 368 if (new_out != fde_stdout->filename) { 369 warn("Using new output file (%s) rather than checkpointed (%s)\n", 370 new_out, fde_stdout->filename); 371 fde_stdout->filename = new_out; 372 fde_stdout->fileOffset = 0; 373 } 374 375 if ((it = oemap.find(fde_stdout->filename)) != oemap.end()) { 376 fde_stdout->fd = it->second; 377 } else { 378 fde_stdout->fd = openOutputFile(fde_stdout->filename); 379 seek(fde_stdout); 380 } 381 382 FDEntry *fde_stderr = getFDEntry(STDERR_FILENO); 383 384 // Check if user has specified a different error file, and if so, use it 385 // instead of the file specified in the checkpoint. This also resets the 386 // file offset from the checkpointed value 387 string new_err = ((ProcessParams*)params())->errout; 388 if (new_err != fde_stderr->filename) { 389 warn("Using new error file (%s) rather than checkpointed (%s)\n", 390 new_err, fde_stderr->filename); 391 fde_stderr->filename = new_err; 392 fde_stderr->fileOffset = 0; 393 } 394 395 if (fde_stdout->filename == fde_stderr->filename) { 396 // Reuse the same file descriptor if these match. 397 fde_stderr->fd = fde_stdout->fd; 398 } else if ((it = oemap.find(fde_stderr->filename)) != oemap.end()) { 399 fde_stderr->fd = it->second; 400 } else { 401 fde_stderr->fd = openOutputFile(fde_stderr->filename); 402 seek(fde_stderr); 403 } 404 405 for (int tgt_fd = 3; tgt_fd < fd_array->size(); tgt_fd++) { 406 FDEntry *fde = getFDEntry(tgt_fd); 407 if (fde->fd == -1) 408 continue; 409 410 if (fde->isPipe) { 411 if (fde->filename == "PIPE-WRITE") 412 continue; 413 assert(fde->filename == "PIPE-READ"); 414 415 int fds[2]; 416 if (pipe(fds) < 0) 417 fatal("Unable to create new pipe"); 418 419 fde->fd = fds[0]; 420 421 FDEntry *fde_write = getFDEntry(fde->readPipeSource); 422 assert(fde_write->filename == "PIPE-WRITE"); 423 fde_write->fd = fds[1]; 424 } else { 425 fde->fd = openFile(fde->filename.c_str(), fde->flags, fde->mode); 426 seek(fde); 427 } 428 } 429} 430 431void 432Process::findFileOffsets() 433{ 434 for (auto& fde : *fd_array) { 435 if (fde.fd != -1) 436 fde.fileOffset = lseek(fde.fd, 0, SEEK_CUR); 437 } 438} 439 440void 441Process::setReadPipeSource(int read_pipe_fd, int source_fd) 442{ 443 FDEntry *fde = getFDEntry(read_pipe_fd); 444 assert(source_fd >= -1); 445 fde->readPipeSource = source_fd; 446} 447 448void | |
449Process::serialize(CheckpointOut &cp) const 450{ 451 SERIALIZE_SCALAR(brk_point); 452 SERIALIZE_SCALAR(stack_base); 453 SERIALIZE_SCALAR(stack_size); 454 SERIALIZE_SCALAR(stack_min); 455 SERIALIZE_SCALAR(next_thread_stack_base); 456 SERIALIZE_SCALAR(mmap_end); 457 pTable->serialize(cp); | 215Process::serialize(CheckpointOut &cp) const 216{ 217 SERIALIZE_SCALAR(brk_point); 218 SERIALIZE_SCALAR(stack_base); 219 SERIALIZE_SCALAR(stack_size); 220 SERIALIZE_SCALAR(stack_min); 221 SERIALIZE_SCALAR(next_thread_stack_base); 222 SERIALIZE_SCALAR(mmap_end); 223 pTable->serialize(cp); |
458 for (int x = 0; x < fd_array->size(); x++) { 459 (*fd_array)[x].serializeSection(cp, csprintf("FDEntry%d", x)); 460 } | 224 /** 225 * Checkpoints for file descriptors currently do not work. Need to 226 * come back and fix them at a later date. 227 */ |
461 | 228 |
229 warn("Checkpoints for file descriptors currently do not work."); 230#if 0 231 for (int x = 0; x < fds->getSize(); x++) 232 (*fds)[x].serializeSection(cp, csprintf("FDEntry%d", x)); 233#endif 234 |
|
462} 463 464void 465Process::unserialize(CheckpointIn &cp) 466{ 467 UNSERIALIZE_SCALAR(brk_point); 468 UNSERIALIZE_SCALAR(stack_base); 469 UNSERIALIZE_SCALAR(stack_size); 470 UNSERIALIZE_SCALAR(stack_min); 471 UNSERIALIZE_SCALAR(next_thread_stack_base); 472 UNSERIALIZE_SCALAR(mmap_end); 473 pTable->unserialize(cp); | 235} 236 237void 238Process::unserialize(CheckpointIn &cp) 239{ 240 UNSERIALIZE_SCALAR(brk_point); 241 UNSERIALIZE_SCALAR(stack_base); 242 UNSERIALIZE_SCALAR(stack_size); 243 UNSERIALIZE_SCALAR(stack_min); 244 UNSERIALIZE_SCALAR(next_thread_stack_base); 245 UNSERIALIZE_SCALAR(mmap_end); 246 pTable->unserialize(cp); |
474 for (int x = 0; x < fd_array->size(); x++) { 475 FDEntry *fde = getFDEntry(x); 476 fde->unserializeSection(cp, csprintf("FDEntry%d", x)); 477 } 478 fixFileOffsets(); | 247 /** 248 * Checkpoints for file descriptors currently do not work. Need to 249 * come back and fix them at a later date. 250 */ 251 warn("Checkpoints for file descriptors currently do not work."); 252#if 0 253 for (int x = 0; x < fds->getSize(); x++) 254 (*fds)[x]->unserializeSection(cp, csprintf("FDEntry%d", x)); 255 fds->restoreFileOffsets(); 256#endif |
479 // The above returns a bool so that you could do something if you don't 480 // find the param in the checkpoint if you wanted to, like set a default 481 // but in this case we'll just stick with the instantiated value if not 482 // found. 483} 484 485bool 486Process::map(Addr vaddr, Addr paddr, int size, bool cacheable) --- 250 unchanged lines hidden --- | 257 // The above returns a bool so that you could do something if you don't 258 // find the param in the checkpoint if you wanted to, like set a default 259 // but in this case we'll just stick with the instantiated value if not 260 // found. 261} 262 263bool 264Process::map(Addr vaddr, Addr paddr, int size, bool cacheable) --- 250 unchanged lines hidden --- |