tai.html (20525B)
1 <html> 2 <head> 3 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 5 <meta http-equiv="Content-Language" content="en" /> 6 <title>skalibs: the tai library interface</title> 7 <meta name="Description" content="skalibs: the tai library interface" /> 8 <meta name="Keywords" content="skalibs c unix tai library libstddjb" /> 9 <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> --> 10 </head> 11 <body> 12 13 <p> 14 <a href="index.html">libstddjb</a><br /> 15 <a href="../libskarnet.html">libskarnet</a><br /> 16 <a href="../index.html">skalibs</a><br /> 17 <a href="//skarnet.org/software/">Software</a><br /> 18 <a href="//skarnet.org/">skarnet.org</a> 19 </p> 20 21 <h1> The <tt>tai</tt> library interface </h1> 22 23 <p> 24 The following functions are declared in the <tt>skalibs/tai.h</tt> header, 25 and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library. 26 </p> 27 28 <h2> General information </h2> 29 30 <p> 31 <tt>tai</tt> is a set of data structures and primitives to represent 32 and perform operations on time. 33 </p> 34 35 <p> 36 The point of <tt>tai</tt> is to handle time without ever having to 37 deal with annoyances such as Y2K, Y2038, NTP limits, non-linear 38 clocks, and the like. By using the <tt>tai</tt> interface, you ensure 39 your program will behave properly no matter what. 40 </p> 41 42 <h3> What is the problem ? </h3> 43 44 <p> 45 The standard APIs for time management under Unix are broken in more 46 or less subtle ways. The most obvious thing is that they do not pass 47 year 2038. A less obvious problem is that they do not handle leap 48 seconds correctly. Here are a few references you should read to 49 understand what is going on: 50 </p> 51 52 <ul> 53 <li> <a href="http://www.madore.org/~david/misc/time.html">David Madore's page 54 on time</a>. It's outdated (there was a leap second in 2009), but complete. </li> 55 <li> From David Madore again, more to the point: a 56 <a href="http://www.madore.org/~david/computers/unix-leap-seconds.html">page 57 about leap seconds, UTC and TAI</a>. </li> 58 <li> The skalibs <a href="../flags.html#clockistai">--enable-tai-clock</a> 59 documentation. </li> 60 <li> <a href="https://cr.yp.to/proto/utctai.html">Dan J. Bernstein's page 61 on UTC, TAI and Unix time</a>. </li> 62 </ul> 63 64 <p> 65 The meat and potatoes of all this is that programmers cannot simply rely on 66 standard Unix APIs such as 67 <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/gettimeofday.html">gettimeofday()</a> 68 (which, by the way, is marked as obsolescent, but it's not going to disappear tomorrow) 69 to measure time intervals or even to give precise absolute time, and in 70 any case those APIs will become obsolete in 2038. 71 </p> 72 73 <h3> So what does <tt>tai</tt> do ? </h3> 74 75 <p> 76 <tt>tai</tt> implements - among other things - the 77 <a href="https://cr.yp.to/libtai/tai64.html">TAI64 and TAI64N</a> 78 formats, which are used in all of skalibs. This gives a programmer access 79 to precise <em>linear absolute time</em>, which is suitable for both 80 timestamping (<em>wallclock</em> usage) and time interval measurements 81 (<em>stopwatch</em> usage). Additionally, TAI64 passes Y2038 (it can 82 represent dates exceeding the estimated lifespan of the universe). 83 </p> 84 85 <p> 86 <tt>tai</tt> has been inspired by Dan J. Bernstein's 87 <a href="https://cr.yp.to/libtai.html">libtai</a> library, but does not 88 borrow any code from it. 89 </p> 90 91 <h2> Data structures </h2> 92 93 <p> 94 A <tt>tai</tt> structure holds an absolute date with a one-second 95 precision. A <tt>tain</tt> structure holds an absolute date with a 96 maximum of one-nanosecond precision, as permitted by the underlying system 97 call. If <a href="../flags.html#usert">flag-usert</a> is clear, the system 98 clock will be read via 99 <a href="https://www.opengroup.org/onlinepubs/9699919799/functions/gettimeofday.html">gettimeofday()</a> 100 system call, which has a one-microsecond precision; if it is set, the 101 system clock will be read via the 102 <a href="https://www.opengroup.org/onlinepubs/9699919799/functions/clock_gettime.html">clock_gettime()</a> 103 system call, which has a one-nanosecond precision. In either case, a current 104 <tt>tain</tt> will be unable to be more precise than the underlying 105 implementation. 106 </p> 107 108 <p> 109 A <tt>tai</tt>, as well as a <tt>tain</tt>, can also 110 hold a (possibly negative) relative time, i.e. a difference of absolute 111 dates. It is up to the programmer to make sure that a relative time is 112 never interpreted as an absolute TAI64 date, and vice-versa. 113 </p> 114 115 <h2> Functions </h2> 116 117 <h3> Wallclock operations </h3> 118 119 <p> 120 <code> int tai_now (tai *t) </code> <br /> 121 Writes the current time as a TAI value to *<em>t</em>, with a 122 1-second precision. The current time is based on the system clock. 123 Make sure skalibs has been compiled with or without the 124 <a href="../flags.html#clockistai">--enable-tai-clock</a> configure option according 125 to your system clock synchronization method: skalibs supports a 126 system clock set to TAI-10 or to UTC. 127 The function returns 1 if it succeeds, or 0 (and sets errno) if 128 it fails. 129 </p> 130 131 <p> 132 <code> int sysclock_get (tain *a) </code> <br /> 133 Reads the current value of the system clock (as in CLOCK_REALTIME) into *<em>a</em>. 134 Returns 1 if it succeeds or 0 (and sets errno) if it fails. 135 Note that despite being a <tt>tain</tt>, *<em>a</em> 136 <strong>does not contain a TAI value</strong> - it only contains 137 an internal, Y2038-safe representation of the value of the system 138 clock, which should be either TAI-10 or UTC. You should not use 139 this function directly unless you know exactly what you are doing. 140 </p> 141 142 <p> 143 <code> int sysclock_set (tain const *a) </code> <br /> 144 Sets the system clock to *<em>a</em>, provided *<em>a</em> has 145 the correct internal representation. You should not use this 146 function directly unless you know exactly what you are doing. 147 </p> 148 149 <p> 150 <code> int tain_wallclock_read (tain *a) </code> <br /> 151 Reads the current time into *<em>a</em>, as a TAI64N value. 152 Returns 1 if it succeeds or 0 (and sets errno) if it fails. 153 Here <em>a</em> contains a valid TAI64N stamp, no matter what the 154 system clock is set to: arithmetic operations can be performed 155 on it. 156 </p> 157 158 <p> 159 <code> int tain_setnow (tain const *a) </code> <br /> 160 Sets the current time to *<em>a</em>. 161 Returns 1 if it succeeds or 0 (and sets errno) if it fails. 162 <em>a</em> must contain a valid TAI64N stamp; proper 163 operations will be automatically run to convert that stamp into 164 the right format for the system clock. 165 </p> 166 167 <p> 168 <code> int tain_now_set_wallclock (tain *a) </code> <br /> 169 Tells skalibs that future invocations of <tt>tain_now()</tt> 170 (see below) should use a wall clock, i.e. the system time 171 as returned by <tt>clock_gettime(CLOCK_REALTIME)</tt> or 172 <tt>gettimeofday()</tt>. Also reads the current time into *<em>a</em>. 173 Returns 1 if it succeeds or 0 (and sets errno) if it fails. 174 A wall clock is the default: it is not necessary 175 to call this function before invoking <tt>tain_now()</tt> at the 176 start of a program. 177 </p> 178 179 <h3> Stopwatch operations </h3> 180 181 <p> 182 The following two operations can only succeed if your system provides the 183 <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_gettime.html">clock_gettime()</a> 184 primitive with at least one of the CLOCK_MONOTONIC or CLOCK_BOOTTIME clocks. 185 Otherwise, they will fail with errno set to ENOSYS. 186 </p> 187 188 <p> 189 <code> int tain_stopwatch_init (tain *a, clock_t cl, tain *offset) </code> <br /> 190 Initializes a stopwatch in *<em>offset</em>, using a clock named <em>cl</em>. 191 Typically, <em>cl</em> is something like CLOCK_MONOTONIC, when it is defined 192 by the system. The actual value of 193 *<em>offset</em> is meaningless to the user; <em>offset</em>'s only 194 use is to be given as a second parameter to <tt>tain_stopwatch_read()</tt>. 195 The function returns 1 if it succeeds or 0 (and sets errno) if it fails. 196 On success, the current time, as given by the <em>system clock</em> (a 197 wall clock), is returned in *<em>a</em>. 198 </p> 199 200 <p> 201 What <tt>tain_stopwatch_init()</tt> does is synchronize the "stopwatch 202 clock" to the system clock. Right after <tt>tain_stopwatch_init()</tt> 203 has been called, the absolute times given 204 by <tt>tain_stopwatch_read()</tt> and <tt>tain_wallclock_read()</tt> are 205 the same. Then, depending on the accuracy of the system clock, a drift 206 may appear; calling <tt>tain_stopwatch_init()</tt> again resets that drift 207 to zero. 208 </p> 209 210 <p> 211 <code> int tain_stopwatch_read (tain *a, clock_t cl, tain const *offset) </code> <br /> 212 Gives the absolute time, as a TAI64N value, in *<em>a</em>. This 213 absolute time is computed as a linear increase (as measured with 214 the <em>cl</em> clock, which should be a monotonic clock such as 215 CLOCK_MONOTONIC) since the last time <tt>tain_stopwatch_init()</tt> 216 was called with parameter <em>offset</em>. <tt>tain_stopwatch_read()</tt> 217 guarantees precise time interval measurements; however, the time it 218 gives can slightly differ from the result of <tt>tain_wallclock_read()</tt>. 219 The function returns 1 if it succeeds or 0 (and sets errno) if it fails. 220 </p> 221 222 <p> 223 <code> int tain_now_set_stopwatch (tain *a) </code> <br /> 224 Tells skalibs that future invocations of <tt>tain_now()</tt> 225 (see below) should use a stopwatch, i.e. the system time 226 as returned by <tt>clock_gettime(CLOCK_MONOTONIC)</tt> or similar, 227 if supported by the system. This is useful when it is more important 228 for a program to compute unchanging time intervals no matter what the 229 system clock does, than to display absolute time that is in sync with a 230 human view of time (which is the cause and reason of most system clock 231 jumps). <br /> 232 If no monotonic clock is supported by the system, this function does 233 not change what <tt>tain_now()</tt> refers to (i.e. it will keep 234 referring to the system clock). <br /> 235 Returns 1 on success and 0 (and sets errno) on failure. On success, 236 the current time, as given by the <em>system clock</em> (a wall clock), 237 is returned in *<em>a</em>. 238 </p> 239 240 <h3> All-purpose time reading </h3> 241 242 <p> 243 <code> int tain_now (tain *a) </code> <br /> 244 Writes the current time, as a TAI value, to *<em>a</em>. This is the 245 function you should use by default. It returns 1 if it succeeds or 246 0 (and sets errno) if it fails. 247 </p> 248 249 <p> 250 <tt>tain_now()</tt> relies on the concept that there is One True Time Source 251 for the process, and that is where it reads time from. By default, the 252 One True Time Source is the system clock (a wall clock), and <tt>tain_now()</tt> 253 is actually an alias to <tt>tain_wallclock_read()</tt>. At the start of a 254 program, calling <tt>tain_now_set_stopwatch()</tt> will define a monotonic 255 clock (if supported by the system) as the One True Time Source, which will 256 make <tt>tain_now()</tt> resistant to system clock jumps, but will also 257 make it unsuitable for timestamping. 258 </p> 259 260 <p> 261 In other words: the <em>first</em> time you need to read the clock, or 262 at the start of your program, you should use 263 <tt>tain_now_set_wallclock()</tt> or <tt>tain_now_set_stopwatch()</tt> 264 depending on whether you want the One True Time Source to be the system 265 clock (CLOCK_REALTIME or <tt>gettimeofday()</tt>) or a stopwatch 266 (CLOCK_MONOTONIC, if supported). Afterwards, every time you need to read 267 from that time source, use <tt>tain_now()</tt>. skalibs functions that 268 may block, such as <tt>iopause_g</tt>, internally call <tt>tain_now()</tt> 269 to update the timestamp they're using, so they will use the time source 270 you have defined. (Functions ending in <tt>_g</tt> 271 use the STAMP global variable to store the current timestamp.) 272 </p> 273 274 275 <h3> Converting to/from libc representations </h3> 276 277 <p> 278 The following functions only convert from a certain structure 279 format to another; they do not make any assumption about the 280 format of the time contained in those structures. For instance, 281 for the <tt>tai_from_timeval</tt> function, if the struct timeval 282 contains an absolute UTC time, then the tai will also contain 283 the same UTC time. Despite being a tai, it may contain 284 something else than TAI time. 285 </p> 286 287 <p> 288 If you need conversion from the native machine 289 system clock format to TAI, see the next section. 290 </p> 291 292 <p> 293 <code> int tai_from_time (tai *t, time_t u) <br /> 294 int tai_relative_from_time (tai *t, time_t u) </code> <br /> 295 Those functions convert an absolute (resp. relative) time in a 296 time_t to an absolute (resp. relative) 297 time in a tai, with a 1-second precision. They return 1, 298 unless the time_t value is invalid (in which case they return 0). 299 </p> 300 301 <p> 302 <code> int time_from_tai (time_t *u, tai const *t) <br /> 303 int time_from_tai_relative (time_t *u, tai const *t) </code> <br /> 304 The inverse functions of the previous ones. Be aware that 305 time_t is 32 bits on some systems and cannot store all values 306 of a tai (in which case the functions will return 0 EOVERFLOW). 307 </p> 308 309 <p> 310 <code> int tain_from_timeval (tain *a, struct timeval const *tv) <br /> 311 int tain_relative_from_timeval (tain *a, struct timeval const *tv) <br /> 312 int tain_from_timespec (tain *a, struct timespec const *ts) <br /> 313 int tain_relative_from_timespec (tain *a, struct timespec const *ts) <br /> 314 int timeval_from_tain (struct timeval *tv, tain const *a) <br /> 315 int timeval_from_tain_relative (struct timeval *tv, tain const *a) <br /> 316 int timespec_from_tain (struct timespec *ts, tain const *a) <br /> 317 int timespec_from_tain_relative (struct timespec *ts, tain const *a) </code> <br /> 318 Same conversion operations, between <tt>tain</tt> and a 319 <tt>struct timeval</tt> or <tt>struct timespec</tt>. The 1-microsecond 320 (for <tt>struct timeval</tt>) or 1-nanosecond (for <tt>struct timespec</tt>) 321 precision is preserved. 322 </p> 323 324 <h3> Conversion between TAI and the system clock format </h3> 325 326 <p> 327 Unlike the previous functions, the functions listed here will 328 always operate on valid absolute timestamps. Only TAI64 time is 329 stored in tai structures, and only TAI64N time is stored in 330 tain structures. These functions will convert to/from TAI, 331 from/to the machine system clock format, i.e. TAI-10 or UTC 332 depending on whether skalibs was 333 compiled with the --enable-tai-clock configure option). 334 This is useful to get valid TAI/TAI64N timestamps out of 335 information exported by the system, for instance the time_t 336 returned by <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/time.html">time()</a>, 337 or in the <tt>st_atim</tt>, <tt>st_mtim</tt> or 338 <tt>st_ctim</tt> fields of a <tt>struct stat</tt>. 339 </p> 340 341 <p> 342 The functions return 1 in case of success, or 0 if the conversion 343 could not be performed; in which case errno is set to EINVAL if 344 the input argument was not a valid timestamp, to EOVERFLOW if the 345 output could not be represented in the chosen format (which may 346 happen on systems with a 32 bit <tt>time_t</tt>), or other error 347 codes. 348 </p> 349 350 <code> int tai_from_time_sysclock (tai *a, time_t t) <br /> 351 int time_sysclock_from_tai (time_t *t, tai const *a) <br /> 352 int tain_from_timeval_sysclock (tain *a, struct timeval const *tv) <br /> 353 int timeval_sysclock_from_tain (struct timeval *tv, tain const *a) <br /> 354 int tain_from_timespec_sysclock (tain *a, struct timespec const *ts) <br /> 355 int timespec_sysclock_from_tain (struct timespec *ts, tain const *a) </code> 356 357 <h3> Conversions to/from basic types </h3> 358 359 <p> 360 <code> int tain_uint (tain *a, unsigned int c) </code> <br /> 361 Stores a relative time of <em>c</em> seconds into <em>a</em>. 362 Normally returns 1, but may return 0 EINVAL on pathological numbers. 363 </p> 364 365 <p> 366 <code> int tain_from_millisecs (tain *a, int ms) </code> <br /> 367 This function makes a <tt>tain</tt> representing a relative 368 time of <em>ms</em> milliseconds. <em>ms</em> must be non-negative. 369 The function returns 1, unless <em>ms</em> is negative, in which case 370 it returns 0 EINVAL. 371 </p> 372 373 <p> 374 <code> int taino_millisecs (tain const *a) </code> <br /> 375 If *<em>a</em> contains a non-negative relative time that fits into 376 a 31-bit integer number of milliseconds, the function returns that 377 number. Else it returns -1 EINVAL. 378 </p> 379 380 <h3> Time computations </h3> 381 382 <p> 383 <code> int tai_add (tai *t, tai const *t1, tai const *t2) </code> <br /> 384 Stores *<em>t1</em> + *<em>t2</em> into <em>t</em>. Of course, *<em>t1</em> 385 and *<em>t2</em> must not both represent absolute times. 386 The function normally returns 1, but will return 0 on bad inputs. 387 </p> 388 389 <p> 390 <code> int tai_sub (tai *t, tai const *t1, tai const *t2) </code> <br /> 391 Stores *<em>t1</em> - *<em>t2</em> into <em>t</em>. *<em>t1</em> cannot 392 be relative if *<em>t2</em> is absolute. If they are both relative or 393 both absolute, then *<em>t</em> is relative, else it's absolute. 394 The function normally returns 1, but will return 0 on bad inputs. 395 </p> 396 397 <p> 398 <code> int tain_add (tain *a, tain const *a1, tain const *a2) <br /> 399 int tain_sub (tain *a, tain const *a1, tain const *a2) </code> <br /> 400 Same thing with <tt>tain</tt>. 401 </p> 402 403 <p> 404 <code> int tain_addsec (tain *a, tain const *a1, int c) </code> <br /> 405 Adds <em>c</em> seconds to *<em>a1</em> and stores the result into <em>a</em>. 406 <em>c</em> may be negative. 407 </p> 408 409 <p> 410 <code> void tain_half (tain *a, tain const *b) </code> <br /> 411 Stores *<em>b</em>/2 into <em>a</em>. *<em>b</em> must be relative. 412 </p> 413 414 <h3> Comparing dates or durations </h3> 415 416 <p> 417 <code> int tai_less (tai const *t1, tai const *t2) <br /> 418 int tain_less (tain const *t1, tain const *t2) </code> <br /> 419 Those functions return nonzero iff *<em>t1</em> is lesser than *<em>t2</em>. 420 *<em>t1</em> and *<em>t2</em> must be both relative, or both absolute. 421 </p> 422 423 <h3> Packing and unpacking </h3> 424 425 <p> 426 <code> void tai_pack (char *s, tai const *t) </code> <br /> 427 Marshals *<em>t</em> into the buffer <em>s</em> points to, which 428 must be preallocated with at least TAI_PACK (8) characters. Afterwards, 429 the buffer contains the 430 <a href="https://cr.yp.to/libtai/tai64.html#tai64">external TAI64 format</a> 431 representation of *<em>t</em>. 432 </p> 433 434 <p> 435 <code> void tai_unpack (char const *s, tai *t) </code> <br /> 436 Unmarshals the 437 <a href="https://cr.yp.to/libtai/tai64.html#tai64">external TAI64 format</a> 438 label pointed to by <em>s</em> (at least TAI_PACK characters) and stores 439 the result into <em>t</em>. 440 </p> 441 442 <p> 443 <code> void tain_pack (char *s, tain const *a) <br /> 444 void tain_unpack (char const *s, tain *a) </code> <br /> 445 Same thing with 446 <a href="https://cr.yp.to/libtai/tai64.html#tai64n">external TAI64N format</a>, 447 using TAIN_PACK (12) characters. 448 </p> 449 450 <h3> Formatting and scanning </h3> 451 452 <p> 453 <code> unsigned int tain_fmt (char *s, tain const *a) </code> <br /> 454 Writes into <em>s</em> an ASCII representation of *<em>a</em> in external 455 TAI64N format. <em>s</em> must point to a preallocated buffer of at least 456 TAIN_PACK*2 (24) characters. The function returns the number of bytes that 457 have been written to <em>s</em> (24). 458 </p> 459 460 <p> 461 <code> unsigned int tain_scan (char const *s, tain *a) </code> <br /> 462 Reads 24 characters from <em>s</em>; if those characters are a valid ASCII 463 representation of the external TAI64N format of some time value, this value 464 is stored into <em>a</em>, and 24 is returned. Else 0 is returned. 465 </p> 466 467 <a name="timestamp"><h3> Timestamping </h3></a> 468 469 <p> 470 A <em>TAI64N timestamp</em> is a string of 25 characters: a single '@' 471 character followed by the ASCII representation of the TAI64N external 472 format of an absolute date. 473 </p> 474 475 <p> 476 <code> unsigned int timestamp_fmt (char *s, tain const *a) </code> <br /> 477 Writes a TAI64N timestamp representing the absolute date *<em>a</em> 478 into the 25 characters pointed to by <em>s</em>. Returns 25. 479 </p> 480 481 <p> 482 <code> unsigned int timestamp_scan (char const *s, tain *a) </code> <br /> 483 Reads 25 characters at <em>s</em>. If those characters are a valid TAI64N 484 timestamp, stores the absolute date in <em>a</em> and returns 25. Else, 485 returns 0. 486 </p> 487 488 <p> 489 <code> int timestamp (char *s) </code> <br /> 490 Writes the current time (read from the system clock) as a TAI64N timestamp 491 into <em>s</em>. Returns 1 if it succeeds or 0 (and sets errno) if it fails. 492 </p> 493 494 <p> 495 TAI64N timestamps are an efficient, robust, and easy-to-use way of 496 timestampping log lines. They're easy to recognize in automatic data 497 parsers. Log files where every line starts with a TAI64N timestamp can 498 be merged and alphanumerically sorted: the resulting file will be 499 chronologically sorted. 500 </p> 501 502 <p> 503 The <a href="//skarnet.org/software/s6/">s6</a> package 504 provides tools to convert TAI64N timestamps into human-readable 505 dates. Please do not embed human-readable dates in your log files, 506 thus making parsing tools unnecessarily hard to write; 507 use TAI64N timestamps instead, design tools that can parse them, 508 and translate them to human-readable form at human analysis time. 509 </p> 510 511 </body> 512 </html>