GetTickCount64 api - 64-bit return value?

How do I prototype and use it?

Given it’s eight bytes I wondered if something like this would work:

GetTickCount64  procedure,real,pascal,name('GetTickCount64')

myResult    real 
myUINT64    group,over(myResult) 
lo              ulong
hi              ulong
            end 
            
    myResult = sdkGetTickCount64()

But of course I get garbage in the group.

Thanks

No. Wouldn’t work, different storage.
Try
Myresuly Group
lo ulong
hi ulong
end

I’m really really unsure because I’ve never dealt with 64 bit but hey…

Finally I found how to.

Declare it like this (return LONG instead of REAL), but assign it to REAL target:

GetTickCount64(),LONG,PASCAL,NAME('GetTickCount64')

ticks                                   LONG, AUTO
rTicks                                  REAL, AUTO
  CODE
  ticks = GetTickCount()
  rTicks = GetTickCount64()
  printd('ticks=%i, ticks64=%i', ticks, rTicks)

This works as expected.

I would get rid of the Over Real. You must prototype to return a Real so the compiler knows it’s getting an 8 byte return value, but it is not a Real internally.

GetTickCount64  procedure,REAL,pascal,name('GetTickCount64'),DLL(1l

myResult    group   !no-h> ,over(myResult) 
lo              ulong
hi              ulong
            end 
            
    myResult = sdkGetTickCount64()

If you are going to compare to the 32 bit GetTickCount() you must read MSDN that it rolls over at 49.7 days. As long as your system has been up less than that the myResult.LO should be close and .HI = Zero

Mike. Unless I’m losing my mind I think you have deleted an earlier response in favour of this “use a real” approach?

I didn’t keep a copy of that earlier response but was acting on it and things seemed good. It was along these lines:

ticks64 group
hi long
lo ulong
end

ticks64.lo = GetTickCount64() ! with the api call declared as returning a long

It did seem too magical - I’m thinking you found that ticks64.hi was never populated?

Background is that I’ve used GetTickCount to monitor server runtimes for ever and it’s annoying when they start going back in time after 21 days or so. I now realise that using ulongs would probably have pushed that out to 43 days but wanted to finally tidy it up.

Using that “ticks64 group” approach, one particular server is now moving forward again (27 days+) - nice but only because ulongs got involved? Milliseconds-wise it’s nearly 3 weeks away from exceeding a 32 bit number.

I did try your “assign to a real” approach but got a negative number in line with GetTickCount().

Really appreciate your input. For me, this is a very low priority, would be nice to understand and resolve thing…

Simon,

For some unknown reason when I declare GetTickCount64 as “(), REAL” it always returns 0xFFFF8000 hex value.

Yep. That’s what I was seeing and why I originally reached out.

A C helper DLL that returns the data in a Clarion digestible format?

Yes. But I don’t care enough to go there.

Was hoping for a simple clarion way/trick. But now suspect that was naive - my current picture is that when clarion deals with api “functions” (c/pascal) it’s always expecting a 32-bit number back. Which might well be a pointer to something else but that’s all it permits - (LONG/ULONG, your choice) numbers. Given that, fact that you can prototype real / string / cstring return values doesn’t make much sense on a Sunday afternoon. So my picture is probably still wrong.

Appreciate everyone’s input. And if Mike D can’t make it work then probably case closed.

Made it working with asm wrapper:

  PROGRAM

  PRAGMA('compile(MyGetTickCount64.a)')

  MAP
    MODULE('MyGetTickCount64.a')
      GetTickCount64(*LONG pTicksLo, *LONG pTicksHi),PASCAL,NAME('__ASM__GetTickCount64')
    END
  END
ticks64_lo                              LONG, AUTO
ticks64_hi                              LONG, AUTO

  CODE
  GetTickCount64(ticks64_lo, ticks64_hi)

MyGetTickCount64.a:

  module gettickcount64
  
(* c++ call in assembler: *)
(*       ULONGLONG ticks = GetTickCount64(); *)
(* 003E2466  mov         esi,esp   *)
(* 003E2468  call        dword ptr [__imp__GetTickCount64@0 (03ED000h)]   *)
(* 003E246E  cmp         esi,esp   *)
(* 003E2470  call        __RTC_CheckEsp (03E1294h)   *)
(* 003E2475  mov         dword ptr [ticks],eax   *)
(* 003E2478  mov         dword ptr [ebp-8],edx   *)


segment GETTICKCOUNT64_TEXT("CODE",00029H)

  extrn GetTickCount64

public __ASM__GetTickCount64:

push        ebp             (* save stack frame *)
mov         ebp, esp        (* set local ebp *)
push        ebx             (* just in case preserve ebx *)
call        GetTickCount64  (* call api *)
mov         ebx, [esp][12]  (* copy Lo address to ebx *)
mov         [ebx], eax      (* copy Lo value from eax *)
mov         ebx, [esp][16]  (* copy Hi address to ebx *)
mov         [ebx], edx      (* copy Hi value from edx *)
pop         ebx             (* restore ebx *)
pop         ebp             (* restore stack frame *)
ret         8               (* pop 2 pushed arguments *)

  end
2 Likes

Wow.

Late in the day here but I understand how to incorporate asm and already have some on board in my apps so should be easy enough. Will try to take a look tomorrow and revert here. But there’s no rush - the one long-running machine that triggered me is at 39 days so I’ve got 10 days to get this in place (and hope it doesn’t get restarted in the interim).

Whole thing was always a bit academic for me - just nice to see runtime reliably reported into hundreds of days. But perhaps you benefit elsewhere.

Either way, thank you very much.

By the way, the values returned by these 2 functions don’t have much meaning, only the difference between the two calls matters, see this post:
When does GetTickCount consider the system to have started? - The Old New Thing

Interesting but I think Mr Chen is being a bit picky there. If you are monitoring machines and want an idea of how long they’ve been running then the GetTickCount route seems best option.

In my case it shows anything but not running time - yesterday it was 10 days, right now it is 10 hours, if it would be the time from system start, then both values are completely wrong.