syscall emulation: Add the futex system call.

This commit is contained in:
Marc Orr 2012-07-10 22:51:54 -07:00
parent 52540b1b78
commit 387f843d51
5 changed files with 95 additions and 1 deletions

View file

@ -142,6 +142,10 @@ class AlphaLinux : public Linux
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__

View file

@ -415,7 +415,7 @@ SyscallDesc X86_64LinuxProcess::syscallDescs[] = {
/* 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),

View file

@ -171,6 +171,12 @@ class Linux : public OperatingSystem
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__

View file

@ -334,6 +334,87 @@ SyscallReturn getegidFunc(SyscallDesc *desc, int num,
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

View file

@ -400,6 +400,9 @@ class System : public MemObject
static void printSystems();
// For futex system call
std::map<uint64_t, std::list<ThreadContext *> * > futexMap;
};