#define _XOPEN_SOURCE 700 #include #undef _XOPEN_SOURCE #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #include #undef WIN32_LEAN_AND_MEAN #endif #include "pocketpy/pocketpy.h" #include "pocketpy/common/threads.h" #include #define NANOS_PER_SEC 1000000000 #ifndef __circle__ int64_t time_ns() { #ifdef _WIN32 FILETIME system_time; ULARGE_INTEGER large; GetSystemTimePreciseAsFileTime(&system_time); large.u.LowPart = system_time.dwLowDateTime; large.u.HighPart = system_time.dwHighDateTime; /* 11,644,473,600,000,000,000: number of nanoseconds between the 1st january 1601 and the 1st january 1970 (369 years + 89 leap days). */ return (large.QuadPart - 116444736000000000) * 100; #else struct timespec tms; #ifdef CLOCK_REALTIME clock_gettime(CLOCK_REALTIME, &tms); #else /* The C11 way */ timespec_get(&tms, TIME_UTC); #endif /* seconds, multiplied with 1 billion */ int64_t nanos = tms.tv_sec * (int64_t)NANOS_PER_SEC; /* Add full nanoseconds */ nanos += tms.tv_nsec; return nanos; #endif } int64_t time_monotonic_ns() { #ifdef _WIN32 LARGE_INTEGER now; QueryPerformanceCounter(&now); LONGLONG ticksll = now.QuadPart; static LARGE_INTEGER freq; if(freq.QuadPart == 0) QueryPerformanceFrequency(&freq); /* Convert ticks to nanoseconds */ return (ticksll * NANOS_PER_SEC) / freq.QuadPart; #else struct timespec tms; #ifdef CLOCK_MONOTONIC clock_gettime(CLOCK_MONOTONIC, &tms); #else /* The C11 way */ timespec_get(&tms, TIME_UTC); #endif /* seconds, multiplied with 1 billion */ int64_t nanos = tms.tv_sec * (int64_t)NANOS_PER_SEC; /* Add full nanoseconds */ nanos += tms.tv_nsec; return nanos; #endif } #else int64_t time_ns() { return 0; } int64_t time_monotonic_ns() { return 0; } #endif static bool time_time(int argc, py_Ref argv) { PY_CHECK_ARGC(0); int64_t nanos = time_ns(); py_newfloat(py_retval(), (double)nanos / NANOS_PER_SEC); return true; } static bool time_time_ns(int argc, py_Ref argv) { PY_CHECK_ARGC(0); int64_t nanos = time_ns(); py_newint(py_retval(), nanos); return true; } static bool time_time_monotonic(int argc, py_Ref argv) { PY_CHECK_ARGC(0); int64_t nanos = time_monotonic_ns(); py_newfloat(py_retval(), (double)nanos / NANOS_PER_SEC); return true; } static bool time_time_monotonic_ns(int argc, py_Ref argv) { PY_CHECK_ARGC(0); int64_t nanos = time_monotonic_ns(); py_newint(py_retval(), nanos); return true; } static bool time_perf_counter(int argc, py_Ref argv) { return time_time_monotonic(argc, argv); } static bool time_process_time(int argc, py_Ref argv) { PY_CHECK_ARGC(0); py_newfloat(py_retval(), (double)clock() / CLOCKS_PER_SEC); return true; } static bool time_sleep(int argc, py_Ref argv) { PY_CHECK_ARGC(1); py_f64 secs; if(!py_castfloat(argv, &secs)) return false; int64_t start = time_monotonic_ns(); const int64_t end = start + secs * NANOS_PER_SEC; while(true) { int64_t now = time_monotonic_ns(); if(now >= end) break; #if PK_ENABLE_THREADS c11_thrd__yield(); #endif } py_newnone(py_retval()); return true; } static bool time_localtime(int argc, py_Ref argv) { PY_CHECK_ARGC(0); py_Type tp_struct_time = py_gettype("time", py_name("struct_time")); assert(tp_struct_time); struct tm* ud = py_newobject(py_retval(), tp_struct_time, 0, sizeof(struct tm)); time_t t = time(NULL); *ud = *localtime(&t); return true; } #define DEF_STRUCT_TIME__PROPERTY(name, expr) \ static bool struct_time__##name(int argc, py_Ref argv) { \ PY_CHECK_ARGC(1); \ struct tm* tm = py_touserdata(argv); \ py_newint(py_retval(), expr); \ return true; \ } DEF_STRUCT_TIME__PROPERTY(tm_year, tm->tm_year + 1900) DEF_STRUCT_TIME__PROPERTY(tm_mon, tm->tm_mon + 1) DEF_STRUCT_TIME__PROPERTY(tm_mday, tm->tm_mday) DEF_STRUCT_TIME__PROPERTY(tm_hour, tm->tm_hour) DEF_STRUCT_TIME__PROPERTY(tm_min, tm->tm_min) DEF_STRUCT_TIME__PROPERTY(tm_sec, tm->tm_sec) DEF_STRUCT_TIME__PROPERTY(tm_wday, (tm->tm_wday + 6) % 7) DEF_STRUCT_TIME__PROPERTY(tm_yday, tm->tm_yday + 1) DEF_STRUCT_TIME__PROPERTY(tm_isdst, tm->tm_isdst) #undef DEF_STRUCT_TIME__PROPERTY void pk__add_module_time() { py_Ref mod = py_newmodule("time"); py_Type tp_struct_time = py_newtype("struct_time", tp_object, mod, NULL); py_bindproperty(tp_struct_time, "tm_year", struct_time__tm_year, NULL); py_bindproperty(tp_struct_time, "tm_mon", struct_time__tm_mon, NULL); py_bindproperty(tp_struct_time, "tm_mday", struct_time__tm_mday, NULL); py_bindproperty(tp_struct_time, "tm_hour", struct_time__tm_hour, NULL); py_bindproperty(tp_struct_time, "tm_min", struct_time__tm_min, NULL); py_bindproperty(tp_struct_time, "tm_sec", struct_time__tm_sec, NULL); py_bindproperty(tp_struct_time, "tm_wday", struct_time__tm_wday, NULL); py_bindproperty(tp_struct_time, "tm_yday", struct_time__tm_yday, NULL); py_bindproperty(tp_struct_time, "tm_isdst", struct_time__tm_isdst, NULL); py_bindfunc(mod, "time", time_time); py_bindfunc(mod, "time_ns", time_time_ns); py_bindfunc(mod, "monotonic", time_time_monotonic); py_bindfunc(mod, "monotonic_ns", time_time_monotonic_ns); py_bindfunc(mod, "perf_counter", time_perf_counter); py_bindfunc(mod, "process_time", time_process_time); py_bindfunc(mod, "sleep", time_sleep); py_bindfunc(mod, "localtime", time_localtime); } #undef NANOS_PER_SEC #undef DEF_STRUCT_TIME__PROPERTY