os-irix5.3.tcl 7.57 KB
#
# 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. 
#

###
### This file is responsible for raising OS level annotations and tracking
### the current process.
###
###

####
#### init this module
####

if [info exists RUNNING_HIVE] {
    annotation type osEvent enum {
        startUser   endUser
        startKernel endKernel
        startIdle   endIdle
        startSync   endSync
        switchIn    switchOut
        procstart   procexit   procexec
        startRpc    endRpc
    }
} else {
    annotation type osEvent enum {
        startUser   endUser
        startKernel endKernel
        startIdle   endIdle
        startSync   endSync
        switchIn    switchOut
        procstart   procexit   procexec
    }
}

if [info exists R4000_KERNEL] {
    proc inUserMode {} {
        global sr
        expr !($sr & 0x4) && !($sr &0x2) && (($sr & 0x18) == 0x10)
    }

} else {
    proc inUserMode {} {
        global sr
        expr ($sr & 0x02) != 0
    }
}


####
#### the annotations 
####

annotation set pc kernel::_assfail:START {
        debug
}

##
## process and idle tracking
##

annotation set simos enter {
    if [catch {symbol read kernel::$private.p_curproc}] {
        # booting
        set PROCESS($CPU) "boot"
        set PID($CPU) boot$CPU
        
    } elseif {(([hex $pc] >= [symbol read kernel::idle:START])
               && ([hex $pc] <= ([symbol read kernel::idle:END] + 4)))
              || ((![catch {symbol read kernel::checkRunq:START}]) && 
                  ([hex $pc] >= [symbol read kernel::checkRunq:START])
                  && ([hex $pc] <= ([symbol read kernel::checkRunq:END] + 4)))} {
        # idle
        set PROCESS($CPU) "idle"
        set PID($CPU) idle$CPU
        
    } elseif {[symbol read kernel::$u.u_procp->p_sonproc] == $MCPU($CPU)} {
        set PROCESS($CPU) [symbol read kernel::$u.u_comm]
        set PID($CPU) [symbol read kernel::$u.u_procp->p_pid]    

    } else {
        set PROCESS($CPU) "runq"
        set PID($CPU) "runq$CPU"
    }
}

proc newproc {pid process} {
    global CPU PROCESS PID
    annotation exec osEvent switchOut
    set PROCESS($CPU) $process
    set PID($CPU) $pid
    annotation exec osEvent switchIn
}

annotation set pc kernel::idle:START {
    newproc idle$CPU "idle"
    annotation exec osEvent startIdle
}

annotation set pc kernel::idle:END {
    if {$PROCESS($CPU) != "idle"} {
        # this can happen when we take an interrupt on idle end
        console "OS.TCL: ignoring end idle when process != idle $CYCLES\n"
    } else {
        annotation exec osEvent endIdle
        newproc runq$CPU "runq"
    }
}

annotation set pc kernel::swtch:START {
    newproc runq$CPU "runq"
}

annotation set pc kernel::swtch:END {
    newproc [symbol read kernel::$u.u_procp->p_pid] [symbol read kernel::$u.u_comm]
}

annotation set pc kernel::pswtch:START {
    annotation exec osEvent procexit
    newproc runq$CPU "runq"
}

annotation set pc kernel:fork.c:procdup:END {
    set pid [symbol read kernel::$u.u_procp->p_pid]
    if {$pid != $PID($CPU)} {
        # child process of the fork
        newproc $pid [symbol read kernel::$u.u_comm]
        annotation exec osEvent procstart
    }
}

annotation set pc kernel::exece:END {
    annotation exec osEvent switchOut
    set PROCESS($CPU) [symbol read kernel::$u.u_comm]
    console "EXEC of $PROCESS($CPU)\n"
    annotation exec osEvent procexec
    annotation exec osEvent switchIn
}

if {$detailLevel >= 2} {

    ##
    ## kernel - user transitions
    ##

    set MAX_CPUS 256

    for {set i 0} {$i < $MAX_CPUS} {incr i} {
        set utlb($i) 0
    }
    
    annotation set utlb {
        set utlb($CPU) 1
        if {!($epc & $K0BASE)} {
            annotation exec osEvent endUser
        }
        annotation exec osEvent startKernel
    }
    
    annotation set exc {
        if {!$utlb($CPU)} {
            if {!($epc & $K0BASE)} {
                annotation exec osEvent endUser
            }
            annotation exec osEvent startKernel
        }
        set utlb($CPU) 0
    }
        
    annotation set inst rfe {
        set utlb($CPU) 0
        annotation exec osEvent endKernel
        if [inUserMode] {
            annotation exec osEvent startUser
        }
    }
        

    ##
    ## synchronization stuff
    ##

    if ![catch {symbol read kernel::netisr_init} msg] {

            # MP kernel
            log "INFO: IRIX is multiprocessor\n"
            
            annotation set pc kernel::io_splock:START {
                annotation exec osEvent startSync
            }
            
            if [catch {symbol read kernel::io_splock:ann_splock_gotit}] {
                annotation set pc kernel::io_splock:END {
                    annotation exec osEvent endSync
                }
            } else {
                annotation set pc kernel::io_splock:ann_splock_gotit {
                    annotation exec osEvent endSync
                }
            }
            
            annotation set pc kernel::spsemahi:START {
                annotation exec osEvent startSync
            }
            
            annotation set pc kernel::spsemahi:ann_spsemahi_gotit {
                annotation exec osEvent endSync
            }
            
            annotation set pc kernel::svsema:START {
                annotation exec osEvent startSync
            }
            
            annotation set pc kernel::svsema:END {
                annotation exec osEvent endSync
            }
            
            annotation set pc kernel::svsemax:START {
                annotation exec osEvent startSync
            }
            
            annotation set pc kernel::svsemax:END {
                annotation exec osEvent endSync
            }
            
            annotation set pc kernel::io_splockspl:START {
                annotation exec osEvent startSync
            }
            
            annotation set pc kernel::io_splockspl:ann_splockspl_gotit {
                annotation exec osEvent endSync
            }
            
            annotation set pc kernel::io_spunlockspl:START {
                annotation exec osEvent startSync
            }
            
            annotation set pc kernel::io_spunlockspl:END {
                annotation exec osEvent endSync
            }
            
            annotation set pc kernel::_trylock:START {
                annotation exec osEvent startSync
            }
            
            annotation set pc kernel::_trylock:ann_trylock_gotit {
                annotation exec osEvent endSync
            }
            
            annotation set pc kernel::spsema:START {
                annotation exec osEvent startSync
            }
            
            annotation set pc kernel::spsema:END {
                annotation exec osEvent endSync
            }
        } else {
            log "INFO: IRIX is uniprocessor\n"
	}

    if [info exists RUNNING_HIVE] {

        for {set cpu 0} {$cpu<$PARAM(CPU.Count)} {incr cpu} {
            set RPCWAIT($cpu) 0
        }

        annotation set pc kernel:hrpc.c:hrpcFastInvokeINTERN:receive {
            set RPCWAIT($CPU) 1
            annotation exec osEvent startRpc
        }

        annotation set pc kernel:hrpc.c:hrpcFastInvokeINTERN:block {
            if {$RPCWAIT($CPU)} {
                annotation exec osEvent endRpc
                set RPCWAIT($CPU) 0
            }
        }

        annotation set pc kernel:hrpc.c:hrpcFastInvokeINTERN:END {
            if {$RPCWAIT($CPU)} {
                annotation exec osEvent endRpc
                set RPCWAIT($CPU) 0
            }
        }
    }
}