闲来无事,把GetTickCount的原代码也贴出来。

174 views
Skip to first unread message

SevenCat

unread,
May 15, 2006, 9:03:32 PM5/15/06
to 高性能网络编程邮件列表
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

#define KI_USER_SHARED_DATA 0x7FFE0000
#define SharedUserData ((KUSER_SHARED_DATA * CONST)
KI_USER_SHARED_DATA)

typedef struct _KSYSTEM_TIME
{
ULONG LowPart;
LONG High1Time;
LONG High2Time;
} KSYSTEM_TIME, *PKSYSTEM_TIME;

typedef enum _NT_PRODUCT_TYPE
{
NtProductWinNt = 1,
NtProductLanManNt,
NtProductServer
} NT_PRODUCT_TYPE, *PNT_PRODUCT_TYPE;

//
// Maximum Processor Features supported in KUSER_SHARED_DATA
//
#define PROCESSOR_FEATURE_MAX 64

typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE
{
StandardDesign,
NEC98x86,
EndAlternatives
} ALTERNATIVE_ARCHITECTURE_TYPE;

#define MAX_WOW64_SHARED_ENTRIES 16

typedef struct _KUSER_SHARED_DATA
{
ULONG TickCountLowDeprecated;
ULONG TickCountMultiplier;
volatile KSYSTEM_TIME InterruptTime;
volatile KSYSTEM_TIME SystemTime;
volatile KSYSTEM_TIME TimeZoneBias;
USHORT ImageNumberLow;
USHORT ImageNumberHigh;
WCHAR NtSystemRoot[260];
ULONG MaxStackTraceDepth;
ULONG CryptoExponent;
ULONG TimeZoneId;
ULONG LargePageMinimum;
ULONG Reserved2[7];
NT_PRODUCT_TYPE NtProductType;
BOOLEAN ProductTypeIsValid;
ULONG NtMajorVersion;
ULONG NtMinorVersion;
BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX];
ULONG Reserved1;
ULONG Reserved3;
volatile ULONG TimeSlip;
ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture;
LARGE_INTEGER SystemExpirationDate;
ULONG SuiteMask;
BOOLEAN KdDebuggerEnabled;
volatile ULONG ActiveConsoleId;
volatile ULONG DismountCount;
ULONG ComPlusPackage;
ULONG LastSystemRITEventTickCount;
ULONG NumberOfPhysicalPages;
BOOLEAN SafeBootMode;
ULONG TraceLogging;
ULONG Fill0;
ULONGLONG TestRetInstruction;
ULONG SystemCall;
ULONG SystemCallReturn;
ULONGLONG SystemCallPad[3];
union {
volatile KSYSTEM_TIME TickCount;
volatile ULONG64 TickCountQuad;
};
ULONG Cookie;
LONGLONG ConsoleSessionForegroundProcessId;
ULONG Wow64SharedInformation[MAX_WOW64_SHARED_ENTRIES];
ULONG UserModeGlobalLogging;
} KUSER_SHARED_DATA, *PKUSER_SHARED_DATA;


DWORD MyGetTickCount()
{
return (DWORD)((ULONGLONG)SharedUserData->TickCountLowDeprecated *
SharedUserData->TickCountMultiplier / 16777216);
}


int main(int argc,char *argv[])
{
DWORD u1=GetTickCount();
DWORD u2=MyGetTickCount();
return 0;
}

sunway

unread,
May 15, 2006, 9:16:47 PM5/15/06
to 高性能网络编程邮件列表
有乘法运算,效率不高啊

SevenCat

unread,
May 15, 2006, 9:23:00 PM5/15/06
to 高性能网络编程邮件列表
只有一个乘法运算了,还可以,马虎马虎着用,

sunway

unread,
May 15, 2006, 9:24:59 PM5/15/06
to 高性能网络编程邮件列表
没看到更新SharedUserData的代码啊

SevenCat

