⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kernel_stats-irix5.3.tcl

📁 一个用在mips体系结构中的操作系统
💻 TCL
字号:
## Copyright (C) 1996-1998 by the Board of Trustees#    of Leland Stanford Junior University.# # This file is part of the SimOS distribution. # See LICENSE file for terms of the license. ### ## kernel_stats.tcl##timing create kstatslog [timing fields]###### statistics logging###annotation set simos exit {    timing exit kstats    log [timing dump kstats]}annotation set simos sigusr {    log [timing dump kstats]}###### thread naming### In Hive there are multiple copies of each pid so we### must differentiate by cell number###if [info exists RUNNING_HIVE] {    proc ktname {} {        global CELL PID CPU        return ${CELL}_$PID($CPU)    }    proc pid2ktname {pid} {        global CELL        return ${CELL}_$pid    }} elseif { $PARAM(MACHINE.Count) == 1 } {    proc ktname {} {        global PID CPU		return $PID($CPU)    }    proc pid2ktname {pid} {		return $pid    }} else {    proc ktname {} {        global M PID CPU       	return $M($CPU)_$PID($CPU)    }    proc pid2ktname {pid} {        global M CPU       	return $M($CPU)_$pid    }}###### thread control###proc kstatsSwitch args {    global PROCESS CELL RUNNING_HIVE CYCLES kstatsThread M CPU PARAM    if [info exists RUNNING_HIVE] {        eval timing switch kstats [ktname] cell$CELL $args	} elseif { $PARAM(MACHINE.Count) == 1 } {        eval timing switch kstats [ktname] $args    } else {        eval timing switch kstats [ktname] machine$M($CPU) $args    }    if ![info exists kstatsThread([ktname])] {        set kstatsThread([ktname]) "runq"    } else {        timing end kstats $kstatsThread([ktname])    }}annotation set simos enter {    if [inUserMode] {        kstatsSwitch     } elseif {$PROCESS($CPU) == "boot"} {        kstatsSwitch bootproc    } elseif {$PROCESS($CPU) == "idle"} {        kstatsSwitch idleproc idle    } else {        kstatsSwitch startup    }}annotation set osEvent switchOut {    # has thread still active (i.e. has not exited)    if [info exists kstatsThread([ktname])] {        if {[timing current kstats] == "ROOT"} {             console "KSTATS: CPU $CPU CYCLE $CYCLES: bad DESCHED pid $PID($CPU)\n"        }                timing start kstats $kstatsThread([ktname])    }}set kernelThreadNames(vhand) 1set kernelThreadNames(bdflush) 1set kernelThreadNames(pdflush) 1set kernelThreadNames(sched) 1if [info exists RUNNING_HIVE] {    set kernelThreadNames(dspatch) 1    set kernelThreadNames(PING) 1    set kernelThreadNames(LSET) 1    set kernelThreadNames(RECV) 1    set kernelThreadNames(RBOT) 1    set kernelThreadNames(BALANCE) 1}proc kernelThreadState {proc} {    global kernelThreadNames    if {[string range $proc 0 4] == "hrpc_"} {        return hrpcServer    } elseif [info exists kernelThreadNames($proc)] {        return $proc    } else {        return fork    }}annotation set osEvent switchIn {    if {$PROCESS($CPU) == "idle"} {        kstatsSwitch idleproc    } elseif {$PROCESS($CPU) == "runq"} {        kstatsSwitch runqproc    } else {        kstatsSwitch [kernelThreadState $PROCESS($CPU)]    }}annotation set osEvent procexit {    timing terminate kstats [ktname]    unset kstatsThread([ktname])}###### kernel services###annotation set utlb {    timing start kstats utlb}annotation set exc {    if {[timing current kstats] == "utlb"} {        timing end kstats utlb    }    set exc [expr ($cause >> 2) & 0x1F]    if {$exc == 0} {        timing start? kstats intrdisp    } elseif {$exc == 8} {        timing start kstats syscall([expr $v0])    } else {        timing start? kstats exc($exc)    }}annotation set inst rfe {    set current [timing current kstats]    if {$current != "ROOT"} {        timing end kstats $current    } else {        console "KSTATS: CPU $CPU CYCLE $CYCLES: bad rfe pid $PID($CPU)\n"    }}annotation set osEvent startIdle {    timing start kstats idle}annotation set osEvent endIdle {    timing end kstats idle}annotation set osEvent startSync {    timing start kstats sync}annotation set osEvent endSync {    timing end kstats sync}#### rpc servers##if [info exists RUNNING_HIVE] {    annotation set pc kernel::registerQMethodAnn:START {        timing start kstats qmethod($a0)    }    annotation set pc kernel:hrpc.c:1041 {        timing end kstats [timing current kstats]    }    for {set i 0} {$i < $PARAM(CPU.Count)} {incr i} {        set inFMethod($i) 0    }    annotation set pc kernel::registerFMethodAnn:START {        timing start kstats fmethod($a0)        set inFMethod($CPU) 1    }    annotation set pc kernel:hrpc.c:hrpcRequestInterrupt:END {        if {$inFMethod($CPU)} {            timing end kstats [timing current kstats]            set inFMethod($CPU) 0        }    }}#### page faults##annotation set pc kernel::pfault:START {    timing vector kstats pfault}annotation set pc kernel::page_copy:START {    if {[timing current kstats] == "pfault"} {        timing vector kstats COW_fault    }}annotation set pc kernel::vfault:START {    timing vector kstats vfault}annotation set pc kernel::page_zero:START {    if {[timing current kstats] == "vfault"} {        timing vector kstats demand_zero    }}#### interrutps### simscsi_intr, if_etintr, and du_poll all share the interrupt# dispatch path. There are two ways to charge the overhead to# routines. 1) We can treat the routines as interrupt handlers in the# normal way. This leads to simscsi_intr getting charged all the# dispatch overhead and du_poll getting charged all the return# overhead. This is what is currently done. 2) We could have a# level3_intr, do normal start, ends on simscsi_intr, if_etintr, and# du_poll, and then divide the overhead of level3_intr among the 3 as# a post processing step. Fortunately the overhead is small enough# where we do not really care.set intr(timein)         1set intr(netintr)        2set intr(simscsi_intr)   3set intr(if_etintr)      3set intr(du_poll)        3set intr(level4_intr)    4set intr(clock)          5set intr(cpuintr)        6set intr(ackkgclock)     7set intr(buserror_intr)  8if [info exists RUNNING_HIVE] {    set intr(hrpcRequestInterrupt)        3}foreach i [array names intr] {    annotation set pc kernel:SIMMP.c:$i:START "dointr $i"}proc dointr {name} {    global intr CPU CYCLES    set current [timing current kstats]     if {$current == "intrdisp"} {        timing vector kstats $name    } elseif [info exists intr($current)] {        timing end kstats $current        timing start kstats $name    } else {        console "KSTATS: CPU $CPU CYCLE $CYCLES: bad intr: $name current: $current\n"    }}#### Latency Components### kstatsThread is an array indexed by pid that holds the reason that# the thread is getting descheduled. There are two ways a thread could# get descheduled. 1) the thread could get pre-empted and put on the# runq. In this case we do nothing and it goes down as DESCHED. 2) The# thread could get put on a semaphore. In this case we try to# determine further the reason its on the semaphore. Currently we only# deferentiate IO. All other semaphores are put under semawait.annotation set pc kernel:sema.c:semaaddproc:START {    if {$kstatsThread([ktname]) == "runq"} {        set kstatsThread([ktname]) semawait    }}# The if check in the following that looks at timing current# responds to the following race condition:## thread A does a psema.  This calls semaaddproc above.# Normally next event is that thread A calls swtch, causing# an osEvent switchOut which does timing start semawait.## However, it is possible for an interrupt to occur between the# semaaddproc and the call to swtch(), during which the interrupt# handler can do a semarmproc or a semadq.## We can tell if this has happened because the timing current value# will show that we have not yet made it to semawait or diskIO.# Appropriate response in terms of stats is to change kstatsThread# so the switchOut will change to runq (ready to run) rather than# semawait or diskIO.annotation set pc kernel:sema.c:semarmproc:END {    set pid [symbol read "kernel:proc.h:((proc_t*)$a1)->p_pid"]    set kname [pid2ktname $pid]    if {[info exists kstatsThread($kname)] && $v0 && ($pid != $PID($CPU))} {        if {[timing current kstats $kname] == $kstatsThread($kname)} {            timing end kstats $kstatsThread($kname) $kname            timing start kstats runq $kname        } else {            log "$CYCLES semarmproc special case: thread $kname\n"            timing dumpstack kstats $kname            log "State after desched will be \"runq\" rather than \"$kstatsThread($kname)\"\n"        }        set kstatsThread($kname) "runq"    }}annotation set pc kernel:sema.c:semadq:END {    set pid [symbol read "kernel:proc.h:((proc_t*)$v0)->p_pid"]    set kname [pid2ktname $pid]    if {[info exists kstatsThread($kname)] && ($pid != $PID($CPU))} {        if {[timing current kstats $kname] == $kstatsThread($kname)} {            timing end kstats $kstatsThread($kname) $kname            timing start kstats runq $kname        } else {            log "$CYCLES semarmproc special case: thread $kname\n"            timing dumpstack kstats $kname            log "State after desched will be \"runq\" rather than \"$kstatsThread($kname)\"\n"        }        set kstatsThread($kname) "runq"    }}annotation set pc kernel:simscsi.c:simscsi_command:START {    set kstatsThread([ktname]) diskIO}if [info exists RUNNING_HIVE] {    annotation set pc kernel:hrpc.c:1196 {        set kstatsThread([ktname]) queuedRPC    }    annotation set pc kernel:hrpc.c:hrpcFastInvokeINTERN:START {        timing start kstats fastRPC    }    annotation set pc kernel:hrpc.c:hrpcFastInvokeINTERN:block {        set kstatsThread([ktname]) fastRPCblock    }    annotation set pc kernel:hrpc.c:hrpcFastInvokeINTERN:END {        timing end kstats fastRPC    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -