diff --git a/code/os/win/win.h b/code/os/win/win.h index 1cebe50..8a0186c 100644 --- a/code/os/win/win.h +++ b/code/os/win/win.h @@ -7,3 +7,5 @@ struct _os_heap { HANDLE handle; }; + +void _os_timing_init(void); \ No newline at end of file diff --git a/code/os/win/win_entry.c b/code/os/win/win_entry.c index 5fa2b44..9d389e1 100644 --- a/code/os/win/win_entry.c +++ b/code/os/win/win_entry.c @@ -35,6 +35,8 @@ static bool convert_wide_chars_to_ansi(char* out, const wchar_t* str, size_t len } void mainCRTStartup() { + _os_timing_init(); + HANDLE heap = GetProcessHeap(); if (heap == NULL) { ExitProcess(-42069); diff --git a/code/os/win/win_time.c b/code/os/win/win_time.c new file mode 100644 index 0000000..b84ea34 --- /dev/null +++ b/code/os/win/win_time.c @@ -0,0 +1,55 @@ +#include +#include +#include "win.h" + +// Store the time since we started running the process +static uint64_t timer_freq; +static uint64_t timer_start; + +int timespec_get(struct timespec *ts, int base) { + if (base != TIME_UTC) return 0; + + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + + ULARGE_INTEGER s = { + .LowPart = ft.dwLowDateTime, + .HighPart = ft.dwHighDateTime + }; + + ULONGLONG t = s.QuadPart - 116444736000000000ULL; + ts->tv_sec = t / 10000000; + ts->tv_nsec = ((int) (t % 10000000)) * 100; + return base; +} + +clock_t clock(void) { + LARGE_INTEGER curr; + if (!QueryPerformanceCounter(&curr)) { + return -1; + } + + // time travel? + if (curr.QuadPart < timer_start) { + return -1; + } + + uint64_t time_from_start = curr.QuadPart - timer_start; + + uint64_t scaled_millis = (time_from_start / timer_freq) * CLOCKS_PER_SEC; + // helps reduce error when doing integer division + scaled_millis += ((time_from_start % timer_freq) * CLOCKS_PER_SEC) / timer_freq; + + return scaled_millis; +} + +void _os_timing_init(void) { + LARGE_INTEGER freq, start; + if (QueryPerformanceFrequency(&freq) && QueryPerformanceCounter(&start)) { + timer_start = start.QuadPart; + timer_freq = freq.QuadPart; + } else { + // failure... + timer_start = timer_freq = UINT64_MAX; + } +} diff --git a/code/printf.h b/code/printf.h index f097aa3..0f71805 100644 --- a/code/printf.h +++ b/code/printf.h @@ -71,6 +71,14 @@ inline static int FMT_FUNC_NAME (void *ctx, OutputFunc out, const FMT_CHAR_TYPE } else { int_length = SHORT; } + } else if (*fmt == 'z') { + fmt++; + + int_length = _Generic((size_t)0, + unsigned short: SHORT, + unsigned int: INT, + unsigned long: LONG, + unsigned long long: LLONG); } FMT_CHAR_TYPE ch = *fmt++; diff --git a/inc/time.h b/inc/time.h index 0fa12e7..2e49983 100644 --- a/inc/time.h +++ b/inc/time.h @@ -1,14 +1,18 @@ - #pragma once +#include #if !defined(NULL) - #define NULL ((void *)0) +#define NULL ((void *)0) #endif // The number of clock ticks per second #define CLOCKS_PER_SEC ((clock_t)1000) + #define TIME_UTC 1 +typedef size_t clock_t; +typedef size_t time_t; + struct timespec { time_t tv_sec; // Seconds - >= 0 long tv_nsec; // Nanoseconds - [0, 999999999] @@ -30,7 +34,7 @@ clock_t clock(void); double difftime(time_t time1, time_t time0); time_t mktime(struct tm *timeptr); time_t time(time_t *timer); -int timespec_get(timespec *ts, int base); +int timespec_get(struct timespec *ts, int base); char *asctime(const struct tm *timeptr); char *ctime(const time_t *timer); struct tm *gmtime(const time_t *timer); @@ -38,8 +42,8 @@ struct tm *localtime(const time_t *timer); size_t strftime(char * restrict s, size_t maxsize, const char * restrict format, const struct tm * restrict timeptr); #ifdef __STDC_WANT_LIB_EXT1__ - errno_t asctime_s(char *s, rsize_t maxsize, const struct tm *timeptr); - errno_t ctime_s(char *s, rsize_t maxsize, const time_t *timer); - struct tm *gmtime_s(const time_t * restrict timer, struct tm * restrict result); - struct tm *localtime_s(const time_t * restrict timer, struct tm * restrict result); +errno_t asctime_s(char *s, rsize_t maxsize, const struct tm *timeptr); +errno_t ctime_s(char *s, rsize_t maxsize, const time_t *timer); +struct tm *gmtime_s(const time_t * restrict timer, struct tm * restrict result); +struct tm *localtime_s(const time_t * restrict timer, struct tm * restrict result); #endif diff --git a/test/test4.c b/test/test4.c index 32187e9..29c4f09 100644 --- a/test/test4.c +++ b/test/test4.c @@ -1,6 +1,7 @@ // https://en.cppreference.com/w/c/algorithm/bsearch #include #include +#include struct data { int nr; @@ -17,9 +18,6 @@ int data_cmp(void const *lhs, void const *rhs) if (l->nr < r->nr) return -1; else if (l->nr > r->nr) return 1; else return 0; - - // return (l->nr > r->nr) - (l->nr < r->nr); // possible shortcut - // return l->nr - r->nr; // erroneous shortcut (fails if INT_MIN is present) } int main(void) @@ -31,4 +29,17 @@ int main(void) } else { printf("No %d not found\n", key.nr); } + + while (clock() <= 3*CLOCKS_PER_SEC) { + printf("%llu seconds\n", clock() / CLOCKS_PER_SEC); + } + + struct timespec start; + timespec_get(&start, TIME_UTC); + + struct timespec ts; + do { + timespec_get(&ts, TIME_UTC); + printf("%zu:%ld\n", ts.tv_sec, ts.tv_nsec); + } while (ts.tv_sec < start.tv_sec+5); }