unread,
May 15, 2006, 9:35:39 PM5/15/06
to 高性能网络编程邮件列表
这个伪实现是C的,2KSOURCE里面是汇编代码。
/*
* NOTE: On Windows this function takes exactly zero parameters and EBP
is
* guaranteed to point to KTRAP_FRAME. Also [esp+0] contains an
IRQL.
* The function is used only by HAL, so there's no point in
keeping
* that prototype.
*
* @implemented
*/
VOID
STDCALL
KeUpdateSystemTime(
IN PKTRAP_FRAME TrapFrame,
IN KIRQL Irql
)
/*
* FUNCTION: Handles a timer interrupt
*/
{
LARGE_INTEGER Time;

ASSERT(KeGetCurrentIrql() == PROFILE_LEVEL);

KiRawTicks++;

if (KiClockSetupComplete == FALSE) return;

/*
* Increment the number of timers ticks
*/
KeTickCount++;
SharedUserData->TickCountLowDeprecated++;

Time.u.LowPart = SharedUserData->InterruptTime.LowPart;
Time.u.HighPart = SharedUserData->InterruptTime.High1Time;
Time.QuadPart += CLOCK_INCREMENT;
SharedUserData->InterruptTime.High2Time = Time.u.HighPart;
SharedUserData->InterruptTime.LowPart = Time.u.LowPart;
SharedUserData->InterruptTime.High1Time = Time.u.HighPart;

Time.u.LowPart = SharedUserData->SystemTime.LowPart;
Time.u.HighPart = SharedUserData->SystemTime.High1Time;
Time.QuadPart += CLOCK_INCREMENT;
SharedUserData->SystemTime.High2Time = Time.u.HighPart;
SharedUserData->SystemTime.LowPart = Time.u.LowPart;
SharedUserData->SystemTime.High1Time = Time.u.HighPart;

/* FIXME: Here we should check for remote debugger break-ins */

/* Update process and thread times */
KeUpdateRunTime(TrapFrame, Irql);

/*
* Queue a DPC that will expire timers
*/
KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0);
}
汇编代码的注释:

; VOID
; KeUpdateSystemTime (
; IN KIRQL PreviousIrql,
; IN KTRAP_FRAME TrapFrame
; )
;
; Routine Description:
;
; This routine is entered as the result of an interrupt generated by
CLOCK2.
; Its function is to update the system time and check to determine
if a timer
; has expired.
;
; N.B. This routine is executed on a single processor in a
multiprocess
; system. The remainder of the processors only execute the
quantum end
; and runtime update code.
;
; N.B. This routine is not called, but directly jumped to. Thus,
there
; is no return address. It returns via the INTERRUPT_EXIT macro.

SevenCat

unread,
May 15, 2006, 9:37:38 PM5/15/06
to 高性能网络编程邮件列表
; Arguments:
;
; PreviousIrql (esp) - supplies previous irql of system
;
; HardwareVector (esp+4) - supplies hardware vector for
EndSystemInterrupt
;
; TrapFrame (esp+8) - supplies base of trap frame
;
; EAX is the TimeIncrement value
;
; EBP is a pointer to the trap frame
;
;
; Environment:
;
; IRQL = CLOCK_LEVEL
;
; Return Value:
;
; None.
;
;--
cPublicProc _KeUpdateSystemTime ,0

.FPO (2, 0, 0, 0, 0, 1) ; treat params as locals since functions is
JMPed too

if DBG
cmp byte ptr PCR[PcPrcbData+PbSkipTick], 0
jnz kust_skiptick
endif

;
; Update interrupt time.
;
; N.B. The interrupt time is updated in a very strict manner so that an
; interlock does not have to be used in an MP system to read time.
;

mov ecx,USER_SHARED_DATA ; set address of user shared
data
mov edi,[ecx].UsInterruptTime+0 ; get low interrupt time
mov esi,[ecx].UsInterruptTime+4 ; get high interrupt time
add edi,eax ; add time increment
adc esi,0 ; propagate carry
mov [ecx].UsInterruptTime+8,esi ; store high 2 interrupt
time
mov [ecx].UsInterruptTime+0,edi ; store low interrupt time
mov [ecx].UsInterruptTime+4,esi ; store high 1 interrupt
time

