tru64.hh
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 1,211 行 · 第 1/3 页
HH
1,211 行
// fell out of loop... no available inactive context cerr << "nxm_thread_create: no idle contexts available." << endl; abort(); } else { cerr << "nxm_thread_create: can't handle thread type " << attrp->type << endl; abort(); } return 0; } /// Thread idle call (like yield()). static SyscallReturn nxm_idleFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { return 0; } /// Block thread. static SyscallReturn nxm_thread_blockFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { using namespace std; uint64_t tid = tc->getSyscallArg(0); uint64_t secs = tc->getSyscallArg(1); uint64_t flags = tc->getSyscallArg(2); uint64_t action = tc->getSyscallArg(3); uint64_t usecs = tc->getSyscallArg(4); cout << tc->getCpuPtr()->name() << ": nxm_thread_block " << tid << " " << secs << " " << flags << " " << action << " " << usecs << endl; return 0; } /// block. static SyscallReturn nxm_blockFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { using namespace std; Addr uaddr = tc->getSyscallArg(0); uint64_t val = tc->getSyscallArg(1); uint64_t secs = tc->getSyscallArg(2); uint64_t usecs = tc->getSyscallArg(3); uint64_t flags = tc->getSyscallArg(4); BaseCPU *cpu = tc->getCpuPtr(); cout << cpu->name() << ": nxm_block " << hex << uaddr << dec << " " << val << " " << secs << " " << usecs << " " << flags << endl; return 0; } /// Unblock thread. static SyscallReturn nxm_unblockFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { using namespace std; Addr uaddr = tc->getSyscallArg(0); cout << tc->getCpuPtr()->name() << ": nxm_unblock " << hex << uaddr << dec << endl; return 0; } /// Switch thread priority. static SyscallReturn swtch_priFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { // Attempts to switch to another runnable thread (if there is // one). Returns false if there are no other threads to run // (i.e., the thread can reasonably spin-wait) or true if there // are other threads. // // Since we assume at most one "kernel" thread per CPU, it's // always safe to return false here. return 0; //false; } /// Activate thread context waiting on a channel. Just activate one /// by default. static int activate_waiting_context(Addr uaddr, LiveProcess *process, bool activate_all = false) { using namespace std; int num_activated = 0; list<Process::WaitRec>::iterator i = process->waitList.begin(); list<Process::WaitRec>::iterator end = process->waitList.end(); while (i != end && (num_activated == 0 || activate_all)) { if (i->waitChan == uaddr) { // found waiting process: make it active ThreadContext *newCtx = i->waitingContext; assert(newCtx->status() == ThreadContext::Suspended); newCtx->activate(); // get rid of this record i = process->waitList.erase(i); ++num_activated; } else { ++i; } } return num_activated; } /// M5 hacked-up lock acquire. static void m5_lock_mutex(Addr uaddr, LiveProcess *process, ThreadContext *tc) { using namespace TheISA; TypedBufferArg<uint64_t> lockp(uaddr); lockp.copyIn(tc->getMemPort()); if (gtoh(*lockp) == 0) { // lock is free: grab it *lockp = htog(1); lockp.copyOut(tc->getMemPort()); } else { // lock is busy: disable until free process->waitList.push_back(Process::WaitRec(uaddr, tc)); tc->suspend(); } } /// M5 unlock call. static void m5_unlock_mutex(Addr uaddr, LiveProcess *process, ThreadContext *tc) { TypedBufferArg<uint64_t> lockp(uaddr); lockp.copyIn(tc->getMemPort()); assert(*lockp != 0); // Check for a process waiting on the lock. int num_waiting = activate_waiting_context(uaddr, process); // clear lock field if no waiting context is taking over the lock if (num_waiting == 0) { *lockp = 0; lockp.copyOut(tc->getMemPort()); } } /// Lock acquire syscall handler. static SyscallReturn m5_mutex_lockFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { Addr uaddr = tc->getSyscallArg(0); m5_lock_mutex(uaddr, process, tc); // Return 0 since we will always return to the user with the lock // acquired. We will just keep the context inactive until that is // true. return 0; } /// Try lock (non-blocking). static SyscallReturn m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { using namespace TheISA; Addr uaddr = tc->getSyscallArg(0); TypedBufferArg<uint64_t> lockp(uaddr); lockp.copyIn(tc->getMemPort()); if (gtoh(*lockp) == 0) { // lock is free: grab it *lockp = htog(1); lockp.copyOut(tc->getMemPort()); return 0; } else { return 1; } } /// Unlock syscall handler. static SyscallReturn m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { Addr uaddr = tc->getSyscallArg(0); m5_unlock_mutex(uaddr, process, tc); return 0; } /// Signal ocndition. static SyscallReturn m5_cond_signalFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { Addr cond_addr = tc->getSyscallArg(0); // Wake up one process waiting on the condition variable. activate_waiting_context(cond_addr, process); return 0; } /// Wake up all processes waiting on the condition variable. static SyscallReturn m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { Addr cond_addr = tc->getSyscallArg(0); activate_waiting_context(cond_addr, process, true); return 0; } /// Wait on a condition. static SyscallReturn m5_cond_waitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { using namespace TheISA; Addr cond_addr = tc->getSyscallArg(0); Addr lock_addr = tc->getSyscallArg(1); TypedBufferArg<uint64_t> condp(cond_addr); TypedBufferArg<uint64_t> lockp(lock_addr); // user is supposed to acquire lock before entering lockp.copyIn(tc->getMemPort()); assert(gtoh(*lockp) != 0); m5_unlock_mutex(lock_addr, process, tc); process->waitList.push_back(Process::WaitRec(cond_addr, tc)); tc->suspend(); return 0; } /// Thread exit. static SyscallReturn m5_thread_exitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { assert(tc->status() == ThreadContext::Active); tc->deallocate(); return 0; } /// Indirect syscall invocation (call #0). static SyscallReturn indirectSyscallFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { int new_callnum = tc->getSyscallArg(0); for (int i = 0; i < 5; ++i) tc->setSyscallArg(i, tc->getSyscallArg(i+1)); SyscallDesc *new_desc = process->getDesc(new_callnum); if (desc == NULL) fatal("Syscall %d out of range", callnum); new_desc->doSyscall(new_callnum, process, tc); return 0; }}; // class Tru64class Tru64_F64 : public Tru64{ public: /// Stat buffer. Note that Tru64 v5.0+ use a new "F64" stat /// structure, and a new set of syscall numbers for stat calls. /// On some hosts (notably Linux) define st_atime, st_mtime, and /// st_ctime as macros, so we append an X to get around this. struct F64_stat { dev_t st_dev; //!< st_dev int32_t st_retired1; //!< st_retired1 mode_t st_mode; //!< st_mode nlink_t st_nlink; //!< st_nlink uint16_t st_nlink_reserved; //!< st_nlink_reserved uid_t st_uid; //!< st_uid gid_t st_gid; //!< st_gid dev_t st_rdev; //!< st_rdev dev_t st_ldev; //!< st_ldev off_t st_size; //!< st_size time_t st_retired2; //!< st_retired2 int32_t st_uatime; //!< st_uatime time_t st_retired3; //!< st_retired3 int32_t st_umtime; //!< st_umtime time_t st_retired4; //!< st_retired4 int32_t st_uctime; //!< st_uctime int32_t st_retired5; //!< st_retired5 int32_t st_retired6; //!< st_retired6 uint32_t st_flags; //!< st_flags uint32_t st_gen; //!< st_gen uint64_t st_spare[4]; //!< st_spare[4] ino_t st_ino; //!< st_ino int32_t st_ino_reserved; //!< st_ino_reserved time_t st_atimeX; //!< st_atime int32_t st_atime_reserved; //!< st_atime_reserved time_t st_mtimeX; //!< st_mtime int32_t st_mtime_reserved; //!< st_mtime_reserved time_t st_ctimeX; //!< st_ctime int32_t st_ctime_reserved; //!< st_ctime_reserved uint64_t st_blksize; //!< st_blksize uint64_t st_blocks; //!< st_blocks }; typedef F64_stat tgt_stat;/* static void copyOutStatBuf(TranslatingPort *mem, Addr addr, global_stat *host) { Tru64::copyOutStatBuf<Tru64::F64_stat>(mem, addr, host); }*/ static void copyOutStatfsBuf(TranslatingPort *mem, Addr addr, global_statfs *host) { Tru64::copyOutStatfsBuf<Tru64::F64_statfs>(mem, addr, host); }};class Tru64_PreF64 : public Tru64{ public: /// Old Tru64 v4.x stat struct. /// Tru64 maintains backwards compatibility with v4.x by /// implementing another set of stat functions using the old /// structure definition and binding them to the old syscall /// numbers. struct pre_F64_stat { dev_t st_dev; ino_t st_ino; mode_t st_mode; nlink_t st_nlink; uid_t st_uid __attribute__ ((aligned(sizeof(uid_t)))); gid_t st_gid; dev_t st_rdev; off_t st_size __attribute__ ((aligned(sizeof(off_t)))); time_t st_atimeX; int32_t st_uatime; time_t st_mtimeX; int32_t st_umtime; time_t st_ctimeX; int32_t st_uctime; uint32_t st_blksize; int32_t st_blocks; uint32_t st_flags; uint32_t st_gen; }; typedef pre_F64_stat tgt_stat;/* static void copyOutStatBuf(TranslatingPort *mem, Addr addr, global_stat *host) { Tru64::copyOutStatBuf<Tru64::pre_F64_stat>(mem, addr, host); }*/ static void copyOutStatfsBuf(TranslatingPort *mem, Addr addr, global_statfs *host) { Tru64::copyOutStatfsBuf<Tru64::pre_F64_statfs>(mem, addr, host); }};#endif // FULL_SYSTEM#endif // __TRU64_HH__
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?