time_calls.h

来自「Ubuntu packages of security software。 相」· C头文件 代码 · 共 438 行

H
438
字号
/* * Copyright (c) 2001 *	Politecnico di Torino.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the Politecnico * di Torino, and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#ifndef _time_calls#define _time_calls#ifdef WIN_NT_DRIVER#include "debug.h"#include "ndis.h"#define	DEFAULT_TIMESTAMPMODE	0#define TIMESTAMPMODE_SINGLE_SYNCHRONIZATION		0#define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP	1#define TIMESTAMPMODE_QUERYSYSTEMTIME			2#define TIMESTAMPMODE_RDTSC				3#define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP	99#define TIMESTAMPMODE_REGKEY L"TimestampMode"extern ULONG TimestampMode;/*!  \brief A microsecond precise timestamp.  included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet. */struct timeval {        long    tv_sec;         ///< seconds        long    tv_usec;        ///< microseconds};#endif /*WIN_NT_DRIVER*/struct time_conv{	ULONGLONG reference;	struct timeval start[32];};#ifdef WIN_NT_DRIVER__inline void TIME_DESYNCHRONIZE(struct time_conv *data){	data->reference = 0;//	data->start.tv_sec = 0;//	data->start.tv_usec = 0;}__inline void ReadTimeStampModeFromRegistry(PUNICODE_STRING RegistryPath){	ULONG NewLength;	PWSTR NullTerminatedString;	RTL_QUERY_REGISTRY_TABLE Queries[2];	ULONG DefaultTimestampMode = DEFAULT_TIMESTAMPMODE;	NewLength = RegistryPath->Length/2;		NullTerminatedString = ExAllocatePool(PagedPool, (NewLength+1) *sizeof(WCHAR));		if (NullTerminatedString != NULL)	{		RtlCopyMemory(NullTerminatedString, RegistryPath->Buffer, RegistryPath->Length);						NullTerminatedString[NewLength]=0;		RtlZeroMemory(Queries, sizeof(Queries));				Queries[0].Flags = RTL_QUERY_REGISTRY_DIRECT;		Queries[0].Name = TIMESTAMPMODE_REGKEY;		Queries[0].EntryContext = &TimestampMode;		Queries[0].DefaultType = REG_DWORD;		Queries[0].DefaultData = &DefaultTimestampMode;		Queries[0].DefaultLength = sizeof(ULONG);		if (RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, NullTerminatedString, Queries, NULL, NULL) != STATUS_SUCCESS)		{			TimestampMode = DEFAULT_TIMESTAMPMODE;		}		RtlWriteRegistryValue(	RTL_REGISTRY_ABSOLUTE, NullTerminatedString, TIMESTAMPMODE_REGKEY,  REG_DWORD, &TimestampMode,sizeof(ULONG));			ExFreePool(NullTerminatedString);	}		else		TimestampMode = DEFAULT_TIMESTAMPMODE;}#pragma optimize ("g",off)  //Due to some weird behaviour of the optimizer of DDK build 2600 /* KeQueryPerformanceCounter TimeStamps */__inline void SynchronizeOnCpu(struct timeval *start){//	struct timeval *start = (struct timeval*)Data;	struct timeval tmp;	LARGE_INTEGER SystemTime;	LARGE_INTEGER i;	ULONG tmp2;	LARGE_INTEGER TimeFreq,PTime;	// get the absolute value of the system boot time.   		PTime = KeQueryPerformanceCounter(&TimeFreq);	KeQuerySystemTime(&SystemTime);		start->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);	start->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);	start->tv_sec -= (ULONG)(PTime.QuadPart/TimeFreq.QuadPart);	start->tv_usec -= (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);	if (start->tv_usec < 0)	{		start->tv_sec --;		start->tv_usec += 1000000;	}}	/*RDTSC timestamps			*//* callers must be at IRQL=PASSIVE_LEVEL*/__inline VOID TimeSynchronizeRDTSC(struct time_conv *data){	struct timeval tmp;	LARGE_INTEGER system_time;	ULONGLONG curr_ticks;	KIRQL old;	LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;	ULONGLONG start_ticks,stop_ticks;	ULONGLONG delta,delta2;	KEVENT event;	LARGE_INTEGER i;	ULONGLONG reference;   	if (data->reference!=0)		return;		KeInitializeEvent(&event,NotificationEvent,FALSE);	i.QuadPart=-3500000;	KeRaiseIrql(HIGH_LEVEL,&old);	start_kqpc=KeQueryPerformanceCounter(&start_freq);	__asm	{		push eax		push edx		push ecx		rdtsc		lea ecx, start_ticks		mov [ecx+4], edx		mov [ecx], eax		pop ecx		pop edx		pop eax	}	KeLowerIrql(old);	    	KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);	KeRaiseIrql(HIGH_LEVEL,&old);	stop_kqpc=KeQueryPerformanceCounter(&stop_freq);	__asm	{		push eax		push edx		push ecx		rdtsc		lea ecx, stop_ticks		mov [ecx+4], edx		mov [ecx], eax		pop ecx		pop edx		pop eax	}	KeLowerIrql(old);	delta=stop_ticks-start_ticks;	delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;	if (delta>10000000000)	{		delta/=16;		delta2/=16;	}	reference=delta*(start_freq.QuadPart)/delta2;		data->reference=reference/1000;	if (reference%1000>500) 		data->reference++;	data->reference*=1000;	reference=data->reference;			KeQuerySystemTime(&system_time);	__asm	{		push eax		push edx		push ecx		rdtsc		lea ecx, curr_ticks		mov [ecx+4], edx		mov [ecx], eax		pop ecx		pop edx		pop eax	}		tmp.tv_sec=-(LONG)(curr_ticks/reference);	tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);	system_time.QuadPart-=116444736000000000;		tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);	tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);		if (tmp.tv_usec<0)	{		tmp.tv_sec--;		tmp.tv_usec+=1000000;	}	data->start[0] = tmp;	IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)}#pragma optimize ("g",on)  //Due to some weird behaviour of the optimizer of DDK build 2600 __inline VOID TIME_SYNCHRONIZE(struct time_conv *data){	ULONG NumberOfCpus, i;	KAFFINITY AffinityMask;	if (data->reference != 0)		return;			NumberOfCpus = NdisSystemProcessorCount();	if ( TimestampMode ==  TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)	{		for (i = 0 ;  i < NumberOfCpus ; i++ )		{			AffinityMask = (1 << i);			ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));			SynchronizeOnCpu(&(data->start[i]));				}		AffinityMask = 0xFFFFFFFF;		ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));		data->reference = 1; 	}	else	if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )	{		//do nothing		data->reference = 1;	}	else	if ( TimestampMode == TIMESTAMPMODE_RDTSC )	{		TimeSynchronizeRDTSC(data);	}	else	{	//it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION		SynchronizeOnCpu(data->start);		data->reference = 1;	}	return;}#pragma optimize ("g",off)  //Due to some weird behaviour of the optimizer of DDK build 2600 __inline void GetTimeKQPC(struct timeval *dst, struct time_conv *data){	LARGE_INTEGER PTime, TimeFreq;	LONG tmp;	ULONG CurrentCpu;	static struct timeval old_ts={0,0};	PTime = KeQueryPerformanceCounter(&TimeFreq);	tmp = (LONG)(PTime.QuadPart/TimeFreq.QuadPart);	if (TimestampMode ==  TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)	{		//actually this code is ok only if we are guaranteed that no thread scheduling will take place. 		CurrentCpu = KeGetCurrentProcessorNumber();			dst->tv_sec = data->start[CurrentCpu].tv_sec + tmp;		dst->tv_usec = data->start[CurrentCpu].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);			if (dst->tv_usec >= 1000000)		{			dst->tv_sec ++;			dst->tv_usec -= 1000000;		}		if (TimestampMode ==  TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP)		{			if (old_ts.tv_sec > dst->tv_sec || (old_ts.tv_sec == dst->tv_sec &&  old_ts.tv_usec > dst->tv_usec) )				*dst = old_ts;				else				old_ts = *dst;		}	}	else	{	//it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION		dst->tv_sec = data->start[0].tv_sec + tmp;		dst->tv_usec = data->start[0].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);			if (dst->tv_usec >= 1000000)		{			dst->tv_sec ++;			dst->tv_usec -= 1000000;		}	}}__inline void GetTimeRDTSC(struct timeval *dst, struct time_conv *data){	ULONGLONG tmp;	__asm	{		push eax		push edx		push ecx		rdtsc		lea ecx, tmp		mov [ecx+4], edx		mov [ecx], eax		pop ecx		pop edx		pop eax	}	if (data->reference==0)	{		return;	}	dst->tv_sec=(LONG)(tmp/data->reference);	dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);		dst->tv_sec+=data->start[0].tv_sec;	dst->tv_usec+=data->start[0].tv_usec;	if (dst->tv_usec>=1000000)	{		dst->tv_sec++;		dst->tv_usec-=1000000;	}}__inline void GetTimeQST(struct timeval *dst, struct time_conv *data){	LARGE_INTEGER SystemTime;	KeQuerySystemTime(&SystemTime);		dst->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);	dst->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);}#pragma optimize ("g",on)  //Due to some weird behaviour of the optimizer of DDK build 2600 __inline void GET_TIME(struct timeval *dst, struct time_conv *data){	if ( TimestampMode == TIMESTAMPMODE_RDTSC )	{		GetTimeRDTSC(dst,data);	}	else	if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )	{		GetTimeQST(dst,data);	}	else	{		GetTimeKQPC(dst,data);	}}#else /*WIN_NT_DRIVER*/__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest){	dest->start[0]=*src;}__inline void GET_TIME(struct timeval *dst, struct time_conv *data){	*dst=data->start[0];}#endif /*WIN_NT_DRIVER*/#endif /*_time_calls*/

⌨️ 快捷键说明

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