sub _KiTickOffset,eax ; subtract time increment
mov eax,_KeTickCount+0 ; get low tick count
mov ebx,eax ; copy low tick count
jg kust10 ; if greater, not complete tick

;
; Update system time.
;
; N.B. The system time is updated in a very strict manner so that an
; interlock does not have to be used in an MP system to read time.
;

mov ebx,USER_SHARED_DATA ; set address of user shared
data
mov ecx,[ebx].UsSystemTime+0 ; get low interrupt time
mov edx,[ebx].UsSystemTime+4 ; get high interrupt time
add ecx,_KeTimeAdjustment ; add time increment
adc edx,0 ; propagate carry
mov [ebx].UsSystemTime+8,edx ; store high 2 interrupt time
mov [ebx].UsSystemTime+0,ecx ; store low interrupt time
mov [ebx].UsSystemTime+4,edx ; store high 1 interrupt time
mov ebx,eax ; restore low tick count

;
; Update tick count.
;
; N.B. The tick count is updated in a very strict manner so that an
; interlock does not have to be used in an MP system to read
count.
;

mov ecx,eax ; copy low tick count
mov edx,_KeTickCount+4 ; get high tick count
add ecx,1 ; increment tick count
adc edx,0 ; propagate carry
mov _KeTickCount+8,edx ; store high 2 tick count
mov _KeTickCount+0,ecx ; store low tick count
mov _KeTickCount+4,edx ; store high 1 tick count
mov USERDATA[UsTickCountLow], ecx

if 0
; debug code
push eax
mov edx, esi
mov eax, edi ; (eax:edx) = InterruptTime
mov ecx, _KeMaximumIncrement
div ecx
cmp al, bl ; same bucket?
je short @f
int 3 ; no - stop
@@:
pop eax
endif

;
; Check to determine if a timer has expired.
; (edi:esi) = KiInterruptTime
; (eax) = KeTickCount.LowPart
; (ebx) = KeTickCount.LowPart
;

and eax,TIMER_TABLE_SIZE-1 ; isolate current hand value
lea ecx,_KiTimerTableListHead[eax*8] ; get listhead addrees
mov edx,[ecx] ; get first entry address
cmp ecx,edx ; check if list is empry
je short kust5 ; if equal, list is empty
cmp esi,[edx].TiDueTime.TmHighTime-TiTimerListEntry ;
compare high
jb short kust5 ; if below, timer has not
expired
ja short kust15 ; if above, timer has expired
cmp edi,[edx].TiDueTime.TmLowTime-TiTimerListEntry ;
compare low
jae short kust15 ; if above or equal, time has
expired
kust5: inc eax ; advance hand value to next
entry
inc ebx

;
; Check to determine if a timer has expired.
; (edi:esi) = KiInterruptTime
; (eax) = bucket
; (ebx) = KeTickCount.LowPart
;

kust10: and eax,TIMER_TABLE_SIZE-1 ; isolate current hand value
lea ecx,_KiTimerTableListHead[eax*8] ; get listhead addrees
mov edx,[ecx] ; get first entry address
cmp ecx,edx ; check if list is empry
je kustxx ; if equal, list is empty
cmp esi,[edx].TiDueTime.TmHighTime-TiTimerListEntry ;
compare high
jb kustxx ; if below, timer has not
expired
ja short kust15 ; if above, timer has expired
cmp edi,[edx].TiDueTime.TmLowTime-TiTimerListEntry ;
compare low
jb kustxx ; if below, timer has not
expired

kust15:
;
; Timer has expired, put timer expiration DPC in the current
processor's DPC
; queue.
;
; (ebx) = KeTickCount.LowPart
;

mov ecx,PCR[PcPrcb] ; get processor control block
address
lea eax,_KiTimerExpireDpc+DpDpcListEntry ; get list entry
address
lea edx,[ecx]+PbDpcLock ; get DPC lock address
cmp dword ptr [eax]+(DpLock-DpDpcListEntry), 0H ; check if
inserted
jnz kustxx ; if nz, DPC already inserted

kust20: cli
ACQUIRE_SPINLOCK edx, kust60

