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 + -
显示快捷键?