time.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include <u.h>
  2. #include <libc.h>
  3. #include "realtime.h"
  4. #include "time.h"
  5. Ticks fasthz;
  6. static uvlong
  7. uvmuldiv(uvlong x, ulong num, ulong den)
  8. {
  9. /* multiply, then divide, avoiding overflow */
  10. uvlong hi;
  11. hi = (x & 0xffffffff00000000LL) >> 32;
  12. x &= 0xffffffffLL;
  13. hi *= num;
  14. return (x*num + (hi%den << 32)) / den + (hi/den << 32);
  15. }
  16. Time
  17. ticks2time(Ticks ticks)
  18. {
  19. assert(ticks >= 0);
  20. return uvmuldiv(ticks, Onesecond, fasthz);
  21. }
  22. Ticks
  23. time2ticks(Time time)
  24. {
  25. assert(time >= 0);
  26. return uvmuldiv(time, fasthz, Onesecond);
  27. }
  28. int
  29. timeconv(Fmt *f)
  30. {
  31. char buf[128], *sign;
  32. Time t;
  33. Ticks ticks;
  34. buf[0] = 0;
  35. switch(f->r) {
  36. case 'U':
  37. ticks = va_arg(f->args, Ticks);
  38. t = ticks2time(ticks);
  39. break;
  40. case 'T': // Time in nanoseconds
  41. t = va_arg(f->args, Time);
  42. break;
  43. default:
  44. return fmtstrcpy(f, "(timeconv)");
  45. }
  46. if (t < 0) {
  47. sign = "-";
  48. t = -t;
  49. }
  50. else
  51. sign = "";
  52. if (t > Onesecond)
  53. sprint(buf, "%s%d.%.3ds", sign, (int)(t / Onesecond), (int)(t % Onesecond)/1000000);
  54. else if (t > Onemillisecond)
  55. sprint(buf, "%s%d.%.3dms", sign, (int)(t / Onemillisecond), (int)(t % Onemillisecond)/1000);
  56. else if (t > Onemicrosecond)
  57. sprint(buf, "%s%d.%.3dµs", sign, (int)(t / Onemicrosecond), (int)(t % Onemicrosecond));
  58. else
  59. sprint(buf, "%s%dns", sign, (int)t);
  60. return fmtstrcpy(f, buf);
  61. }
  62. char *
  63. parsetime(Time *rt, char *s)
  64. {
  65. uvlong ticks;
  66. ulong l;
  67. char *e, *p;
  68. static int p10[] = {100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
  69. if (s == nil)
  70. return("missing value");
  71. ticks=strtoul(s, &e, 10);
  72. if (*e == '.'){
  73. p = e+1;
  74. l = strtoul(p, &e, 10);
  75. if(e-p > nelem(p10))
  76. return "too many digits after decimal point";
  77. if(e-p == 0)
  78. return "ill-formed number";
  79. l *= p10[e-p-1];
  80. }else
  81. l = 0;
  82. if (*e == '\0' || strcmp(e, "s") == 0){
  83. ticks = 1000000000 * ticks + l;
  84. }else if (strcmp(e, "ms") == 0){
  85. ticks = 1000000 * ticks + l/1000;
  86. }else if (strcmp(e, "µs") == 0 || strcmp(e, "us") == 0){
  87. ticks = 1000 * ticks + l/1000000;
  88. }else if (strcmp(e, "ns") != 0)
  89. return "unrecognized unit";
  90. *rt = ticks;
  91. return nil;
  92. }