inc dword ptr [ecx].PbDpcQueueDepth ; increment DPC queue
depth
mov dword ptr [eax]+(DpLock-DpDpcListEntry), edx ; set lock
address
mov [eax]+(DpSystemArgument1-DpDpcListEntry),ebx ; pass
tick count
add ecx,PbDpcListHead ; compute DPC listhead address
mov ebx,[ecx]+LsBlink ; get address of last entry in
list
mov [ecx]+LsBlink, eax ; set new address of last entry
mov [ebx]+LsFlink, eax ; set forward link in old last
entry
mov [eax]+LsFlink, ecx ; set forward link in new last
entry
mov [eax]+LsBlink, ebx ; set backward link in new last
entry

RELEASE_SPINLOCK edx
sti ; enable interrupt

; request dispatch interrupt

mov ecx, DISPATCH_LEVEL
fstCall HalRequestSoftwareInterrupt

kustxx:
if DEVL
cmp _KdDebuggerEnabled, 0
jnz short kust45
kust30:
endif
cmp _KiTickOffset,0 ; check if full tick
jg short Kust40 ; if not less, not a full tick

mov eax,_KeMaximumIncrement ; get maximum time incrmeent
add _KiTickOffset,eax ; add maximum tine to residue

;
; call KeUpdateRunTime to do the acutal work
;

; TOS const PreviousIrql
push [esp]
call _KeUpdateRunTime@4

;
; Do interrupt exit processing
;

INTERRUPT_EXIT

kust40:
inc dword ptr PCR[PcPrcbData+PbInterruptCount]
INTERRUPT_EXIT

if DEVL
kust45:
stdCall _KdPollBreakIn
or al,al
jz short kust30
stdCall _DbgBreakPointWithStatus,<DBG_STATUS_CONTROL_C>
jmp short kust30
endif

if DBG
kust_skiptick:
mov byte ptr PCR[PcPrcbData+PbSkipTick], 0
jmp short kust40
endif

;
; Lock is currently owned; spin until free and then attempt to acquire
; lock again.
;

ALIGN 4
kust60: sti ; spin with interrupts enabled
SPIN_ON_SPINLOCK edx, kust20,,DbgMp

stdENDP _KeUpdateSystemTime


page ,132
subttl "Update Thread and Process Runtime"

sunway

unread,
May 15, 2006, 10:09:12 PM5/15/06
to 高性能网络编程邮件列表
mail list就你我两人,真冷清

kalos

unread,
May 15, 2006, 10:09:44 PM5/15/06
to dev4s...@googlegroups.com

技术我不懂,灌水我还行!!!
-----邮件原件-----
发件人: dev4s...@googlegroups.com [mailto:dev4s...@googlegroups.com] 代
表 sunway
发送时间: 2006年5月16日 10:09
收件人: 高性能网络编程邮件列表
主题: Re: 闲来无事,把GetTickCount的原代码也贴出来。

mail list就你我两人,真冷清


Ghost Cheng

unread,
May 15, 2006, 11:00:55 PM5/15/06
to dev4s...@googlegroups.com
无忌兄:
还有我哪~哈哈

 
On 5/16/06, sunway <sunh...@gmail.com> wrote:
mail list就你我两人,真冷清

--

Sincerely,
Ghost Cheng
Email : ghost...@gmail.com
Web : http://www.GhostSoft.net

sunway

unread,
May 15, 2006, 11:09:38 PM5/15/06
to 高性能网络编程邮件列表
老cheng也在啊,大家一起开个Part把,哈哈,sodme莫怪!

quengzi

unread,
May 16, 2006, 12:56:50 AM5/16/06
to dev4server
dev4server,
 
潜水呢:D
支持!
 
2006-5-16

疯子阿虹

unread,
May 18, 2006, 4:02:31 AM5/18/06
to 高性能网络编程邮件列表
晕啊。
写这个函数能干什么?
最多提升一点效率,不解。

sunway

unread,
May 18, 2006, 4:24:02 AM5/18/06
to 高性能网络编程邮件列表
猫猫把这个函数的代码拿出来给大家看看,了解一下原理,不是重写这个函数
Reply all
Reply to author
Forward
0 new messages