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

📄 timing.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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.  * *//***************************************************************** * timing.c * * $Author: bosch $ * $Date: 1998/02/10 00:30:04 $ ****************************************************************/#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <math.h>#include <setjmp.h>#include <ctype.h>#include <assert.h>#include "cpu_interface.h"#include "statrecord.h"#include "statistics.h"#include "simutil.h"#include "sim_error.h"#include "tcl_init.h"#include "stack.h"#define CPUMASK     uint#define CPUNum ((CPUVec.CurrentCpuNum) ? CPUVec.CurrentCpuNum() : 0)/*#define TIMING_DEBUG*/typedef struct TimingTree  TimingTree;typedef struct TimingThread TimingThread;typedef struct TimingNode   TimingNode;struct TimingThread {   char   *name;   Stack  *stack;   uint64 compStart;   char   active;};struct TimingTree {   char *name;   uint numThreads;   Tcl_HashTable threads;   TimingThread  *currentThread[SIM_MAXCPUS];   StatRecordSwitch *selector;   TimingNode *root;};struct TimingNode {   char       *name;   Stats      *stats;   TimingNode *child;   TimingNode *sibling;   StatRecordBucket *bucket;     char       mutable;};static int CmdCreate(Tcl_Interp *interp, int argc, char *argv[]);static int CmdExit(Tcl_Interp *interp, int argc, char *argv[]);static int CmdDump(Tcl_Interp *interp, int argc, char *argv[]);static int CmdSwitch(Tcl_Interp *interp, int argc, char *argv[]);static int CmdTerminate(Tcl_Interp *interp, int argc, char *argv[]);static int CmdStart(Tcl_Interp *interp, int argc, char *argv[]);static int CmdVector(Tcl_Interp *interp, int argc, char *argv[]);static int CmdEnd(Tcl_Interp *interp, int argc, char *argv[]);static int CmdCurrent(Tcl_Interp *interp, int argc, char *argv[]);static int CmdStackList(Tcl_Interp *interp, int argc, char *argv[]);static int CmdFields(Tcl_Interp *interp, int argc, char *argv[]);static TimingTree *TreeCreate(char *TreeName);static TimingTree *TreeLookup(char *treeName);static void TreeDump(TimingTree *tree);static TimingThread *ThreadCreate(TimingTree *tree, char *threadName,                                  char *startStates[], int numStartStates);static TimingThread *ThreadLookup(TimingTree *tree, char *threadName);static void ThreadExit(TimingTree *tree, TimingThread *thread);static int ThreadStartPhase(TimingTree *tree, TimingThread *thread, char *phaseName,                            int mutable);static void ThreadEndPhase(TimingTree *tree, TimingThread *thread, char *phaseName);static void TimingStackList(Stack *stack);static TimingNode *NodeCreate(char *name);static TimingNode *NodeFind(TimingNode *parent, char *name);static void NodeZip(TimingTree *tree, TimingNode *src, TimingNode *dest);static void OverflowDebug(Tcl_Interp *interp, TimingThread *thread);static Tcl_HashTable trees;static tclcmd timingCmds[] = {{   "create",     3, CmdCreate,      " create treeName"},{   "exit",       3, CmdExit,        " exit treeName"},{   "dump",       3, CmdDump,        " dump treeName"},{   "switch",    -1, CmdSwitch,      " switch treeName threadName ?phase ...?"},{   "terminate",  4, CmdTerminate,   " terminate treeName threadName"},{   "start",     -1, CmdStart,       " start treeName phaseName ?threadName?"},{   "start?",    -1, CmdStart,       " start? treeName phaseName ?threadName?"},{   "vector",    -1, CmdVector,      " vector treeName phaseName ?threadName?"},{   "end",       -1, CmdEnd,         " end treeName phaseName ?threadName?"},{   "current",   -1, CmdCurrent,     " current treeName ?threadName?"},{   "dumpstack", -1, CmdStackList,   " dumpstack treeName ?threadName?"},{   "fields",     2, CmdFields,      " fields"},{   NULL,         0, NULL,           NULL}};/**************************************************************** * TimingInit ****************************************************************/void TimingInit(Tcl_Interp *interp){   Tcl_InitHashTable(&trees, TCL_STRING_KEYS);   Tcl_CreateCommand(interp, "timing", DispatchCmd, (ClientData)timingCmds,                      NULL);}/***************************************************************** * CmdCreate * * Create a new timing tree. This will be the level at which you  * limit timing to certain pid's. ****************************************************************/static int CmdCreate(Tcl_Interp *interp, int argc, char *argv[]){   char *treeName = argv[2];      if (TreeCreate(treeName) == NULL) {      Tcl_AppendResult(interp, "tree name already taken \"",                       treeName, "\"", NULL);      return TCL_ERROR;   }   return TCL_OK;}/***************************************************************** * CmdExit * * Assorted cleanup routines to get all of the timing stuff in order * before printing.  *****************************************************************/static int CmdExit(Tcl_Interp *interp, int argc, char *argv[]){   Tcl_HashEntry *entry;   Tcl_HashSearch search;   TimingTree  *tree;   char *treeName;      treeName  = argv[2];      if ((tree = TreeLookup(treeName)) == NULL) {      Tcl_AppendResult(interp, "no tree named \"", treeName, "\"", NULL);      return TCL_ERROR;   }   for (entry = Tcl_FirstHashEntry(&tree->threads, &search); entry;        entry = Tcl_NextHashEntry(&search)) {      ThreadExit(tree, (TimingThread *)Tcl_GetHashValue(entry));   }      return TCL_OK;}/***************************************************************** * CmdStart * * Entry point to a new phase... add it if it doesn't exist yet. * This is a "push". ****************************************************************/static int CmdStart(Tcl_Interp *interp, int argc, char *argv[]){   TimingTree *tree;   TimingThread *thread;   char *treeName;   char *phaseName;      if ((argc != 4) && (argc != 5)) {      Tcl_AppendResult(interp, "wrong number of arguments", NULL);      return TCL_ERROR;   }      treeName = argv[2];   phaseName = argv[3];   if ((tree = TreeLookup(treeName)) == NULL) {      Tcl_AppendResult(interp, "no tree named \"", treeName, "\"", NULL);      return TCL_ERROR;   }   if (argc == 5) {      thread = ThreadLookup(tree, argv[4]);      if (!thread) {         CPUWarning("TIMING: no thread named %s\n", argv[4]);         return TCL_OK;      }   } else {      thread = tree->currentThread[CPUNum];      if (!thread) {         Tcl_AppendResult(interp, "no current thread in \"", treeName, "\"", NULL);         return TCL_ERROR;      }   }   if (StackEmpty(thread->stack)) {      Tcl_AppendResult(interp, "cannot start phase on terminated thread", NULL);      return TCL_ERROR;   }      if (thread->active) {      if (ThreadStartPhase(tree, thread, phaseName, argv[1][5]) != TCL_OK) {	 OverflowDebug(interp, thread);         return TCL_ERROR;      }         } else {      ThreadEndPhase(tree, thread, "DESCHED");      if (ThreadStartPhase(tree, thread, phaseName, argv[1][5]) != TCL_OK) {         OverflowDebug(interp, thread);         return TCL_ERROR;      }            if (ThreadStartPhase(tree, thread, "DESCHED", 0) != TCL_OK) {         OverflowDebug(interp, thread);         return TCL_ERROR;      }   }#ifdef TIMING_DEBUG   CPUPrint("TIMING: Start thread %s\n", thread->name);   TimingStackList(thread->stack);#endif   return TCL_OK;}/***************************************************************** * CmdVector ****************************************************************/static int CmdVector(Tcl_Interp *interp, int argc, char *argv[]){   TimingTree *tree;   TimingThread *thread;   TimingNode *node;   char *treeName;   char *phaseName;      if ((argc != 4) && (argc != 5)) {      Tcl_AppendResult(interp, "wrong number of arguments", NULL);      return TCL_ERROR;   }      treeName = argv[2];   phaseName = argv[3];   if ((tree = TreeLookup(treeName)) == NULL) {      Tcl_AppendResult(interp, "no tree named \"", treeName, "\"", NULL);      return TCL_ERROR;   }   if (argc == 5) {      thread = ThreadLookup(tree, argv[4]);      if (!thread) {         CPUWarning("TIMING: no thread named %s\n", argv[4]);         return TCL_OK;      }   } else {      thread = tree->currentThread[CPUNum];      if (!thread) {         Tcl_AppendResult(interp, "no current thread in \"", treeName, "\"", NULL);         return TCL_ERROR;      }   }   if (StackEmpty(thread->stack)) {      Tcl_AppendResult(interp, "cannot vector phase on terminated thread", NULL);      return TCL_ERROR;   }      if (thread->active) {      node = UINT64_TO_PTR(StackIndex(thread->stack, 2));   } else {      node = UINT64_TO_PTR(StackIndex(thread->stack, 5));   }      ASSERT(node);   if (!node->mutable) {      CPUWarning("TIMING: CPU %d CYCLE %lld: node not mutable, tree: %s, node: %s\n",                  CPUNum, CPUVec.CycleCount(CPUNum), treeName, node->name);      TimingStackList(thread->stack);      return TCL_OK;   }   ASSERT(!node->sibling);      free(node->name);   node->name = SaveString(phaseName);   return TCL_OK;}/***************************************************************** * CmdEnd * * End of an existing phase. Print a warning if this ending phase * doesn't match the top of the stack. ****************************************************************/static int CmdEnd(Tcl_Interp *interp, int argc, char *argv[]){   char *treeName;   char *phaseName;   TimingTree *tree;   TimingThread *thread;      if ((argc != 4) && (argc != 5)) {      Tcl_AppendResult(interp, "wrong number of arguments", NULL);      return TCL_ERROR;   }      treeName  = argv[2];   phaseName = argv[3];      if ((tree = TreeLookup(treeName)) == NULL) {      Tcl_AppendResult(interp, "no tree named \"", treeName, "\"", NULL);      return TCL_ERROR;   }   if (argc == 5) {      thread = ThreadLookup(tree, argv[4]);      if (!thread) {         CPUWarning("TIMING: no thread named %s\n", argv[4]);         return TCL_OK;      }   } else {      thread = tree->currentThread[CPUNum];      if (!thread) {         Tcl_AppendResult(interp, "no current thread in \"", treeName, "\"", NULL);         return TCL_ERROR;      }   }   if (StackEmpty(thread->stack)) {      Tcl_AppendResult(interp, "cannot end phase on terminated thread", NULL);      return TCL_ERROR;   }      if (thread->active) {      ThreadEndPhase(tree, thread, phaseName);         } else {      ThreadEndPhase(tree, thread, "DESCHED");      ThreadEndPhase(tree, thread, phaseName);      ThreadStartPhase(tree, thread, "DESCHED", 0);   }#ifdef TIMING_DEBUG   CPUPrint("TIMING: End thread %s\n", thread->name);   TimingStackList(thread->stack);#endif   return TCL_OK;}/***************************************************************** * CmdCurrent * * Return the top phase on the stack ****************************************************************/static intCmdCurrent(Tcl_Interp *interp, int argc, char *argv[]){   TimingTree *tree;   TimingThread *thread;   TimingNode *node;   char *treeName;   if (argc !=3 && argc !=4) {       Tcl_AppendResult(interp,"wrong number of arguments",NULL);      return TCL_ERROR;   }   treeName  = argv[2];      if ((tree = TreeLookup(treeName)) == NULL) {      Tcl_AppendResult(interp, "no tree named \"", treeName, "\"", NULL);      return TCL_ERROR;   }   if (argc == 4) {      if (!(thread = ThreadLookup(tree, argv[3]))) {         Tcl_AppendResult(interp, "no thread named \"", argv[3], "\"", NULL);         return TCL_ERROR;      }   } else {      if (!(thread = tree->currentThread[CPUNum])) {         Tcl_AppendResult(interp, "no current thread", NULL);         return TCL_ERROR;      }      ASSERT(thread->active);   }   if (StackEmpty(thread->stack)) {      Tcl_AppendResult(interp, "cannot get current phase on terminated thread", NULL);      return TCL_ERROR;   }      if (thread->active) {      node = UINT64_TO_PTR(StackIndex(thread->stack, 2));   } else {      node = UINT64_TO_PTR(StackIndex(thread->stack, 5));   }      if (node) {      ASSERT(node->name);      Tcl_AppendResult(interp, node->name, NULL);   } else {      Tcl_AppendResult(interp, "", NULL);   }      return TCL_OK;}/***************************************************************** * CmdStackList * * Access from TCL to stacklist debugging command ****************************************************************/static intCmdStackList(Tcl_Interp *interp, int argc, char *argv[]){   TimingTree *tree;   TimingThread *thread;   char *treeName;   if (argc !=3 && argc !=4) {       Tcl_AppendResult(interp,"wrong number of arguments",NULL);      return TCL_ERROR;   }   treeName  = argv[2];      if ((tree = TreeLookup(treeName)) == NULL) {      Tcl_AppendResult(interp, "no tree named \"", treeName, "\"", NULL);      return TCL_ERROR;   }   if (argc == 4) {      if (!(thread = ThreadLookup(tree, argv[3]))) {         Tcl_AppendResult(interp, "no thread named \"", argv[3], "\"", NULL);         return TCL_ERROR;      }   } else {      if (!(thread = tree->currentThread[CPUNum])) {         Tcl_AppendResult(interp, "no current thread", NULL);         return TCL_ERROR;      }   }   TimingStackList(thread->stack);   return TCL_OK;}/***************************************************************** * CmdSwitch * * Move to another thread... create a stack for it if it doesn't * exist.  ****************************************************************/static int CmdSwitch(Tcl_Interp *interp, int argc, char *argv[]){   TimingTree *tree;   TimingThread *thread;   char *treeName;   char *threadName;   char **startState;   int  numStartStates;      if ((argc < 4)) {      Tcl_AppendResult(interp, "wrong # args: should be \"",                       argv[0], timingCmds[3].usage, "\"", NULL);      return TCL_ERROR;   }   treeName  = argv[2];   threadName = argv[3];   startState = &(argv[4]);   numStartStates = argc - 4;   if ((tree = TreeLookup(treeName)) == NULL) {      Tcl_AppendResult(interp, "no tree named \"", treeName, "\"", NULL);      return TCL_ERROR;   }   /* First, if this thread has not yet exited, then push DESCHED */   thread = tree->currentThread[CPUNum];   if (thread && !StackEmpty(thread->stack)) {      if (ThreadStartPhase(tree, thread, "DESCHED", 0) != TCL_OK) {         OverflowDebug(interp, thread);         return TCL_ERROR;      }   }   if (thread) {      thread->active = 0;   }      /* See if a stack for new thread exists... if not, create one */

⌨️ 快捷键说明

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