blob: 8fe56779e6c4614b7233ce64342d659631c71223 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define CDEV_CURRENT_FUNCTION _comment_
/**
* @file
* @ingroup Port
* @brief Timer utilities
*/
#undef CDEV_CURRENT_FUNCTION
#include <windows.h>
#include "hyport.h"
#include "portpriv.h"
#include "hyportpg.h"
#define CDEV_CURRENT_FUNCTION _prototypes_private
void VMCALL shutdown_timer (void);
I_32 VMCALL init_timer (void);
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hytime_msec_clock
/**
* Query OS for timestamp.
* Retrieve the current value of system clock and convert to milliseconds.
*
* @param[in] portLibrary The port library.
*
* @return 0 on failure, time value in milliseconds on success.
* @deprecated Use @ref hytime_hires_clock and @ref hytime_hires_delta
*/
UDATA VMCALL
hytime_msec_clock (struct HyPortLibrary *portLibrary)
{
LARGE_INTEGER freq, i, multiplier;
UDATA result;
if (!QueryPerformanceFrequency (&freq))
{
return (UDATA) GetTickCount ();
}
multiplier.QuadPart = freq.QuadPart / 1000;
QueryPerformanceCounter (&i);
result = (UDATA) (i.QuadPart / multiplier.QuadPart);
return result;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hytime_usec_clock
/**
* Query OS for timestamp.
* Retrieve the current value of system clock and convert to microseconds.
*
* @param[in] portLibrary The port library.
*
* @return 0 on failure, time value in microseconds on success.
* @deprecated Use @ref hytime_hires_clock and @ref hytime_hires_delta
*/
UDATA VMCALL
hytime_usec_clock (struct HyPortLibrary * portLibrary)
{
LARGE_INTEGER freq, i, multiplier;
UDATA result;
if (!QueryPerformanceFrequency (&freq))
{
return (UDATA) GetTickCount ();
}
multiplier.QuadPart = freq.QuadPart / 1000000;
QueryPerformanceCounter (&i);
result = (UDATA) (i.QuadPart / multiplier.QuadPart);
return result;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hytime_current_time_millis
/**
* Query OS for timestamp.
* Retrieve the current value of system clock and convert to milliseconds since
* January 1st 1970.
*
* @param[in] portLibrary The port library.
*
* @return 0 on failure, time value in milliseconds on success.
*/
I_64 VMCALL
hytime_current_time_millis (struct HyPortLibrary * portLibrary)
{
/* returns in time the number of 100ns elapsed since January 1, 1601 */
/* subtract 116444736000000000 = number of 100ns from jan 1, 1601 to jan 1, 1970 */
/* multiply by 10000 to get number of milliseconds since Jan 1, 1970 */
LONGLONG time;
GetSystemTimeAsFileTime ((FILETIME *) & time);
return (I_64) ((time - 116444736000000000) / 10000);
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION init_timer
I_32 VMCALL
init_timer (void)
{
/* on Win98 this forced the process to run with a higher
* resolution clock. It made things like Thread.sleep() more
* accurate. But the functions it calls are defined in WINMM.DLL,
* which forces USER32.DLL, GDI.DLL and other modules to
* be loaded, polluting the address space. By not loading WINMM.DLL
* we increase the chances of having a large contiguous region
* of virtual memory to use as the Java heap.
*/
#if 0
TIMECAPS timecaps;
timeGetDevCaps (&timecaps, sizeof (TIMECAPS));
timeBeginPeriod (timecaps.wPeriodMin);
#endif
return 0;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION shutdown_timer
void VMCALL
shutdown_timer (void)
{
/* see init_timer */
#if 0
TIMECAPS timecaps;
timeGetDevCaps (&timecaps, sizeof (TIMECAPS));
timeEndPeriod (timecaps.wPeriodMin);
#endif
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hytime_hires_clock
/**
* Query OS for timestamp.
* Retrieve the current value of the high-resolution performance counter.
*
* @param[in] portLibrary The port library.
*
* @return 0 on failure, time value on success.
*/
U_64 VMCALL
hytime_hires_clock (struct HyPortLibrary *portLibrary)
{
LARGE_INTEGER i;
if (QueryPerformanceCounter (&i))
{
return (U_64) i.QuadPart;
}
else
{
return (U_64) GetTickCount ();
}
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hytime_hires_frequency
/**
* Query OS for clock frequency
* Retrieves the frequency of the high-resolution performance counter.
*
* @param[in] portLibrary The port library.
*
* @return 0 on failure, number of ticks per second on success.
*/
U_64 VMCALL
hytime_hires_frequency (struct HyPortLibrary * portLibrary)
{
return PPG_time_hiresClockFrequency;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hytime_hires_delta
/**
* Calculate time difference between two hires clock timer values @ref hytime_hires_clock.
*
* Given a start and end time determine how much time elapsed. Return the value as
* requested by the required resolution
*
* @param[in] portLibrary The port library.
* @param[in] startTime Timer value at start of timing interval
* @param[in] endTime Timer value at end of timing interval
* @param[in] requiredResolution Returned timer resolution as a fraction of a second. For example:
* \arg 1 to report elapsed time in seconds
* \arg 1,000 to report elapsed time in milliseconds
* \arg 1,000,000 to report elapsed time in microseconds
*
* @return 0 on failure, time difference on success.
*
* @note helper macros are available for commonly requested resolution
* \arg HYPORT_TIME_DELTA_IN_SECONDS return timer value in seconds.
* \arg HYPORT_TIME_DELTA_IN_MILLISECONDS return timer value in milliseconds.
* \arg HYPORT_TIME_DELTA_IN_MICROSECONDS return timer value in micoseconds.
* \arg HYPORT_TIME_DELTA_IN_NANOSECONDS return timer value in nanoseconds.
*/
U_64 VMCALL
hytime_hires_delta (struct HyPortLibrary * portLibrary, U_64 startTime,
U_64 endTime, UDATA requiredResolution)
{
U_64 ticks;
U_64 frequency = PPG_time_hiresClockFrequency;
/* modular arithmetic saves us, answer is always ... */
ticks = endTime - startTime;
if (frequency == requiredResolution)
{
return ticks;
}
if (frequency < requiredResolution)
{
return (ticks * requiredResolution) / frequency;
}
return ticks / (frequency / requiredResolution);
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hytime_shutdown
/**
* PortLibrary shutdown.
*
* This function is called during shutdown of the portLibrary. Any resources that were created by @ref hytime_startup
* should be destroyed here.
*
* @param[in] portLibrary The port library.
*
* @note Most implementations will be empty.
*/
void VMCALL
hytime_shutdown (struct HyPortLibrary *portLibrary)
{
shutdown_timer ();
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hytime_startup
/**
* PortLibrary startup.
*
* This function is called during startup of the portLibrary. Any resources that are required for
* the time operations may be created here. All resources created here should be destroyed
* in @ref hytime_shutdown.
*
* @param[in] portLibrary The port library.
*
* @return 0 on success, negative error code on failure. Error code values returned are
* \arg HYPORT_ERROR_STARTUP_TIME
*
* @note Most implementations will simply return success.
*/
I_32 VMCALL
hytime_startup (struct HyPortLibrary *portLibrary)
{
LARGE_INTEGER freq;
if (QueryPerformanceFrequency (&freq))
{
PPG_time_hiresClockFrequency = freq.QuadPart;
}
else
{
PPG_time_hiresClockFrequency = 1000; /* GetTickCount() returns millis */
}
return init_timer ();
}
#undef CDEV_CURRENT_FUNCTION