time.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #define _XOPEN_SOURCE 700
  2. #include <time.h>
  3. #undef _XOPEN_SOURCE
  4. #include "pocketpy/pocketpy.h"
  5. #include "pocketpy/common/threads.h"
  6. #include <assert.h>
  7. #define NANOS_PER_SEC 1000000000
  8. #ifndef __circle__
  9. int64_t time_ns() {
  10. struct timespec tms;
  11. #ifdef CLOCK_REALTIME
  12. clock_gettime(CLOCK_REALTIME, &tms);
  13. #else
  14. /* The C11 way */
  15. timespec_get(&tms, TIME_UTC);
  16. #endif
  17. /* seconds, multiplied with 1 billion */
  18. int64_t nanos = tms.tv_sec * (int64_t)NANOS_PER_SEC;
  19. /* Add full nanoseconds */
  20. nanos += tms.tv_nsec;
  21. return nanos;
  22. }
  23. #else
  24. int64_t time_ns() { return 0; }
  25. #endif
  26. static bool time_time(int argc, py_Ref argv) {
  27. PY_CHECK_ARGC(0);
  28. int64_t nanos = time_ns();
  29. py_newfloat(py_retval(), (double)nanos / NANOS_PER_SEC);
  30. return true;
  31. }
  32. static bool time_time_ns(int argc, py_Ref argv) {
  33. PY_CHECK_ARGC(0);
  34. int64_t nanos = time_ns();
  35. py_newint(py_retval(), nanos);
  36. return true;
  37. }
  38. static bool time_perf_counter(int argc, py_Ref argv) {
  39. PY_CHECK_ARGC(0);
  40. py_newfloat(py_retval(), (double)clock() / CLOCKS_PER_SEC);
  41. return true;
  42. }
  43. static bool time_sleep(int argc, py_Ref argv) {
  44. PY_CHECK_ARGC(1);
  45. py_f64 secs;
  46. if(!py_castfloat(argv, &secs)) return false;
  47. int64_t start = time_ns();
  48. const int64_t end = start + secs * NANOS_PER_SEC;
  49. while(true) {
  50. int64_t now = time_ns();
  51. if(now >= end) break;
  52. #if PK_ENABLE_THREADS
  53. c11_thrd__yield();
  54. #endif
  55. }
  56. py_newnone(py_retval());
  57. return true;
  58. }
  59. static bool time_localtime(int argc, py_Ref argv) {
  60. PY_CHECK_ARGC(0);
  61. py_Type tp_struct_time = py_gettype("time", py_name("struct_time"));
  62. assert(tp_struct_time);
  63. struct tm* ud = py_newobject(py_retval(), tp_struct_time, 0, sizeof(struct tm));
  64. time_t t = time(NULL);
  65. *ud = *localtime(&t);
  66. return true;
  67. }
  68. #define DEF_STRUCT_TIME__PROPERTY(name, expr) \
  69. static bool struct_time__##name(int argc, py_Ref argv) { \
  70. PY_CHECK_ARGC(1); \
  71. struct tm* tm = py_touserdata(argv); \
  72. py_newint(py_retval(), expr); \
  73. return true; \
  74. }
  75. DEF_STRUCT_TIME__PROPERTY(tm_year, tm->tm_year + 1900)
  76. DEF_STRUCT_TIME__PROPERTY(tm_mon, tm->tm_mon + 1)
  77. DEF_STRUCT_TIME__PROPERTY(tm_mday, tm->tm_mday)
  78. DEF_STRUCT_TIME__PROPERTY(tm_hour, tm->tm_hour)
  79. DEF_STRUCT_TIME__PROPERTY(tm_min, tm->tm_min)
  80. DEF_STRUCT_TIME__PROPERTY(tm_sec, tm->tm_sec)
  81. DEF_STRUCT_TIME__PROPERTY(tm_wday, (tm->tm_wday + 6) % 7)
  82. DEF_STRUCT_TIME__PROPERTY(tm_yday, tm->tm_yday + 1)
  83. DEF_STRUCT_TIME__PROPERTY(tm_isdst, tm->tm_isdst)
  84. #undef DEF_STRUCT_TIME__PROPERTY
  85. void pk__add_module_time() {
  86. py_Ref mod = py_newmodule("time");
  87. py_Type tp_struct_time = py_newtype("struct_time", tp_object, mod, NULL);
  88. py_bindproperty(tp_struct_time, "tm_year", struct_time__tm_year, NULL);
  89. py_bindproperty(tp_struct_time, "tm_mon", struct_time__tm_mon, NULL);
  90. py_bindproperty(tp_struct_time, "tm_mday", struct_time__tm_mday, NULL);
  91. py_bindproperty(tp_struct_time, "tm_hour", struct_time__tm_hour, NULL);
  92. py_bindproperty(tp_struct_time, "tm_min", struct_time__tm_min, NULL);
  93. py_bindproperty(tp_struct_time, "tm_sec", struct_time__tm_sec, NULL);
  94. py_bindproperty(tp_struct_time, "tm_wday", struct_time__tm_wday, NULL);
  95. py_bindproperty(tp_struct_time, "tm_yday", struct_time__tm_yday, NULL);
  96. py_bindproperty(tp_struct_time, "tm_isdst", struct_time__tm_isdst, NULL);
  97. py_bindfunc(mod, "time", time_time);
  98. py_bindfunc(mod, "time_ns", time_time_ns);
  99. py_bindfunc(mod, "perf_counter", time_perf_counter);
  100. py_bindfunc(mod, "sleep", time_sleep);
  101. py_bindfunc(mod, "localtime", time_localtime);
  102. }
  103. #undef NANOS_PER_SEC
  104. #undef DEF_STRUCT_TIME__PROPERTY