summaryrefslogtreecommitdiff
path: root/src/sim/syscall_emul.hh
diff options
context:
space:
mode:
authorMoyang Wang <mw828@cornell.edu>2018-04-02 16:23:02 -0400
committerTuan Ta <qtt2@cornell.edu>2019-02-08 15:25:30 +0000
commit758b62cfb2ede5fa2187e4cab899691505179d43 (patch)
treedeaaf97ea7b97c061f36e10d08463ae78498e864 /src/sim/syscall_emul.hh
parent42b063ad30324f1459915070226e820aabd54336 (diff)
downloadgem5-758b62cfb2ede5fa2187e4cab899691505179d43.tar.xz
sim, kern: support FUTEX_CMP_REQUEUE
This patch supports FUTEX_CMP_REQUEUE operation. Below is its description from Linux man page: futex syscall: int futex(int *uaddr, int futex_op, int val, const struct timespec *timeout, int *uaddr2, int val3); This operation first checks whether the location uaddr still contains the value val3. If not, the operation fails with the error EAGAIN. Otherwise, the operation wakes up a maximum of val waiters that are waiting on the futex at uaddr. If there are more than val waiters, then the remaining waiters are removed from the wait queue of the source futex at uaddr and added to the wait queue of the target futex at uaddr2. The val2 argument specifies an upper limit on the number of waiters that are requeued to the futex at uaddr2. Reference: http://man7.org/linux/man-pages/man2/futex.2.html Change-Id: I6d2ebd19a935b656d19d8342f7ab450c0d2031f4 Reviewed-on: https://gem5-review.googlesource.com/c/9629 Reviewed-by: Brandon Potter <Brandon.Potter@amd.com> Maintainer: Brandon Potter <Brandon.Potter@amd.com>
Diffstat (limited to 'src/sim/syscall_emul.hh')
-rw-r--r--src/sim/syscall_emul.hh15
1 files changed, 14 insertions, 1 deletions
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index 295598c52..0b7585cb4 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -441,8 +441,21 @@ futexFunc(SyscallDesc *desc, int callnum, Process *process,
return futex_map.wakeup(uaddr, process->tgid(), val);
} else if (OS::TGT_FUTEX_WAKE_BITSET == op) {
return futex_map.wakeup_bitset(uaddr, process->tgid(), val3);
- }
+ } else if (OS::TGT_FUTEX_REQUEUE == op ||
+ OS::TGT_FUTEX_CMP_REQUEUE == op) {
+ // Ensure futex system call accessed atomically.
+ BufferArg buf(uaddr, sizeof(int));
+ buf.copyIn(tc->getMemProxy());
+ int mem_val = *(int*)buf.bufferPtr();
+ /*
+ * For CMP_REQUEUE, the whole operation is only started only if
+ * val3 is still the value of the futex pointed to by uaddr.
+ */
+ if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val)
+ return -OS::TGT_EWOULDBLOCK;
+ return futex_map.requeue(uaddr, process->tgid(), val, timeout, uaddr2);
+ }
warn("futex: op %d not implemented; ignoring.", op);
return -ENOSYS;
}