diff --git a/Makefile.in b/Makefile.in index 1ac6f292..c4f8cf90 100644 --- a/Makefile.in +++ b/Makefile.in @@ -85,8 +85,8 @@ C_SRCS := $(srcroot)src/jemalloc.c $(srcroot)src/arena.c \ $(srcroot)src/extent.c $(srcroot)src/hash.c $(srcroot)src/huge.c \ $(srcroot)src/mb.c $(srcroot)src/mutex.c $(srcroot)src/pages.c \ $(srcroot)src/prof.c $(srcroot)src/quarantine.c $(srcroot)src/rtree.c \ - $(srcroot)src/stats.c $(srcroot)src/tcache.c $(srcroot)src/util.c \ - $(srcroot)src/tsd.c + $(srcroot)src/stats.c $(srcroot)src/tcache.c $(srcroot)src/time.c \ + $(srcroot)src/tsd.c $(srcroot)src/util.c ifeq ($(enable_valgrind), 1) C_SRCS += $(srcroot)src/valgrind.c endif @@ -143,6 +143,7 @@ TESTS_UNIT := $(srcroot)test/unit/atomic.c \ $(srcroot)test/unit/SFMT.c \ $(srcroot)test/unit/size_classes.c \ $(srcroot)test/unit/stats.c \ + $(srcroot)test/unit/time.c \ $(srcroot)test/unit/tsd.c \ $(srcroot)test/unit/util.c \ $(srcroot)test/unit/zero.c diff --git a/include/jemalloc/internal/jemalloc_internal.h.in b/include/jemalloc/internal/jemalloc_internal.h.in index 8c507f79..e7bc4c84 100644 --- a/include/jemalloc/internal/jemalloc_internal.h.in +++ b/include/jemalloc/internal/jemalloc_internal.h.in @@ -356,6 +356,7 @@ typedef unsigned szind_t; # define VARIABLE_ARRAY(type, name, count) type name[(count)] #endif +#include "jemalloc/internal/time.h" #include "jemalloc/internal/valgrind.h" #include "jemalloc/internal/util.h" #include "jemalloc/internal/atomic.h" @@ -384,6 +385,7 @@ typedef unsigned szind_t; /******************************************************************************/ #define JEMALLOC_H_STRUCTS +#include "jemalloc/internal/time.h" #include "jemalloc/internal/valgrind.h" #include "jemalloc/internal/util.h" #include "jemalloc/internal/atomic.h" @@ -469,6 +471,7 @@ void jemalloc_prefork(void); void jemalloc_postfork_parent(void); void jemalloc_postfork_child(void); +#include "jemalloc/internal/time.h" #include "jemalloc/internal/valgrind.h" #include "jemalloc/internal/util.h" #include "jemalloc/internal/atomic.h" @@ -497,6 +500,7 @@ void jemalloc_postfork_child(void); /******************************************************************************/ #define JEMALLOC_H_INLINES +#include "jemalloc/internal/time.h" #include "jemalloc/internal/valgrind.h" #include "jemalloc/internal/util.h" #include "jemalloc/internal/atomic.h" diff --git a/include/jemalloc/internal/jemalloc_internal_decls.h b/include/jemalloc/internal/jemalloc_internal_decls.h index a601d6eb..0f29e676 100644 --- a/include/jemalloc/internal/jemalloc_internal_decls.h +++ b/include/jemalloc/internal/jemalloc_internal_decls.h @@ -61,4 +61,12 @@ isblank(int c) #endif #include +#include +#ifdef _WIN32 +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif + #endif /* JEMALLOC_INTERNAL_H */ diff --git a/include/jemalloc/internal/private_symbols.txt b/include/jemalloc/internal/private_symbols.txt index a90021aa..8b1fd45c 100644 --- a/include/jemalloc/internal/private_symbols.txt +++ b/include/jemalloc/internal/private_symbols.txt @@ -460,6 +460,7 @@ tcaches_get tcache_stats_merge thread_allocated_cleanup thread_deallocated_cleanup +time_update tsd_arena_get tsd_arena_set tsd_boot diff --git a/include/jemalloc/internal/time.h b/include/jemalloc/internal/time.h new file mode 100644 index 00000000..e3e6c5f4 --- /dev/null +++ b/include/jemalloc/internal/time.h @@ -0,0 +1,22 @@ +#define JEMALLOC_CLOCK_GETTIME defined(_POSIX_MONOTONIC_CLOCK) \ + && _POSIX_MONOTONIC_CLOCK >= 0 + +/******************************************************************************/ +#ifdef JEMALLOC_H_TYPES + +#endif /* JEMALLOC_H_TYPES */ +/******************************************************************************/ +#ifdef JEMALLOC_H_STRUCTS + +#endif /* JEMALLOC_H_STRUCTS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_EXTERNS + +bool time_update(struct timespec *time); + +#endif /* JEMALLOC_H_EXTERNS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_INLINES + +#endif /* JEMALLOC_H_INLINES */ +/******************************************************************************/ diff --git a/src/time.c b/src/time.c new file mode 100644 index 00000000..2147c529 --- /dev/null +++ b/src/time.c @@ -0,0 +1,36 @@ +#include "jemalloc/internal/jemalloc_internal.h" + +bool +time_update(struct timespec *time) +{ + struct timespec old_time; + + memcpy(&old_time, time, sizeof(struct timespec)); + +#ifdef _WIN32 + FILETIME ft; + uint64_t ticks; + GetSystemTimeAsFileTime(&ft); + ticks = (ft.dwHighDateTime << 32) | ft.dWLowDateTime; + time->tv_sec = ticks / 10000; + time->tv_nsec = ((ticks % 10000) * 100); +#elif JEMALLOC_CLOCK_GETTIME + if (sysconf(_SC_MONOTONIC_CLOCK) > 0) + clock_gettime(CLOCK_MONOTONIC, time); + else + clock_gettime(CLOCK_REALTIME, time); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + time->tv_sec = tv.tv_sec; + time->tv_nsec = tv.tv_usec * 1000; +#endif + + /* Handle non-monotonic clocks. */ + if (unlikely(old_time.tv_sec > time->tv_sec)) + return (true); + if (unlikely(old_time.tv_sec == time->tv_sec)) + return old_time.tv_nsec > time->tv_nsec; + + return (false); +} diff --git a/test/unit/time.c b/test/unit/time.c new file mode 100644 index 00000000..80460f98 --- /dev/null +++ b/test/unit/time.c @@ -0,0 +1,23 @@ +#include "test/jemalloc_test.h" + +TEST_BEGIN(test_time_update) +{ + struct timespec ts; + + memset(&ts, 0, sizeof(struct timespec)); + + assert_false(time_update(&ts), "Basic time update failed."); + + /* Only Rip Van Winkle sleeps this long. */ + ts.tv_sec += 631152000; + assert_true(time_update(&ts), "Update should detect time roll-back."); +} +TEST_END + +int +main(void) +{ + + return (test( + test_time_update)); +}