summaryrefslogtreecommitdiff
path: root/src/sim
diff options
context:
space:
mode:
authorMatthew Sinclair <matthew.sinclair@amd.com>2019-03-12 10:37:51 -0400
committerBrandon Potter <Brandon.Potter@amd.com>2019-08-06 18:32:22 +0000
commit20428d69da186083a4fe9e97acb25e79c1857366 (patch)
tree5c888cb142e845b385529b831206dde8484e9d50 /src/sim
parent361bc8b47260a55902764054d3ac25694ac93f8a (diff)
downloadgem5-20428d69da186083a4fe9e97acb25e79c1857366.tar.xz
sim-se: adding pipe2 syscall
pipe2 builds on top of the pipe syscall implementation by adding some extra flags for the files (to avoid have to make separate calls to fcntl). Change-Id: I88cf6f1387b9d14e60b33a32db412da9ed93a3e6 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/12310 Reviewed-by: Brandon Potter <Brandon.Potter@amd.com> Maintainer: Brandon Potter <Brandon.Potter@amd.com> Tested-by: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'src/sim')
-rw-r--r--src/sim/syscall_emul.cc60
-rw-r--r--src/sim/syscall_emul.hh5
2 files changed, 61 insertions, 4 deletions
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
index 142292d1f..28e3e3ded 100644
--- a/src/sim/syscall_emul.cc
+++ b/src/sim/syscall_emul.cc
@@ -866,13 +866,18 @@ fcntl64Func(SyscallDesc *desc, int num, ThreadContext *tc)
}
SyscallReturn
-pipeImpl(SyscallDesc *desc, int callnum, ThreadContext *tc, bool pseudoPipe)
+pipeImpl(SyscallDesc *desc, int callnum, ThreadContext *tc, bool pseudo_pipe,
+ bool is_pipe2)
{
Addr tgt_addr = 0;
+ int flags = 0;
auto p = tc->getProcessPtr();
- if (!pseudoPipe) {
+ if (!pseudo_pipe) {
int index = 0;
tgt_addr = p->getSyscallArg(tc, index);
+ if (is_pipe2) {
+ flags = p->getSyscallArg(tc, index);
+ }
}
int sim_fds[2], tgt_fds[2];
@@ -884,10 +889,12 @@ pipeImpl(SyscallDesc *desc, int callnum, ThreadContext *tc, bool pseudoPipe)
auto rend = PipeFDEntry::EndType::read;
auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
tgt_fds[0] = p->fds->allocFD(rpfd);
+ int sim_fd_rpfd = rpfd->getSimFD();
auto wend = PipeFDEntry::EndType::write;
auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
tgt_fds[1] = p->fds->allocFD(wpfd);
+ int sim_fd_wpfd = wpfd->getSimFD();
/**
* Now patch the read object to record the target file descriptor chosen
@@ -899,7 +906,7 @@ pipeImpl(SyscallDesc *desc, int callnum, ThreadContext *tc, bool pseudoPipe)
* 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.
*/
- if (pseudoPipe) {
+ if (pseudo_pipe) {
tc->setIntReg(SyscallPseudoReturnReg, tgt_fds[1]);
return tgt_fds[0];
}
@@ -913,6 +920,45 @@ pipeImpl(SyscallDesc *desc, int callnum, ThreadContext *tc, bool pseudoPipe)
buf_ptr[0] = tgt_fds[0];
buf_ptr[1] = tgt_fds[1];
tgt_handle.copyOut(tc->getVirtProxy());
+
+ // pipe2 has additional behavior if flags != 0
+ if (is_pipe2 && flags) {
+ // pipe2 only uses O_NONBLOCK, O_CLOEXEC, and (O_NONBLOCK | O_CLOEXEC)
+ // if flags set to anything else, return EINVAL
+ if ((flags != O_CLOEXEC) && (flags != O_NONBLOCK) &&
+ (flags != (O_CLOEXEC | O_NONBLOCK))) {
+ return -EINVAL;
+ }
+
+ /*
+ If O_NONBLOCK is passed in as a flag to pipe2, set O_NONBLOCK file
+ status flag for two new open file descriptors.
+ */
+ if (flags & O_NONBLOCK) {
+ /*
+ O_NONBLOCK is set when the programmer wants to avoid a separate
+ call(s) to fcntl in their code, so mirror the fcntl
+ implementation for handling file descriptors -- rely on host to
+ maintain file status flags.
+ */
+ if (fcntl(sim_fd_rpfd, F_SETFL, O_NONBLOCK)) {
+ return -errno;
+ }
+ if (fcntl(sim_fd_wpfd, F_SETFL, O_NONBLOCK)) {
+ return -errno;
+ }
+ }
+
+ /*
+ If O_CLOEXEC is passed in as a flag to pipe2, set close-on-exec
+ (FD_CLOEXEC) file status flag for two new open file descriptors.
+ */
+ if (flags & O_CLOEXEC) {
+ rpfd->setCOE(true);
+ wpfd->setCOE(true);
+ }
+ }
+
return 0;
}
@@ -929,6 +975,14 @@ pipeFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
}
SyscallReturn
+pipe2Func(SyscallDesc *desc, int callnum, ThreadContext *tc)
+{
+ // call pipeImpl since the only difference between pipe and pipe2 is
+ // the flags values and what they do (at the end of pipeImpl)
+ return pipeImpl(desc, callnum, tc, false, true);
+}
+
+SyscallReturn
setpgidFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
{
int index = 0;
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index e2f2fc200..875f565cd 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -252,7 +252,10 @@ SyscallReturn pipeFunc(SyscallDesc *desc, int num, ThreadContext *tc);
/// Internal pipe() handler.
SyscallReturn pipeImpl(SyscallDesc *desc, int num, ThreadContext *tc,
- bool pseudoPipe);
+ bool pseudo_pipe, bool is_pipe2=false);
+
+/// Target pipe() handler.
+SyscallReturn pipe2Func(SyscallDesc *desc, int num, ThreadContext *tc);
/// Target getpid() handler.
SyscallReturn getpidFunc(SyscallDesc *desc, int num, ThreadContext *tc);