?? alpha_tru64_process.cc
字號:
rad_state.copyIn(xc->mem); uint64_t uniq_val = attrp->pthid - rad_state->nxm_uniq_offset; if (attrp->type == Tru64::NXM_TYPE_MANAGER) { // DEC pthreads seems to always create one of these (in // addition to N application threads), but we don't use it, // so don't bother creating it. // This is supposed to be a port number. Make something up. *kidp = 99; kidp.copyOut(xc->mem); return 0; } else if (attrp->type == Tru64::NXM_TYPE_VP) { // A real "virtual processor" kernel thread. Need to fork // this thread on another CPU. Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[thread_index]; if (ssp->nxm_u.nxm_active != 0) return (int) Tru64::KERN_NOT_RECEIVER; ssp->nxm_u.pth_id = attrp->pthid; ssp->nxm_u.nxm_active = uniq_val | 1; rad_state.copyOut(xc->mem); Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info); int slot_state_size = process->numCpus() * sizeof(Tru64::nxm_slot_state_t); TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr, slot_state_size); slot_state.copyIn(xc->mem); if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) { cerr << "nxm_thread_createFunc: requested VP slot " << thread_index << " not available!" << endl; fatal(""); } slot_state[thread_index] = Tru64::NXM_SLOT_BOUND; slot_state.copyOut(xc->mem); // Find a free simulator execution context. for (int i = 0; i < process->numCpus(); ++i) { ExecContext *xc = process->execContexts[i]; if (xc->status() == ExecContext::Unallocated) { // inactive context... grab it init_exec_context(xc, attrp, uniq_val); // This is supposed to be a port number, but we'll try // and get away with just sticking the thread index // here. *kidp = thread_index; kidp.copyOut(xc->mem); return 0; } } // 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, Process *process, ExecContext *xc) { return 0; } /// Block thread. static SyscallReturn nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { uint64_t tid = xc->getSyscallArg(0); uint64_t secs = xc->getSyscallArg(1); uint64_t flags = xc->getSyscallArg(2); uint64_t action = xc->getSyscallArg(3); uint64_t usecs = xc->getSyscallArg(4); cout << xc->cpu->name() << ": nxm_thread_block " << tid << " " << secs << " " << flags << " " << action << " " << usecs << endl; return 0; } /// block. static SyscallReturn nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { Addr uaddr = xc->getSyscallArg(0); uint64_t val = xc->getSyscallArg(1); uint64_t secs = xc->getSyscallArg(2); uint64_t usecs = xc->getSyscallArg(3); uint64_t flags = xc->getSyscallArg(4); BaseCPU *cpu = xc->cpu; 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, Process *process, ExecContext *xc) { Addr uaddr = xc->getSyscallArg(0); cout << xc->cpu->name() << ": nxm_unblock " << hex << uaddr << dec << endl; return 0; } /// Switch thread priority. static SyscallReturn swtch_priFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { // 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 exec context waiting on a channel. Just activate one /// by default. static int activate_waiting_context(Addr uaddr, Process *process, bool activate_all = false) { 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 ExecContext *newCtx = i->waitingContext; assert(newCtx->status() == ExecContext::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, Process *process, ExecContext *xc) { TypedBufferArg<uint64_t> lockp(uaddr); lockp.copyIn(xc->mem); if (*lockp == 0) { // lock is free: grab it *lockp = 1; lockp.copyOut(xc->mem); } else { // lock is busy: disable until free process->waitList.push_back(Process::WaitRec(uaddr, xc)); xc->suspend(); } } /// M5 unlock call. static void m5_unlock_mutex(Addr uaddr, Process *process, ExecContext *xc) { TypedBufferArg<uint64_t> lockp(uaddr); lockp.copyIn(xc->mem); 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(xc->mem); } } /// Lock acquire syscall handler. static SyscallReturn m5_mutex_lockFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { Addr uaddr = xc->getSyscallArg(0); m5_lock_mutex(uaddr, process, xc); // 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, Process *process, ExecContext *xc) { Addr uaddr = xc->getSyscallArg(0); TypedBufferArg<uint64_t> lockp(uaddr); lockp.copyIn(xc->mem); if (*lockp == 0) { // lock is free: grab it *lockp = 1; lockp.copyOut(xc->mem); return 0; } else { return 1; } } /// Unlock syscall handler. static SyscallReturn m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { Addr uaddr = xc->getSyscallArg(0); m5_unlock_mutex(uaddr, process, xc); return 0; } /// Signal ocndition. static SyscallReturn m5_cond_signalFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { Addr cond_addr = xc->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, Process *process, ExecContext *xc) { Addr cond_addr = xc->getSyscallArg(0); activate_waiting_context(cond_addr, process, true); return 0; } /// Wait on a condition. static SyscallReturn m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { Addr cond_addr = xc->getSyscallArg(0); Addr lock_addr = xc->getSyscallArg(1); TypedBufferArg<uint64_t> condp(cond_addr); TypedBufferArg<uint64_t> lockp(lock_addr); // user is supposed to acquire lock before entering lockp.copyIn(xc->mem); assert(*lockp != 0); m5_unlock_mutex(lock_addr, process, xc); process->waitList.push_back(Process::WaitRec(cond_addr, xc)); xc->suspend(); return 0; } /// Thread exit. static SyscallReturn m5_thread_exitFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { assert(xc->status() == ExecContext::Active); xc->deallocate(); return 0; } /// Array of syscall descriptors for Mach syscalls, indexed by /// (negated) call number. static SyscallDesc machSyscallDescs[]; /// Number of syscalls in machSyscallDescs[]. static const int Num_Mach_Syscall_Descs; /// Max supported Mach syscall number. static const int Max_Mach_Syscall_Desc; /// Since negated values are used to identify Mach syscalls, the /// minimum (signed) valid syscall number is the negated max Mach /// syscall number. static const int Min_Syscall_Desc; /// Do the specified syscall. Just looks the call number up in /// the table and invokes the appropriate handler. static void doSyscall(int callnum, Process *process, ExecContext *xc) { if (callnum < Min_Syscall_Desc || callnum > Max_Syscall_Desc) { fatal("Syscall %d out of range\n", callnum); } SyscallDesc *desc = (callnum < 0) ? &machSyscallDescs[-callnum] : &syscallDescs[callnum]; desc->doSyscall(callnum, process, xc); } /// Indirect syscall invocation (call #0). static SyscallReturn indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { int new_callnum = xc->getSyscallArg(0); for (int i = 0; i < 5; ++i) xc->setSyscallArg(i, xc->getSyscallArg(i+1)); doSyscall(new_callnum, process, xc); return 0; }}; // class Tru64// open(2) flags translation tableOpenFlagTransTable Tru64::openFlagTable[] = {#ifdef _MSC_VER { Tru64::TGT_O_RDONLY, _O_RDONLY },
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -