syscall emulation: Add the futex system call.
This commit is contained in:
parent
52540b1b78
commit
387f843d51
|
@ -142,6 +142,10 @@ class AlphaLinux : public Linux
|
||||||
uint64_t freehigh; /* Available high memory size */
|
uint64_t freehigh; /* Available high memory size */
|
||||||
uint64_t mem_unit; /* Memory unit size in bytes */
|
uint64_t mem_unit; /* Memory unit size in bytes */
|
||||||
} tgt_sysinfo;
|
} 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__
|
#endif // __ALPHA_ALPHA_LINUX_LINUX_HH__
|
||||||
|
|
|
@ -415,7 +415,7 @@ SyscallDesc X86_64LinuxProcess::syscallDescs[] = {
|
||||||
/* 199 */ SyscallDesc("fremovexattr", unimplementedFunc),
|
/* 199 */ SyscallDesc("fremovexattr", unimplementedFunc),
|
||||||
/* 200 */ SyscallDesc("tkill", unimplementedFunc),
|
/* 200 */ SyscallDesc("tkill", unimplementedFunc),
|
||||||
/* 201 */ SyscallDesc("time", timeFunc<X86Linux64>),
|
/* 201 */ SyscallDesc("time", timeFunc<X86Linux64>),
|
||||||
/* 202 */ SyscallDesc("futex", ignoreFunc),
|
/* 202 */ SyscallDesc("futex", futexFunc<X86Linux64>),
|
||||||
/* 203 */ SyscallDesc("sched_setaffinity", unimplementedFunc),
|
/* 203 */ SyscallDesc("sched_setaffinity", unimplementedFunc),
|
||||||
/* 204 */ SyscallDesc("sched_getaffinity", unimplementedFunc),
|
/* 204 */ SyscallDesc("sched_getaffinity", unimplementedFunc),
|
||||||
/* 205 */ SyscallDesc("set_thread_area", unimplementedFunc),
|
/* 205 */ SyscallDesc("set_thread_area", unimplementedFunc),
|
||||||
|
|
|
@ -171,6 +171,12 @@ class Linux : public OperatingSystem
|
||||||
static int openSpecialFile(std::string path, LiveProcess *process, ThreadContext *tc);
|
static int openSpecialFile(std::string path, LiveProcess *process, ThreadContext *tc);
|
||||||
static std::string procMeminfo(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
|
}; // class Linux
|
||||||
|
|
||||||
#endif // __LINUX_HH__
|
#endif // __LINUX_HH__
|
||||||
|
|
|
@ -334,6 +334,87 @@ SyscallReturn getegidFunc(SyscallDesc *desc, int num,
|
||||||
SyscallReturn cloneFunc(SyscallDesc *desc, int num,
|
SyscallReturn cloneFunc(SyscallDesc *desc, int num,
|
||||||
LiveProcess *p, ThreadContext *tc);
|
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,
|
/// Pseudo Funcs - These functions use a different return convension,
|
||||||
/// returning a second value in a register other than the normal return register
|
/// returning a second value in a register other than the normal return register
|
||||||
|
|
|
@ -400,6 +400,9 @@ class System : public MemObject
|
||||||
|
|
||||||
static void printSystems();
|
static void printSystems();
|
||||||
|
|
||||||
|
// For futex system call
|
||||||
|
std::map<uint64_t, std::list<ThreadContext *> * > futexMap;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue