This directory and its subdirectories contain source and binary files for the timer support packages that can be run across multiple platforms. NOTE: The dll under CR286 can be run under Cruiser only, since it uses the PerfView "thunked" timer. For Sloop/Cutter programs, use the dll under the Sloop directory. This uses the new 16BitTmr.sys, a timer driver. For using the Sloop/Cutter timer, read the section titled "Using the Cutter Timer". The directory is organized as follows: 1) .\ -> a) timer.c (single c source) b) makefile.rst (common for windows, CR286, Sloop and OS2 386 and WOW) c) makefile (for Windows NT) d) sources ( -do- ) e) The header file, timing.h, is under .\inc\. 2) .\win (FOR WINDOWS) a) .\src (contains the .asm files for init and 8253io, and the module def file) b) .\bin (the binary timerwin.dll file) 3) .\WIN32 (FOR Win32 NT) a) .\src (contains the .def file and an i386 sub-dir. that has an asm file) b) .\bin (the binary file) 4) .\Sloop (FOR Sloop apps) a) .\src (contains the initializing .asm file, and the module def file) b) .\bin (the binary timerslp.dll file) 5) .\cr286 (FOR 16 bit OS/2 Cruiser apps) a) .\src (contains the initializing asm file and the module def file) b) .\bin (the binary timer286.dll file) 6) .\os2386 (FOR 32 bit OS/2 Cruiser apps) a) .\src (contains the initializing and math .asm files, and the module def file) b) .\bin (the binary timer386.dll file) 7) .\wow (FOR 16 bit WOW on Windows NT - built for Win 3.0) a) .\src (contains the .asm and the module def file) b) .\bin (the binary timerwow.dll file) ********************************************************************** To Use a timer DLL: ------------------ To use one of the above binaries, please read the USAGE NOTES at the end of this document. Please copy the timing.h file from this directory to the directory where you are building your application. Copy the relevant .dll to your libpath. It is essential that you define the type of system you are building your application for, since the header file uses some special types that are dependent on the system. While compiling your application, add the following flag: -DXXX where XXX stands for one of: WIN - for Windows applications on Windows 3.x. WIN32 - for Win32 applications. WOW16 - for Windows applications on Windows NT. SLOOP - for 16 bit Sloop (OS/2 1.2, 1.3) applications OS2286 - for 16 bit Cruiser (OS/2 2.0) applications OS2386 - for 32 bit OS/2 applications ********************************************************************** To build one of the dlls: ------------------------ If building a Windows, WOW, Sloop, Cutter, CR286 or OS/2 32 bit dll: -------------------------------------------------------------- NOTE: To build for Wow on NT, you must be setup to build for Win 3.0 and not Win 3.1. Also, you need the special Windows libraries. These need to be built on NT. a) Copy the timer.c from this dir. and the timing.h from ..\inc\. to a local directory. b) Also copy the "makefile.rst" from here to the same directory. c) From ???\src copy the remaining files to the local directory, where ??? represents win, Sloop, cr286 or os2386. d) Edit makefile.rst to define the system that you are making the dll for. Eg. if you are making the dll for windows, remove the comment sign (#) from the line "WIN=TRUE" in the makefile and ensure that the other system defines (WOW16, SLOOP, OS2286 and OS2386) are commented out. f) Type "nmake -f makefile.rst" and the dll will be created for you. (Ensure that your development environment is set up for the right system). If building the Win32 dll: ------------------------- a) Copy timer.c, makefile and sources files found under this directory and timing.h from ..\inc\. to a local directory. b) tc the win32\src directory to your local directory. This will create an i386 sub-directory containing an asm file on your local machine. c) From the directory where you have your sources file, type "build -xxx timerw32" from the command line, where xxx represents your target system. It is 386 by default. c) A binary file "timerw32.dll" will be created along with the .obj file under .\xxx\obj where xxx is your target system. It is i386 by default. Using the Cutter Timer: (For use on machines running OS/2 1.2x, 1.3x) ---------------------- Note: This driver cannot be used when the DOS box is running. So edit your config.sys file so that the line "PROTECTONLY=YES" is present. a) Copy the 16BitTmr.* files from the .\sloop\bin directory to your machine. b) Edit your Config.sys file to add the line "DEVICE=xxx\16BitTmr.sys, where xxx is the full path name where the driver resides. c) Copy the timerslp.dll from the .\sloop\bin directory to your libpath. c) Reboot your machine and use the timerslp.dll as explained elsewhere. In case you have any questions, or if you run into any problems, contact vaidy (936-7812). ***************************************************************** USAGE NOTES ----------- This document describes the usage of the functions available through the Timer.dll. This dll can be used by all application programs that require a microsecond timer. Send all comments/suggestions to vaidy (ph. 936-7812) or JohnOw (ph. 936-5557). 1) TimerOpen: --------- Description: Opens a timer object and returns a handle for use in timing operations. #include "timing.h" /* for error codes */ SHORT FAR PASCAL TimerOpen ( SHORT far * phTimer, _TimerUnits TimerUnits ); phTimer - Address to which to return the handle to the timer. TimerUnits - Will be one of the enumerated types listed below, that determines the units for the elapsed time values returned by TimerRead. The selected units may be greater or less than the underlying clock frequency: typedef enum { KILOSECONDS, SECONDS, MILLISECONDS, MICROSECONDS, TENTHMICROSECS, NANOSECONDS, TIMER_FREE } _TimerUnits; Remarks: This call should be made by each application, every time a new timer is required. This call should precede any other timer function calls. Each call to TimerOpen will return a new handle, so that multiple threads within a process may use different timers for measuring time. The handle obtained from this call should be used by the other timing functions, viz. TimerOpen and TimerRead. The handle is an index into an array of timer objects that are made available by this function. The number of timers will depend upon the implementation, but will usually be in the order of 100's or 1000's per process. Use TimerClose to release unused timers in case there is a need to reuse a large number of timers. Any opened timers will be automatically closed when the process using them terminates. The scaling factor decides the units of the time returned by TimerRead. The calling application should be careful over the choice of units, to avoid possible overflow and consequently, incorrect results. Return: 0 if a timer handle is made available. An error code, on failure, which may be one of: TIMERERR_TIMER_NOT_AVAILABLE TIMERERR_NO_MORE_HANDLES TIMERERR_INVALID_UNITS See also: TimerInit, TimerRead, TimerClose. 2) TimerInit: --------- Description: Initializes the elements of an internal structure to the current time, obtained from the low level timer. #include "timing.h" /* for error codes */ SHORT FAR PASCAL TimerInit ( SHORT hTimer ); hTimer - The handle, to the timer, that was made available by a call to TimerOpen. Remarks: This function should be called after opening the timer object. Each call to this function should just precede the operation that is being timed. Passing a handle to a timer object that has not been opened, will result in an error code being returned. Return: 0 if the call is successful. An error code is returned, if the call failed. The error code is: TIMERERR_INVALID_HANDLE See also: TimerOpen, TimerRead, TimerClose. 3) TimerRead: --------- Description: Returns the elapsed time since the previous call to TimerInit. #include "timing.h" /* for error codes */ ULONG FAR PASCAL TimerRead ( SHORT hTimer ); hTimer - handle to the timer object that was opened with a call to TimerOpen and initialized by calling TimerInit. Remarks: This call should have been preceded by a call to TimerOpen and TimerInit. This call gets the current time from the low level timer and, using the initialized values in the internal structure, computes the elapsed time from the previous call to TimerInit. Any number of calls to TimerRead may be made, as long they are preceded by at least one call to TimerInit. A timer overflow error code is returned if the scaling factor was so chosen as to cause an overflow in the time being returned. A bad handle to this call will also result in an error code being returned. Return: A successful call returns the elapsed time since the last call to TimerInit. A failure, either invalid handle or overflow, is indicated by returning the maximum ULONG value (0xffffffff). See also: TimerOpen, TimerInit, TimerClose. 4) TimerClose: ---------- Description: Closes a timer object that was opened with a call to TimerInit. #include "timing.h" SHORT FAR PASCAL TimerClose ( SHORT hTimer ); hTimer - Handle to the timer object that was opened with a call to TimerInit. Remarks: This function closes the specfied timer object and returns it to the pool of available timer objects. The object then is considered as available for use, when a call to TimerOpen is made. Return: 0 if the timer was successfully closed. An error code on failure: TIMERERR_INVALID_HANDLE See also: TimerOpen, TimerInit, TimerRead. ---------------------------------------------------------------------- Usage: ----- Test Application Body: { SHORT hTimerHandle1; SHORT sRetVal; if ((sRetVal = TimerOpen ((SHORT far *) &hTimerHandle1, MICROSECONDS)) { could not open timer Do not perform any timing operation } : : Do Stuff : : /* Commence timing operations */ for (some conditions) { TimerInit (hTimerHandle1); Do Timed Operation ulElapsedTime = TimerRead (hTimerHandle1); } if (TimerClose (hTimerHandle1)) { Could not close timer. Check handle and take corrective action } : : } -------------------------------------------------------------------- Debugging Routine ----------------- 5) TimerReport: ----------- Description: Used as a debugging tool, this routine fetches the the time from the last call to TimerInit and TimerRead. #include "timing.h" /* for error codes */ SHORT BOOL PASCAL TimerReport ( PSZ pszReportString, SHORT hHandleHandle; ); pszReportString - Address to which to return the string containing the time obtained in the last call to TimerInit, TimerRead and the time returned from the last call to TimerRead. hTimerHandle - Handle to the timer from whom the information is sought. Remarks: This call can be used as a debugging device in case there is a doubt as to what values are being returned by the timer. This routine should normally be called after a call to TimerRead. The routines TimerInit and TimerRead call an underlying timer to obtain clock tics/time. The call to TimerRead uses this information and returns the time (clock tics are converted to time using the clock frequency on NT) as a ULONG. TimerReport obtains the information stored by the last call to TimerInit and last call to TimerRead. It also obtains the time that is returned by TimerRead (after converting clock tics to time whereever applicable, and subtracting the overhead) and prints the information into a string whose address is passed in as the first parameter to this routine. The format of the string is as follows: "Init Time %lu:%lu Current Time %lu:%lu Returned Time %lu". Both the times are printed as 64 bit values (high:low). On NT, the init and current times are clock tics while the returned time is in time units. The returned time will be about 0.8 times the difference between the clock tics. Note that the returned time takes into account the calling overhead also and hence, is not exactly the difference between the current time and init time. Return: TRUE if timer exists and has been opened. FALSE otherwise. See also: TimerOpen, TimerInit, TimerRead, TimerClose. ------------------------------------------------------------------------- Additional Routines: ------------------- 6) TimerQueryPerformanceCounter: ---------------------------- Description: Makes the raw counts, (tics), and the timer frequency available. #include "timing.h" /* for error codes */ VOID BOOL PASCAL TimerQueryPerformanceCounter ( PQWORD pCurrentTic, PQWORD pFrequency [OPTIONAL] ); pCurrentTic - Address to a 64-bit location to which the raw tic count is written on returning from the call. PQWORD is defined a PLARGE_INTEGER for the Win32 platform in timing.h. PQWORD is a pointer to a QWORD structure (consisting of two ULONG elements), on Win 3.x and OS/2 platforms. pFrequency - Address to a 64-bit location to which the timer frequency is written on returning from the call, if this pointer is not NULL. This is OPTIONAL. If NULL, only the current tic count is written to the location pointed by pCurrentTic. Remarks: This call can be used by any application to return the timer frequency and current tic count. The frequency needs to be obtained only once. All other calls to this routine can have NULL as the second parameter. The calling application should perform its own calibration to determine the overhead when this routine is called back-to-back. To time an operation, this routine should immediately precede and follow the operation. The difference of the tic counts should be computed. The overhead for calling this routine back to back should be subtracted from this difference, and then divided by the frequency to obtain the time in seconds. (To obtain the time in microseconds, multiply the raw tics by a million before dividing by the frequency. To convert the time to units other than seconds, the conversion factor should be applied before performing the division by the frequency, to avoid loss of precision). There is no need to open or initialize the timer if this routine is used to obtain the tic count. Return: None. See also: TimerOpen, TimerInit, TimerRead, TimerClose. 7) TimerConvertTicsToUSec: ---------------------- Description: Used as a utility tool, this routine returns the time in microseconds when the tic difference and timer frequency are passed in. #include "timing.h" /* for error codes */ ULONG BOOL PASCAL TimerConvertTicsToUSec ( ULONG ulTicDifference, ULONG ulTimerFreq; ); ulTicDifference - The duration of an operation in tics. This is obtained by calling TimerQueryPerformanceCounter immediately before and following the desired operation and subtracting the overhead of calling TimerQueryPerformanceCounter back to back. ulTimerFreq - The timer frequency. This is obtained by calling TimerQueryPerformanceCounter. Remarks: This routine just accepts the duration of an operation in timer counts and the timer frequency. It returns the actual time in microseconds corresponding to the tic count. There is no need to open or initialize the timer if this routine is used to obtain the tic count. Return: The time in microseconds that corresponds to the input tics and frequency. A zero if the frequency is zero. See also: TimerOpen, TimerInit, TimerRead, TimerClose.