timestamp.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 438 行
C
438 行
/* * @(#)timestamp.c 1.11 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */#include "javavm/include/defs.h"#include "javavm/include/globals.h"#include "javavm/include/timestamp.h"#include "javavm/include/utils.h"#include "javavm/include/common_exceptions.h"#include "javavm/include/porting/time.h"#include "javavm/include/porting/doubleword.h"#include "javavm/include/porting/ansi/time.h"/* * This is a generic linked list implementation. It is used to store * the time-stamps records. */typedef struct ListType { struct ListNode* headNodePtr; struct ListNode* tailNodePtr; int numberOfElements;} List;typedef struct ListIteratorType{ struct ListNode* currentNodePtr;} ListIterator;typedef struct ListNode { void* dataPtr; struct ListNode* nextNodePtr;} ListNode;List* timeStampList = NULL;/* * P.S. The implementation of list if not multi-thread safe. * Caller of this should take care to lock the list if required. * List implemenation starts here! *//* * Initializes the list pointers. The list has two node pointers * one points to the head of the list and other is the end of * the list. Also keep a count on the number of elements in the * list. */static void listInit(List* list) { CVMassert(list != NULL); list->headNodePtr = NULL; list->tailNodePtr = NULL; list->numberOfElements = 0;}/* * Destroys the list and nodes. * Traverse the list and free the memory allocated by the * nodes and memory allocated by the data within the nodes. * This is done on the assumption that the contents of each * list node, passed through listAddLast() are still * malloc and supposed to be free'ed as we free the nodes. */static voidlistAndNodesDestroy(List* list){ ListNode* temp; while (list->headNodePtr != NULL) { CVMassert(list->numberOfElements > 0); CVMassert((list->numberOfElements != 1) || (list->headNodePtr == list->tailNodePtr)); temp = list->headNodePtr; list->headNodePtr = temp->nextNodePtr; temp->nextNodePtr = NULL; free(temp->dataPtr); temp->dataPtr = NULL; free(temp); list->numberOfElements--; } CVMassert(list->numberOfElements == 0); listInit(list);}/* * Inserts an element at the end of the list */static CVMBool listAddLast(CVMExecEnv* ee, List* list, void* newDataPtr) { ListNode* newNodePtr = (ListNode*) malloc(sizeof(ListNode)); if (newNodePtr == NULL) { CVMthrowOutOfMemoryError(ee, NULL); return CVM_FALSE; } newNodePtr->dataPtr = newDataPtr; newNodePtr->nextNodePtr = NULL; if (list->headNodePtr == NULL) { CVMassert(list->tailNodePtr == NULL); CVMassert(list->numberOfElements == 0); list->headNodePtr = newNodePtr; } else { CVMassert(list->tailNodePtr != NULL); CVMassert(list->numberOfElements > 0); list->tailNodePtr->nextNodePtr = newNodePtr; } list->tailNodePtr = newNodePtr; list->numberOfElements++; return CVM_TRUE; } /* * Returns the pointer to the list itereator */static ListIterator* listGetIterator(CVMExecEnv* ee, List* list) { ListIterator* iterator = (ListIterator*) malloc(sizeof(ListIterator)); if (iterator == NULL) { CVMthrowOutOfMemoryError(ee, NULL); return NULL; } CVMassert(list != NULL); iterator->currentNodePtr = list->headNodePtr; return iterator;}/* * Iterates the list from the beginning towards the end. * Returns the pointer to the data element for the current * node and resets the pointer to the current node. */static void*listNext(ListIterator* iterator) { void* retValPtr; CVMassert(iterator != NULL); if (iterator->currentNodePtr == NULL) { return NULL; } retValPtr = iterator->currentNodePtr->dataPtr; iterator->currentNodePtr = iterator->currentNodePtr->nextNodePtr; return retValPtr;}/* Utility functions to record the time stamp in the beginning * and end and print the recorded time stamps *//* * this struct keeps the timestamps records and the corresponding locations */typedef struct timeStampRecords { char* loc; int position; int cpuTime; /* time in milli-second */ long wallClockTime; /* time in milli-second */} timeStampRecords;/* This function records the CPU time at the location (str), * passed an argument and updates the timestampList. * To prevent the timestampList to be corrputed by another * thread we put the lock on the list, and after the list is * updated, we unlock the list. */static long getWallClkTime();static CVMBooltimeStampRecord(CVMExecEnv* ee, const char* str, int position, long wallClkTime){ timeStampRecords* valPtr; valPtr = (timeStampRecords*) malloc(sizeof(timeStampRecords)); if (valPtr == NULL) { CVMthrowOutOfMemoryError(ee, NULL); return CVM_FALSE; } /* if the location string passes is null then we will * keep the timeStampRecords->loc as null and while printing the * the time stamps, will put auto count. */ if (str != NULL) { valPtr->loc = strdup(str); if (valPtr->loc == NULL) { free(valPtr); return CVM_FALSE; } } else { valPtr->loc = NULL; } valPtr->position = position; valPtr->cpuTime = clock(); /* convert the time from micro-sec to milli-sec */ valPtr->cpuTime /= 1000; valPtr->wallClockTime = wallClkTime; CVMsysMutexLock(ee, &CVMglobals.timestampListLock); /* insert the timeStamp record in the list */ CVMassert(timeStampList != NULL); if (!listAddLast(ee, timeStampList, valPtr)) { CVMsysMutexUnlock(ee, &CVMglobals.timestampListLock); /* insertion in the list failed... */ free(valPtr->loc); free(valPtr); return CVM_FALSE; } CVMsysMutexUnlock(ee, &CVMglobals.timestampListLock); return CVM_TRUE;}/* this function initializes the timestampList and * is called once at the beginning of VM creation. */static CVMBooltimeStampStart(CVMExecEnv* ee, long wallClockTime){ CVMassert(timeStampList == NULL); timeStampList = (List*) malloc(sizeof(List)); if (timeStampList == NULL) { CVMthrowOutOfMemoryError(ee, NULL); return CVM_FALSE; } listInit(timeStampList); return timeStampRecord(ee, "Starting", -1, wallClockTime);}/* This function prints the timeStamp records. Iterates the * timestampList and prints the timeStampRecords. */static CVMBooltimeStampPrint(CVMExecEnv* ee){ ListIterator* fowardIterator; timeStampRecords* value; int prevTime = 0; long prevWallclockTime = 0; int locationCount = 0; fprintf(stdout, "------------------------------------------------" "-------------------\n" "Location\tCPU Time (ms)\tCPU Time (ms)\tClock Time (ms)" "\tClock time\n" " \tused by the \tdiff between \telapsed " "\tdiff (ms) \n" " \tprogram \tlocations\n"); CVMsysMutexLock(ee, &CVMglobals.timestampListLock); fowardIterator = listGetIterator(ee, timeStampList); if (fowardIterator == NULL) { CVMsysMutexUnlock(ee, &CVMglobals.timestampListLock); return CVM_FALSE; } while ((value = (timeStampRecords*)listNext(fowardIterator)) != NULL) { if ((value->loc == NULL) && (value->position == -1)) { fprintf(stdout, "auto# %d \t%d \t\t%d \t\t%ld \t\t%ld\n", ++locationCount, (value->cpuTime), (value->cpuTime) - prevTime, (value->wallClockTime), (value->wallClockTime) - prevWallclockTime); } else if (value->position != -1) { fprintf(stdout, "%10d \t%d \t\t%d \t\t%ld \t\t%ld\n", value->position, (value->cpuTime), (value->cpuTime) - prevTime, (value->wallClockTime), (value->wallClockTime) - prevWallclockTime); } else { fprintf(stdout, "%s \t%d \t\t%d \t\t%ld \t\t%ld\n", value->loc, (value->cpuTime), (value->cpuTime)- prevTime, (value->wallClockTime), (value->wallClockTime) - prevWallclockTime); } prevTime = value->cpuTime; prevWallclockTime = value->wallClockTime; } fprintf(stdout, "----------------------------------------------------" "---------------\n"); free(fowardIterator); CVMsysMutexUnlock(ee, &CVMglobals.timestampListLock); return CVM_TRUE;}/* This function must be called while destroying the VM * because it does the clean up of the memory allocated * during these operations. */static CVMBooltimeStampFinishup(CVMExecEnv* ee, long wallClockTime){ if (!timeStampRecord(ee, "Terminated", -1, wallClockTime)) { return CVM_FALSE; } if (CVMglobals.timeStampEnabled) { fprintf(stdout, "Time Stamps data at VM termination-\n"); if (!timeStampPrint(ee)) { return CVM_FALSE; } } /* Free up location records before feeing up list */ { ListIterator* fowardIterator; timeStampRecords* value; CVMsysMutexLock(ee, &CVMglobals.timestampListLock); fowardIterator = listGetIterator(ee, timeStampList); if (fowardIterator != NULL) { while ((value = (timeStampRecords*)listNext(fowardIterator)) != NULL) { if (value->loc != NULL) { free(value->loc); value->loc = NULL; } } free(fowardIterator); } CVMsysMutexUnlock(ee, &CVMglobals.timestampListLock); } listAndNodesDestroy(timeStampList); free(timeStampList); timeStampList = NULL; return CVM_TRUE;}/* * get time elapsed since first wall clock time has been recorded */static longgetWallClkTime() { /* Here we assume that 'long' is big enough to keep wall-clock * time for a typical execution of an application */ return CVMlong2Int((CVMlongSub(CVMtimeMillis(), CVMglobals.firstWallclockTime)));}/* * Public functions *//* * Initializes the 'firstWallclockTime' of CVMglobals * with -1 */voidCVMtimeStampWallClkInit(){ /* the '-1' value for firstWallclockTime indicates that * it has not been initialized yet */ CVMglobals.firstWallclockTime = CVMint2Long(-1);}/* * Time stamp record after VM initialization */CVMBoolCVMtimeStampStart(CVMExecEnv* ee) { CVMassert(CVMlongEq(CVMglobals.firstWallclockTime, CVMint2Long(-1))); CVMglobals.firstWallclockTime = CVMtimeMillis(); return timeStampStart(ee, 0);}/* * Time stamp record at VM termination */CVMBoolCVMtimeStampFinishup(CVMExecEnv* ee) { return timeStampFinishup(ee, getWallClkTime());}/* * This is a public function, for time stamp recording. * The loc and pos identifies the location * to record the time. You can pass this loc as NULL also. * the pos can not be -1. */CVMBool CVMtimeStampRecord(CVMExecEnv* ee, const char* loc, int pos) { if (CVMglobals.timeStampEnabled) { return timeStampRecord(ee, loc, pos, getWallClkTime()); } else { return CVM_FALSE; }}/* * This function prints the time stamp records. */CVMBoolCVMtimeStampPrint(CVMExecEnv* ee) { if (CVMglobals.timeStampEnabled) { return timeStampPrint(ee); } else { return CVM_FALSE; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?