changeset 6e854ea87bab in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=6e854ea87bab
description:
        syscall emulation: Add the futex system call.

diffstat:

 src/arch/alpha/linux/linux.hh  |   4 ++
 src/arch/x86/linux/syscalls.cc |   2 +-
 src/kern/linux/linux.hh        |   6 +++
 src/sim/syscall_emul.hh        |  81 ++++++++++++++++++++++++++++++++++++++++++
 src/sim/system.hh              |   3 +
 5 files changed, 95 insertions(+), 1 deletions(-)

diffs (146 lines):

diff -r f133ba654050 -r 6e854ea87bab src/arch/alpha/linux/linux.hh
--- a/src/arch/alpha/linux/linux.hh     Tue Jul 10 22:51:54 2012 -0700
+++ b/src/arch/alpha/linux/linux.hh     Tue Jul 10 22:51:54 2012 -0700
@@ -142,6 +142,10 @@
        uint64_t freehigh;  /* Available high memory size */
        uint64_t mem_unit;  /* Memory unit size in bytes */
     } tgt_sysinfo;
+
+    // For futex system call
+    static const unsigned TGT_EAGAIN      = 35;
+    static const unsigned TGT_EWOULDBLOCK = TGT_EAGAIN;
 };
 
 #endif // __ALPHA_ALPHA_LINUX_LINUX_HH__
diff -r f133ba654050 -r 6e854ea87bab src/arch/x86/linux/syscalls.cc
--- a/src/arch/x86/linux/syscalls.cc    Tue Jul 10 22:51:54 2012 -0700
+++ b/src/arch/x86/linux/syscalls.cc    Tue Jul 10 22:51:54 2012 -0700
@@ -415,7 +415,7 @@
     /* 199 */ SyscallDesc("fremovexattr", unimplementedFunc),
     /* 200 */ SyscallDesc("tkill", unimplementedFunc),
     /* 201 */ SyscallDesc("time", timeFunc<X86Linux64>),
-    /* 202 */ SyscallDesc("futex", ignoreFunc),
+    /* 202 */ SyscallDesc("futex", futexFunc<X86Linux64>),
     /* 203 */ SyscallDesc("sched_setaffinity", unimplementedFunc),
     /* 204 */ SyscallDesc("sched_getaffinity", unimplementedFunc),
     /* 205 */ SyscallDesc("set_thread_area", unimplementedFunc),
diff -r f133ba654050 -r 6e854ea87bab src/kern/linux/linux.hh
--- a/src/kern/linux/linux.hh   Tue Jul 10 22:51:54 2012 -0700
+++ b/src/kern/linux/linux.hh   Tue Jul 10 22:51:54 2012 -0700
@@ -171,6 +171,12 @@
     static int openSpecialFile(std::string path, LiveProcess *process, 
ThreadContext *tc);
     static std::string procMeminfo(LiveProcess *process, ThreadContext *tc);
 
+    // For futex system call
+    static const unsigned TGT_FUTEX_WAIT  = 0;
+    static const unsigned TGT_FUTEX_WAKE  = 1;
+    static const unsigned TGT_EAGAIN      = 11;
+    static const unsigned TGT_EWOULDBLOCK = TGT_EAGAIN;
+
 };  // class Linux
 
 #endif // __LINUX_HH__
diff -r f133ba654050 -r 6e854ea87bab src/sim/syscall_emul.hh
--- a/src/sim/syscall_emul.hh   Tue Jul 10 22:51:54 2012 -0700
+++ b/src/sim/syscall_emul.hh   Tue Jul 10 22:51:54 2012 -0700
@@ -334,6 +334,87 @@
 SyscallReturn cloneFunc(SyscallDesc *desc, int num,
                                LiveProcess *p, ThreadContext *tc);
 
+/// Futex system call
+///  Implemented by Daniel Sanchez
+///  Used by printf's in multi-threaded apps
+template <class OS>
+SyscallReturn
+futexFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+          ThreadContext *tc)
+{
+    int index_uaddr = 0;
+    int index_op = 1;
+    int index_val = 2;
+    int index_timeout = 3;
+
+    uint64_t uaddr = process->getSyscallArg(tc, index_uaddr);
+    int op = process->getSyscallArg(tc, index_op);
+    int val = process->getSyscallArg(tc, index_val);
+    uint64_t timeout = process->getSyscallArg(tc, index_timeout);
+
+    std::map<uint64_t, std::list<ThreadContext *> * >
+        &futex_map = tc->getSystemPtr()->futexMap;
+
+    DPRINTF(SyscallVerbose, "In sys_futex: Address=%llx, op=%d, val=%d\n",
+            uaddr, op, val);
+
+
+    if (op == OS::TGT_FUTEX_WAIT) {
+        if (timeout != 0) {
+            warn("sys_futex: FUTEX_WAIT with non-null timeout unimplemented;"
+                 "we'll wait indefinitely");
+        }
+
+        uint8_t *buf = new uint8_t[sizeof(int)];
+        tc->getMemProxy().readBlob((Addr)uaddr, buf, (int)sizeof(int));
+        int mem_val = *((int *)buf);
+        delete buf;
+
+        if(val != mem_val) {
+            DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, read: %d, "
+                                    "expected: %d\n", mem_val, val);
+            return -OS::TGT_EWOULDBLOCK;
+        }
+
+        // Queue the thread context
+        std::list<ThreadContext *> * tcWaitList;
+        if (futex_map.count(uaddr)) {
+            tcWaitList = futex_map.find(uaddr)->second;
+        } else {
+            tcWaitList = new std::list<ThreadContext *>();
+            futex_map.insert(std::pair< uint64_t,
+                            std::list<ThreadContext *> * >(uaddr, tcWaitList));
+        }
+        tcWaitList->push_back(tc);
+        DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAIT, suspending calling "
+                                "thread context\n");
+        tc->suspend();
+        return 0;
+    } else if (op == OS::TGT_FUTEX_WAKE){
+        int wokenUp = 0;
+        std::list<ThreadContext *> * tcWaitList;
+        if (futex_map.count(uaddr)) {
+            tcWaitList = futex_map.find(uaddr)->second;
+            while (tcWaitList->size() > 0 && wokenUp < val) {
+                tcWaitList->front()->activate();
+                tcWaitList->pop_front();
+                wokenUp++;
+            }
+            if(tcWaitList->empty()) {
+                futex_map.erase(uaddr);
+                delete tcWaitList;
+            }
+        }
+        DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, activated %d waiting "
+                                "thread contexts\n", wokenUp);
+        return wokenUp;
+    } else {
+        warn("sys_futex: op %d is not implemented, just returning...");
+        return 0;
+    }
+
+}
+
 
 /// Pseudo Funcs  - These functions use a different return convension,
 /// returning a second value in a register other than the normal return 
register
diff -r f133ba654050 -r 6e854ea87bab src/sim/system.hh
--- a/src/sim/system.hh Tue Jul 10 22:51:54 2012 -0700
+++ b/src/sim/system.hh Tue Jul 10 22:51:54 2012 -0700
@@ -400,6 +400,9 @@
 
     static void printSystems();
 
+    // For futex system call
+    std::map<uint64_t, std::list<ThreadContext *> * > futexMap;
+
 
 };
 
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to