Welcome to mirror list, hosted at ThFree Co, Russian Federation.

clock.h « local_includes « cygwin « winsup - cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 7323299df3b56444e4e0d989676c25a61fe37e29 (plain)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/* clock.h: Definitions for clock calculations

This file is part of Cygwin.

This software is a copyrighted work licensed under the terms of the
Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
details. */

#ifndef __CLOCK_H__
#define __CLOCK_H__

#include <mmsystem.h>

/* Must be a power of 2. */
#define MAX_CLOCKS		 (16)

/* Conversions for per-process and per-thread clocks */
#define CLOCKID(cid) \
		((cid) % MAX_CLOCKS)
#define PID_TO_CLOCKID(pid) \
		((pid) * MAX_CLOCKS + CLOCK_PROCESS_CPUTIME_ID)
#define CLOCKID_TO_PID(cid) \
		(((cid) - CLOCK_PROCESS_CPUTIME_ID) / MAX_CLOCKS)
#define CLOCKID_IS_PROCESS(cid) \
		(CLOCKID(cid) == CLOCK_PROCESS_CPUTIME_ID)
#define THREADID_TO_CLOCKID(tid) \
		((tid) * MAX_CLOCKS + CLOCK_THREAD_CPUTIME_ID)
#define CLOCKID_TO_THREADID(cid) \
		(((cid) - CLOCK_THREAD_CPUTIME_ID) / MAX_CLOCKS)
#define CLOCKID_IS_THREAD(cid) \
		(CLOCKID(cid) == CLOCK_THREAD_CPUTIME_ID)

/* Largest delay in ms for sleep and alarm calls.
   Allow actual delay to exceed requested delay by 10 s.
   Express as multiple of 1000 (i.e. seconds) + max resolution
   The tv_sec argument in timeval structures cannot exceed
   CLOCK_DELAY_MAX / 1000 - 1, so that adding fractional part
   and rounding won't exceed CLOCK_DELAY_MAX */
#define CLOCK_DELAY_MAX ((((UINT_MAX - 10000) / 1000) * 1000) + 10)

/* 100ns difference between Windows and UNIX timebase. */
#define FACTOR (0x19db1ded53e8000LL)
/* # of nanosecs per second. */
#define NSPERSEC (1000000000LL)
/* # of 100ns intervals per second. */
#define NS100PERSEC (10000000LL)
/* # of microsecs per second. */
#define USPERSEC (1000000LL)
/* # of millisecs per second. */
#define MSPERSEC (1000L)

class clk_t
{
 protected:
  /* Some values are returned as ticks/s, some as 100ns period of a
     single tick.  Store the original value and use a computation method
     making the most sense for the value given, to avoid rounding issues. */
  union
    {
      LONGLONG ticks_per_sec;
      LONGLONG period;
    };
  void init ();
  virtual int now (clockid_t, struct timespec *) = 0;

 public:
  int nsecs (clockid_t _id, struct timespec *ts)
  {
    return now (_id, ts);
  }
  virtual void resolution (struct timespec *);

  /* shortcuts for non-process/thread clocks */
  void nsecs (struct timespec *ts)
  {
    now (0, ts);
  }
  ULONGLONG nsecs ()
  {
    struct timespec ts;
    now (0, &ts);
    return (ULONGLONG) ts.tv_sec * NSPERSEC + ts.tv_nsec;
  }
  LONGLONG n100secs ()
  {
    struct timespec ts;
    now (0, &ts);
    return ts.tv_sec * NS100PERSEC + ts.tv_nsec / (NSPERSEC/NS100PERSEC);
  }
  LONGLONG usecs ()
  {
    struct timespec ts;
    now (0, &ts);
    return ts.tv_sec * USPERSEC + ts.tv_nsec / (NSPERSEC/USPERSEC);
  }
  LONGLONG msecs ()
  {
    struct timespec ts;
    now (0, &ts);
    return ts.tv_sec * MSPERSEC + ts.tv_nsec / (NSPERSEC/MSPERSEC);
  }
};

class clk_realtime_coarse_t : public clk_t
{
  virtual int now (clockid_t, struct timespec *);
};

class clk_realtime_t : public clk_t
{
  void init ();
  virtual int now (clockid_t, struct timespec *);
 public:
  virtual void resolution (struct timespec *);
};

class clk_process_t : public clk_t
{
  virtual int now (clockid_t, struct timespec *);
};

class clk_thread_t : public clk_t
{
  virtual int now (clockid_t, struct timespec *);
};

class clk_monotonic_t : public clk_t
{
 protected:
  void init ();
 private:
  virtual int now (clockid_t, struct timespec *);
 public:
  virtual void resolution (struct timespec *);
  /* Under strace 1st call is so early that vtable is NULL. */
  LONGLONG strace_usecs ()
  {
    struct timespec ts;
    clk_monotonic_t::now (0, &ts);
    return ts.tv_sec * USPERSEC + ts.tv_nsec / (NSPERSEC/USPERSEC);
  }
};

class clk_monotonic_coarse_t : public clk_t
{
  virtual int now (clockid_t, struct timespec *);
};

class clk_boottime_t : public clk_monotonic_t
{
  virtual int now (clockid_t, struct timespec *);
};

clk_t *get_clock (clockid_t clk_id);

/* Compute interval between two timespec timestamps: ts1  = ts1 - ts0. */
static inline void
ts_diff (const struct timespec &ts0, struct timespec &ts1)
{
  ts1.tv_nsec -= ts0.tv_nsec;
  if (ts1.tv_nsec < 0)
    {
      ts1.tv_nsec += NSPERSEC;
      --ts1.tv_sec;
    }
  ts1.tv_sec -= ts0.tv_sec;
}

static inline bool
valid_timespec (const timespec& ts)
{
  if (ts.tv_nsec < 0 || ts.tv_nsec >= NSPERSEC || ts.tv_sec < 0)
    return false;
  return true;
}

#endif /*__CLOCK_H__*/