OS/2 codes: Implement nano timer

All the OS/2 APIs releated to time, work in milliseconds. But sometimes a more precise timer is needed. How can this timer implemented on OS/2 ?

Fortunately, OS/2 have APIs for this purpose. They are DosTmrQueryCount() and DosTmrQueryFreq(). Let's see their prototype, first.

  • APIRET DosTmrQueryFreq(PULONG pulTmrFreq)
  • APIRET DosTmrQueryTime(PQWORD pqwTmrTime)
These APIs are releated to IRQ0 high resolution timer(Intel 8254). DosTmrQueryFreq() provides its frequency, DosTmrQueryTime provides its time snapshot.

So you can get a time in seconds if you divide a time snapshot by a frequency. And if you multiply this value by 10^9, then you can get a time in nano seconds. That's it.

However, you should be careful. Because the used values are integer numbers. So the reaminder can be ignored when dividing and the overflow can occur when multiplying. To avoid this, you can use 'double'. But if you mind using float pointing numbers, adjust the order of operations carefully. Or use lldiv().

The following is a nano timer implemented using DosTmrQueryFreq() and DosTmrQueryTime().


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
 * NanoTimer, a class to provide a nano-res timer for OS/2
 *
 * Copyright (C) 2014 KO Myung-Hun <komh@chollian.net>
 *
 * This program is free software. It comes without any warranty, to
 * the extent permitted by applicable law. You can redistribute it
 * and/or modify it under the terms of the Do What The Fuck You Want
 * To Public License, Version 2, as published by Sam Hocevar. See
 * http://www.wtfpl.net/ for more details.
 */


#define INCL_DOS
#include <os2.h>

#include <cstdlib>

class NanoTimer
{
public:
    NanoTimer();
    ~NanoTimer();

    typedef long long int NanoClock;

    static const NanoClock NANO_TIME_BASE = 1000LL * 1000LL * 1000LL;

    NanoClock clock();

private:
    unsigned long _freq;
};

NanoTimer::NanoTimer()
{
    ULONG freq;

    DosTmrQueryFreq(&freq);

    _freq = freq;
}

NanoTimer::~NanoTimer()
{
}

NanoTimer::NanoClock NanoTimer::clock()
{
    union
    {
        long long ticks;
        QWORD qwTime;
    } t;

    DosTmrQueryTime(&t.qwTime);

    lldiv_t ns;

    ns = lldiv(t.ticks, _freq);

    return (ns.quot * NANO_TIME_BASE + (ns.rem * NANO_TIME_BASE) / _freq);
}

#include <iostream>

int main()
{
    NanoTimer nt;
    NanoTimer::NanoClock start;
    NanoTimer::NanoClock end;

    start = nt.clock();
    DosSleep(100);
    end = nt.clock();

    std::cout << "Start time = " << start << " ns\n";
    std::cout << "End time = " << end << " ns\n";
    std::cout << "Duration time = " << ((end - start) / 1000.f / 1000.f)
              << " ms\n";

    return 0;
}

댓글

이 블로그의 인기 게시물

토렌트: < 왕좌의 게임 > 시즌 1 ~ 시즌 8 완결편 마그넷

토렌트: < 스타워즈 > Ep.1 ~ Ep.6 마그넷

토렌트: NGC < 코스모스 > 우리말 더빙 전편(1편~13편) 마그넷