time_calls.h
上传用户:gzdtt123
上传日期:2022-01-26
资源大小:88k
文件大小:10k
开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 2001
  3.  * Politecnico di Torino.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the Politecnico
  13.  * di Torino, and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21. #ifndef _time_calls
  22. #define _time_calls
  23. #ifdef WIN_NT_DRIVER
  24. #include "debug.h"
  25. #include "ndis.h"
  26. #define DEFAULT_TIMESTAMPMODE 0
  27. #define TIMESTAMPMODE_SINGLE_SYNCHRONIZATION 0
  28. #define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP 1
  29. #define TIMESTAMPMODE_QUERYSYSTEMTIME 2
  30. #define TIMESTAMPMODE_RDTSC 3
  31. #define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP 99
  32. #define TIMESTAMPMODE_REGKEY L"TimestampMode"
  33. extern ULONG TimestampMode;
  34. /*!
  35.   brief A microsecond precise timestamp.
  36.   included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet. 
  37. */
  38. struct timeval {
  39.         long    tv_sec;         ///< seconds
  40.         long    tv_usec;        ///< microseconds
  41. };
  42. #endif /*WIN_NT_DRIVER*/
  43. struct time_conv
  44. {
  45. ULONGLONG reference;
  46. struct timeval start[32];
  47. };
  48. #ifdef WIN_NT_DRIVER
  49. __inline void TIME_DESYNCHRONIZE(struct time_conv *data)
  50. {
  51. data->reference = 0;
  52. // data->start.tv_sec = 0;
  53. // data->start.tv_usec = 0;
  54. }
  55. __inline void ReadTimeStampModeFromRegistry(PUNICODE_STRING RegistryPath)
  56. {
  57. ULONG NewLength;
  58. PWSTR NullTerminatedString;
  59. RTL_QUERY_REGISTRY_TABLE Queries[2];
  60. ULONG DefaultTimestampMode = DEFAULT_TIMESTAMPMODE;
  61. NewLength = RegistryPath->Length/2;
  62. NullTerminatedString = ExAllocatePool(PagedPool, (NewLength+1) *sizeof(WCHAR));
  63. if (NullTerminatedString != NULL)
  64. {
  65. RtlCopyMemory(NullTerminatedString, RegistryPath->Buffer, RegistryPath->Length);
  66. NullTerminatedString[NewLength]=0;
  67. RtlZeroMemory(Queries, sizeof(Queries));
  68. Queries[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  69. Queries[0].Name = TIMESTAMPMODE_REGKEY;
  70. Queries[0].EntryContext = &TimestampMode;
  71. Queries[0].DefaultType = REG_DWORD;
  72. Queries[0].DefaultData = &DefaultTimestampMode;
  73. Queries[0].DefaultLength = sizeof(ULONG);
  74. if (RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, NullTerminatedString, Queries, NULL, NULL) != STATUS_SUCCESS)
  75. {
  76. TimestampMode = DEFAULT_TIMESTAMPMODE;
  77. }
  78. RtlWriteRegistryValue( RTL_REGISTRY_ABSOLUTE, NullTerminatedString, TIMESTAMPMODE_REGKEY,  REG_DWORD, &TimestampMode,sizeof(ULONG));
  79. ExFreePool(NullTerminatedString);
  80. }
  81. else
  82. TimestampMode = DEFAULT_TIMESTAMPMODE;
  83. }
  84. #pragma optimize ("g",off)  //Due to some weird behaviour of the optimizer of DDK build 2600 
  85. /* KeQueryPerformanceCounter TimeStamps */
  86. __inline void SynchronizeOnCpu(struct timeval *start)
  87. {
  88. // struct timeval *start = (struct timeval*)Data;
  89. struct timeval tmp;
  90. LARGE_INTEGER SystemTime;
  91. LARGE_INTEGER i;
  92. ULONG tmp2;
  93. LARGE_INTEGER TimeFreq,PTime;
  94. // get the absolute value of the system boot time.   
  95. PTime = KeQueryPerformanceCounter(&TimeFreq);
  96. KeQuerySystemTime(&SystemTime);
  97. start->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
  98. start->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
  99. start->tv_sec -= (ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
  100. start->tv_usec -= (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
  101. if (start->tv_usec < 0)
  102. {
  103. start->tv_sec --;
  104. start->tv_usec += 1000000;
  105. }
  106. }
  107. /*RDTSC timestamps */
  108. /* callers must be at IRQL=PASSIVE_LEVEL*/
  109. __inline VOID TimeSynchronizeRDTSC(struct time_conv *data)
  110. {
  111. struct timeval tmp;
  112. LARGE_INTEGER system_time;
  113. ULONGLONG curr_ticks;
  114. KIRQL old;
  115. LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
  116. ULONGLONG start_ticks,stop_ticks;
  117. ULONGLONG delta,delta2;
  118. KEVENT event;
  119. LARGE_INTEGER i;
  120. ULONGLONG reference;
  121.     if (data->reference!=0)
  122. return;
  123. KeInitializeEvent(&event,NotificationEvent,FALSE);
  124. i.QuadPart=-3500000;
  125. KeRaiseIrql(HIGH_LEVEL,&old);
  126. start_kqpc=KeQueryPerformanceCounter(&start_freq);
  127. __asm
  128. {
  129. push eax
  130. push edx
  131. push ecx
  132. rdtsc
  133. lea ecx, start_ticks
  134. mov [ecx+4], edx
  135. mov [ecx], eax
  136. pop ecx
  137. pop edx
  138. pop eax
  139. }
  140. KeLowerIrql(old);
  141.      KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
  142. KeRaiseIrql(HIGH_LEVEL,&old);
  143. stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
  144. __asm
  145. {
  146. push eax
  147. push edx
  148. push ecx
  149. rdtsc
  150. lea ecx, stop_ticks
  151. mov [ecx+4], edx
  152. mov [ecx], eax
  153. pop ecx
  154. pop edx
  155. pop eax
  156. }
  157. KeLowerIrql(old);
  158. delta=stop_ticks-start_ticks;
  159. delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
  160. if (delta>10000000000)
  161. {
  162. delta/=16;
  163. delta2/=16;
  164. }
  165. reference=delta*(start_freq.QuadPart)/delta2;
  166. data->reference=reference/1000;
  167. if (reference%1000>500) 
  168. data->reference++;
  169. data->reference*=1000;
  170. reference=data->reference;
  171. KeQuerySystemTime(&system_time);
  172. __asm
  173. {
  174. push eax
  175. push edx
  176. push ecx
  177. rdtsc
  178. lea ecx, curr_ticks
  179. mov [ecx+4], edx
  180. mov [ecx], eax
  181. pop ecx
  182. pop edx
  183. pop eax
  184. }
  185. tmp.tv_sec=-(LONG)(curr_ticks/reference);
  186. tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
  187. system_time.QuadPart-=116444736000000000;
  188. tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
  189. tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
  190. if (tmp.tv_usec<0)
  191. {
  192. tmp.tv_sec--;
  193. tmp.tv_usec+=1000000;
  194. }
  195. data->start[0] = tmp;
  196. IF_LOUD(DbgPrint("Frequency %I64u MHzn",data->reference);)
  197. }
  198. #pragma optimize ("g",on)  //Due to some weird behaviour of the optimizer of DDK build 2600 
  199. __inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
  200. {
  201. ULONG NumberOfCpus, i;
  202. KAFFINITY AffinityMask;
  203. if (data->reference != 0)
  204. return;
  205. NumberOfCpus = NdisSystemProcessorCount();
  206. if ( TimestampMode ==  TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
  207. {
  208. for (i = 0 ;  i < NumberOfCpus ; i++ )
  209. {
  210. AffinityMask = (1 << i);
  211. ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
  212. SynchronizeOnCpu(&(data->start[i]));
  213. }
  214. AffinityMask = 0xFFFFFFFF;
  215. ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
  216. data->reference = 1;
  217.   }
  218. else
  219. if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
  220. {
  221. //do nothing
  222. data->reference = 1;
  223. }
  224. else
  225. if ( TimestampMode == TIMESTAMPMODE_RDTSC )
  226. {
  227. TimeSynchronizeRDTSC(data);
  228. }
  229. else
  230. { //it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION
  231. SynchronizeOnCpu(data->start);
  232. data->reference = 1;
  233. }
  234. return;
  235. }
  236. #pragma optimize ("g",off)  //Due to some weird behaviour of the optimizer of DDK build 2600 
  237. __inline void GetTimeKQPC(struct timeval *dst, struct time_conv *data)
  238. {
  239. LARGE_INTEGER PTime, TimeFreq;
  240. LONG tmp;
  241. ULONG CurrentCpu;
  242. static struct timeval old_ts={0,0};
  243. PTime = KeQueryPerformanceCounter(&TimeFreq);
  244. tmp = (LONG)(PTime.QuadPart/TimeFreq.QuadPart);
  245. if (TimestampMode ==  TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
  246. {
  247. //actually this code is ok only if we are guaranteed that no thread scheduling will take place. 
  248. CurrentCpu = KeGetCurrentProcessorNumber();
  249. dst->tv_sec = data->start[CurrentCpu].tv_sec + tmp;
  250. dst->tv_usec = data->start[CurrentCpu].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
  251. if (dst->tv_usec >= 1000000)
  252. {
  253. dst->tv_sec ++;
  254. dst->tv_usec -= 1000000;
  255. }
  256. if (TimestampMode ==  TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP)
  257. {
  258. if (old_ts.tv_sec > dst->tv_sec || (old_ts.tv_sec == dst->tv_sec &&  old_ts.tv_usec > dst->tv_usec) )
  259. *dst = old_ts;
  260. else
  261. old_ts = *dst;
  262. }
  263. }
  264. else
  265. { //it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION
  266. dst->tv_sec = data->start[0].tv_sec + tmp;
  267. dst->tv_usec = data->start[0].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
  268. if (dst->tv_usec >= 1000000)
  269. {
  270. dst->tv_sec ++;
  271. dst->tv_usec -= 1000000;
  272. }
  273. }
  274. }
  275. __inline void GetTimeRDTSC(struct timeval *dst, struct time_conv *data)
  276. {
  277. ULONGLONG tmp;
  278. __asm
  279. {
  280. push eax
  281. push edx
  282. push ecx
  283. rdtsc
  284. lea ecx, tmp
  285. mov [ecx+4], edx
  286. mov [ecx], eax
  287. pop ecx
  288. pop edx
  289. pop eax
  290. }
  291. if (data->reference==0)
  292. {
  293. return;
  294. }
  295. dst->tv_sec=(LONG)(tmp/data->reference);
  296. dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
  297. dst->tv_sec+=data->start[0].tv_sec;
  298. dst->tv_usec+=data->start[0].tv_usec;
  299. if (dst->tv_usec>=1000000)
  300. {
  301. dst->tv_sec++;
  302. dst->tv_usec-=1000000;
  303. }
  304. }
  305. __inline void GetTimeQST(struct timeval *dst, struct time_conv *data)
  306. {
  307. LARGE_INTEGER SystemTime;
  308. KeQuerySystemTime(&SystemTime);
  309. dst->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
  310. dst->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
  311. }
  312. #pragma optimize ("g",on)  //Due to some weird behaviour of the optimizer of DDK build 2600 
  313. __inline void GET_TIME(struct timeval *dst, struct time_conv *data)
  314. {
  315. if ( TimestampMode == TIMESTAMPMODE_RDTSC )
  316. {
  317. GetTimeRDTSC(dst,data);
  318. }
  319. else
  320. if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
  321. {
  322. GetTimeQST(dst,data);
  323. }
  324. else
  325. {
  326. GetTimeKQPC(dst,data);
  327. }
  328. }
  329. #else /*WIN_NT_DRIVER*/
  330. __inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
  331. {
  332. dest->start[0]=*src;
  333. }
  334. __inline void GET_TIME(struct timeval *dst, struct time_conv *data)
  335. {
  336. *dst=data->start[0];
  337. }
  338. #endif /*WIN_NT_DRIVER*/
  339. #endif /*_time_calls*/