hvdebtim.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 649 行 · 第 1/2 页

CPP
649
字号
/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: hvdebtim.cpp,v 1.2.40.1 2004/07/09 01:56:06 hubbe Exp $
 * 
 * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
 * 
 * The contents of this file, and the files included with this file,
 * are subject to the current version of the RealNetworks Public
 * Source License (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (the "RCSL") available at
 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
 * will apply. You may also obtain the license terms directly from
 * RealNetworks.  You may not use this file except in compliance with
 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
 * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
 * the rights, obligations and limitations governing use of the
 * contents of the file.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 * 
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the
 * portions it created.
 * 
 * This file, and the files included with this file, is distributed
 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
 * ENJOYMENT OR NON-INFRINGEMENT.
 * 
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 * 
 * Contributor(s):
 * 
 * ***** END LICENSE BLOCK ***** */

/////////////////////////////////////////////////////////////////////////////
// CVvDebugTimer --
/* How to use it: 

in C (here local creation of struct)

#include "hvdebtim.h"

struct CVvDebugTimer * pDebTim = newCVvDebugTimer();

ResetTime(pDebTim);//reset accu
StartTime(pDebTim);


Debugee();

StopAndAccuTime(pDebTim);
//AverageAndOutputAccuTime(pDebTim, "Resamp@22 kHz", 1);
OutputAccuTime(pDebTim, "Resamp@22 kHz", 1);




in C++:

#include "hvdebtim.h"

CVvDebugTimer DebTim01;
CVvDebugTimer DebTim02;
CVvDebugTimer DebTim03;

	DebTim01.StartTime();

	Debugee();
	
	DebTim01.StopAndAccuTime();

	//DebTim01.AverageAndOutputAccuTime("VvDecode", 1);
	DebTim01.OutputAccuTime("VvDecode  ", 1);
	DebTim01.ResetTime();//reset accu


*/


#include <stdio.h>
#include "hvutils.h"
#include "hvdebtim.h"
#include "hxstrutl.h"

/********************************/
/* time helper functions		*/
extern "C" {

#if TIMERTYPE!=WIN31_TIME
static LARGE_INTEGER	liFrequency = {0};
static S32				nFrequencyValid = FREQUENCY_NOTMEASURED;
#endif

/********************************/
void VvGetAbsCpuClocks(__int64 *time)
{
//	_asm RdTsc	;	Get count of cycles into EDX: EAX
_asm {
	_emit 0x0F	//0F 31 is RDTSC opcode: Reads Pentium CPU clock (costs only 6 clocks at Ring 0, 11 at Ring 3)
	_emit 0x31	//  into EDX:EAX
	mov ebx, time
	mov [ebx], eax;//Intel Little Endian
	mov [ebx+4], edx
	}
}

/********************************/
void VvZeroAbsCpuClocks(void)	//Force Pentium clock to 0  (Can be done at Ring 0 only)
{
	_asm{
		mov ECX, 0x10	//Machine-specific register 10h is the Time Stamp Counter
		xor EAX,EAX		//Timestamp we want to set goes
		xor EDX,EDX		//  into EDX:EAX
		_emit 0x0F	    //WRMSR opcode is 0F 30
		_emit 0x30
	}
	
}
/********************************/
#define TOLERANCE		1		// Number of MHz to allow
								//   samplings to deviate from
								//   average of samplings.
								//   Initially set to 2.
#define ROUND_THRESHOLD		6


U32	 GetRDTSCCpuSpeed()
{
	unsigned long in_cycles=0;	// Internal clock cycles during
								//   test
	unsigned long ex_ticks=0;		// Microseconds elapsed during 
								//   test
	unsigned long raw_freq=0;		// Raw frequency of CPU in MHz
	unsigned long norm_freq=0;	// Normalized frequency of CPU

	LARGE_INTEGER t0,t1;			// Variables for High-
									//   Resolution Performance
									//   Counter reads

	unsigned long  freq  =0;			// Most current frequ. calculation
	unsigned long  freq2 =0;			// 2nd most current frequ. calc.
	unsigned long  freq3 =0;			// 3rd most current frequ. calc.
	
	unsigned long  total;			// Sum of previous three frequency
							//   calculations

	int tries=0;			// Number of times a calculation has
							//   been made on this call to 
							//   cpuspeed

	unsigned long   total_cycles=0, cycles;	// Clock cycles elapsed 
									//   during test
	
	unsigned long   stamp0, stamp1;			// Time Stamp Variable 
									//   for beginning and end 
									//   of test

	unsigned long   total_ticks=0, ticks;	// Microseconds elapsed 
									//   during test
	
	LARGE_INTEGER count_freq;		// High Resolution 
									//   Performance Counter 
									//   frequency

#ifdef WIN32
	int iPriority;
	HANDLE hThread = GetCurrentThread();
#endif // WIN32;


	if ( !QueryPerformanceFrequency ( &count_freq ) ) 
		return raw_freq;//return 0
	
	// On processors supporting the Read 
	//   Time Stamp opcode, compare elapsed
	//   time on the High-Resolution Counter
	//   with elapsed cycles on the Time 
	//   Stamp Register.
	
	do {			// This do loop runs up to 20 times or
	   				//   until the average of the previous 
	   				//   three calculated frequencies is 
	   				//   within 1 MHz of each of the 
	   				//   individual calculated frequencies. 
					//   This resampling increases the 
					//   accuracy of the results since
					//   outside factors could affect this
					//   calculation
			
		tries++;		// Increment number of times sampled
						//   on this call to cpuspeed
			
		freq3 = freq2;	// Shift frequencies back to make
		freq2 = freq;	//   room for new frequency 
						//   measurement

    	QueryPerformanceCounter(&t0);	
    					// Get high-resolution performance 
    					//   counter time
			
		t1.LowPart = t0.LowPart;		// Set Initial time
		t1.HighPart = t0.HighPart;

#ifdef WIN32
		iPriority = GetThreadPriority(hThread);
		if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )	{
			SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
		}
#endif // WIN32

   		while ( (unsigned long)t1.LowPart - (unsigned long)t0.LowPart<50) {	  
   						// Loop until 50 ticks have 
   						//   passed	since last read of hi-
						//	 res counter. This accounts for
						//   overhead later.

			QueryPerformanceCounter(&t1);

		__asm {
			_emit 0x0F	//0F 31 is RDTSC opcode: Reads Pentium CPU clock (costs only 6 clocks at Ring 0, 11 at Ring 3)
			_emit 0x31	//  into EDX:EAX
			MOV stamp0, EAX
			}
		}
			
			
		t0.LowPart = t1.LowPart;		// Reset Initial 
		t0.HighPart = t1.HighPart;		//   Time

   		while ((unsigned long)t1.LowPart-(unsigned long)t0.LowPart<1000 ) {
   						// Loop until 1000 ticks have 
   						//   passed	since last read of hi-
   						//   res counter. This allows for
						//   elapsed time for sampling.
   			
				
   			QueryPerformanceCounter(&t1);
   			

		__asm {
			_emit 0x0F	//0F 31 is RDTSC opcode: Reads Pentium CPU clock (costs only 6 clocks at Ring 0, 11 at Ring 3)
			_emit 0x31	//  into EDX:EAX
			MOV stamp1, EAX
			}
		}

			

#ifdef WIN32
		// Reset priority
		if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )	{
			SetThreadPriority(hThread, iPriority);
		}
#endif // WIN32

       	cycles = stamp1 - stamp0;	// Number of internal 
        							//   clock cycles is 
        							//   difference between 
        							//   two time stamp 
        							//   readings.

    	ticks = (unsigned long) t1.LowPart - (unsigned long) t0.LowPart;	
								// Number of external ticks is
								//   difference between two
								//   hi-res counter reads.
	

		// Note that some seemingly arbitrary mulitplies and
		//   divides are done below. This is to maintain a 
		//   high level of precision without truncating the 
		//   most significant data. According to what value 
		//   ITERATIIONS is set to, these multiplies and
		//   divides might need to be shifted for optimal
		//   precision.

		ticks = ticks * 100000;	
							// Convert ticks to hundred
							//   thousandths of a tick
			
		ticks = ticks / ( count_freq.LowPart/10 );		
							// Hundred Thousandths of a 
							//   Ticks / ( 10 ticks/second )
							//   = microseconds (us)

		total_ticks += ticks;
		total_cycles += cycles;

		if ( ticks%count_freq.LowPart > count_freq.LowPart/2 )
			ticks++;			// Round up if necessary
			
		freq = cycles/ticks;	// Cycles / us  = MHz
        										
     	if ( cycles%ticks > ticks/2 )
       		freq++;				// Round up if necessary
          	
		total = ( freq + freq2 + freq3 );
							// Total last three frequency 
							//   calculations

	} while ( (tries < 3 ) || 		
	          (tries < 20)&&
	          ((abs(3 * freq -total) > 3*TOLERANCE )||
	           (abs(3 * freq2-total) > 3*TOLERANCE )||
	           (abs(3 * freq3-total) > 3*TOLERANCE )));	
					// Compare last three calculations to 
	          		//   average of last three calculations.		

	// Try one more significant digit.
	freq3 = ( total_cycles * 10 ) / total_ticks;
	freq2 = ( total_cycles * 100 ) / total_ticks;

⌨️ 快捷键说明

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