diff options
Diffstat (limited to 'mysys')
-rw-r--r-- | mysys/mf_getdate.c | 2 | ||||
-rw-r--r-- | mysys/my_getsystime.c | 228 | ||||
-rw-r--r-- | mysys/my_init.c | 50 | ||||
-rw-r--r-- | mysys/my_static.c | 5 | ||||
-rw-r--r-- | mysys/my_static.h | 2 | ||||
-rw-r--r-- | mysys/my_uuid.c | 12 | ||||
-rw-r--r-- | mysys/waiting_threads.c | 34 |
7 files changed, 74 insertions, 259 deletions
diff --git a/mysys/mf_getdate.c b/mysys/mf_getdate.c index 9475bebd107..70278e64003 100644 --- a/mysys/mf_getdate.c +++ b/mysys/mf_getdate.c @@ -42,7 +42,7 @@ void get_date(register char * to, int flag, time_t date) struct tm tm_tmp; #endif - skr=date ? (time_t) date : my_time(0); + skr=date ? date : (time_t) my_time(0); #if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT) if (flag & GETDATE_GMT) gmtime_r(&skr,&tm_tmp); diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c index 6bffcd65d30..cb063e27c1f 100644 --- a/mysys/my_getsystime.c +++ b/mysys/my_getsystime.c @@ -14,224 +14,102 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* get time since epoc in 100 nanosec units */ -/* thus to get the current time we should use the system function - with the highest possible resolution */ - -/* - TODO: in functions my_micro_time() and my_micro_time_and_time() there - exists some common code that should be merged into a function. -*/ #include "mysys_priv.h" #include "my_static.h" #ifdef __NETWARE__ #include <nks/time.h> +#elif defined(__WIN__) +#define OFFSET_TO_EPOC 116444736000000000LL +static ulonglong query_performance_frequency; #endif #ifdef HAVE_LINUX_UNISTD_H #include <linux/unistd.h> #endif +/* + return number of nanoseconds since unspecified (but always the same) + point in the past + + NOTE: + Thus to get the current time we should use the system function + with the highest possible resolution -ulonglong my_getsystime() + The value is not anchored to any specific point in time (e.g. epoch) nor + is it subject to resetting or drifting by way of adjtime() or settimeofday(), + and thus it is *NOT* appropriate for getting the current timestamp. It can be + used for calculating time intervals, though. +*/ + +ulonglong my_interval_timer() { #ifdef HAVE_CLOCK_GETTIME struct timespec tp; - clock_gettime(CLOCK_REALTIME, &tp); - return (ulonglong)tp.tv_sec*10000000+(ulonglong)tp.tv_nsec/100; + clock_gettime(CLOCK_MONOTONIC, &tp); + return tp.tv_sec*1000000000ULL+tp.tv_nsec; +#elif defined(HAVE_GETHRTIME) + return gethrtime(); #elif defined(__WIN__) LARGE_INTEGER t_cnt; if (query_performance_frequency) { QueryPerformanceCounter(&t_cnt); - return ((t_cnt.QuadPart / query_performance_frequency * 10000000) + - ((t_cnt.QuadPart % query_performance_frequency) * 10000000 / - query_performance_frequency) + query_performance_offset); + return (t_cnt.QuadPart / query_performance_frequency * 1000000000ULL) + + ((t_cnt.QuadPart % query_performance_frequency) * 1000000000ULL / + query_performance_frequency); + } + else + { + ulonglong newtime; + GetSystemTimeAsFileTime((FILETIME*)&newtime); + return newtime*100ULL; } - return 0; #elif defined(__NETWARE__) NXTime_t tm; NXGetTime(NX_SINCE_1970, NX_NSECONDS, &tm); - return (ulonglong)tm/100; + return (ulonglong)tm; #else /* TODO: check for other possibilities for hi-res timestamping */ struct timeval tv; gettimeofday(&tv,NULL); - return (ulonglong)tv.tv_sec*10000000+(ulonglong)tv.tv_usec*10; + return tv.tv_sec*1000000000ULL+tv.tv_usec*1000ULL; #endif } -/* - Return current time - - SYNOPSIS - my_time() - flags If MY_WME is set, write error if time call fails - -*/ - -time_t my_time(myf flags __attribute__((unused))) -{ - time_t t; -#ifdef HAVE_GETHRTIME - (void) my_micro_time_and_time(&t); - return t; -#else - /* The following loop is here beacuse time() may fail on some systems */ - while ((t= time(0)) == (time_t) -1) - { - if (flags & MY_WME) - fprintf(stderr, "%s: Warning: time() call failed\n", my_progname); - } - return t; -#endif -} - - -/* - Return time in micro seconds - - SYNOPSIS - my_micro_time() - - NOTES - This function is to be used to measure performance in micro seconds. - As it's not defined whats the start time for the clock, this function - us only useful to measure time between two moments. - - For windows platforms we need the frequency value of the CUP. This is - initalized in my_init.c through QueryPerformanceFrequency(). - - If Windows platform doesn't support QueryPerformanceFrequency() we will - obtain the time via GetClockCount, which only supports milliseconds. - - RETURN - Value in microseconds from some undefined point in time -*/ - -ulonglong my_micro_time() -{ -#if defined(__WIN__) - ulonglong newtime; - GetSystemTimeAsFileTime((FILETIME*)&newtime); - return (newtime/10); -#elif defined(HAVE_GETHRTIME) - return gethrtime()/1000; -#else - ulonglong newtime; - struct timeval t; - /* - The following loop is here because gettimeofday may fail on some systems - */ - while (gettimeofday(&t, NULL) != 0) - {} - newtime= (ulonglong)t.tv_sec * 1000000 + t.tv_usec; - return newtime; -#endif /* defined(__WIN__) */ -} - - -/* - Return time in seconds and timer in microseconds (not different start!) - - SYNOPSIS - my_micro_time_and_time() - time_arg Will be set to seconds since epoch (00:00:00 UTC, - January 1, 1970) - - NOTES - This function is to be useful when we need both the time and microtime. - For example in MySQL this is used to get the query time start of a query - and to measure the time of a query (for the slow query log) - - IMPLEMENTATION - Value of time is as in time() call. - Value of microtime is same as my_micro_time(), which may be totally - unrealated to time() +/* Return current time in HRTIME_RESOLUTION (microseconds) since epoch */ - RETURN - Value in microseconds from some undefined point in time -*/ - -#define DELTA_FOR_SECONDS LL(500000000) /* Half a second */ - -ulonglong my_micro_time_and_time(time_t *time_arg) +my_hrtime_t my_hrtime() { + my_hrtime_t hrtime; #if defined(__WIN__) ulonglong newtime; GetSystemTimeAsFileTime((FILETIME*)&newtime); - *time_arg= (time_t) ((newtime - OFFSET_TO_EPOCH) / 10000000); - return (newtime/10); -#elif defined(HAVE_GETHRTIME) - /* - Solaris has a very slow time() call. We optimize this by using the very - fast gethrtime() call and only calling time() every 1/2 second - */ - static hrtime_t prev_gethrtime= 0; - static time_t cur_time= 0; - hrtime_t cur_gethrtime; - - pthread_mutex_lock(&THR_LOCK_time); - cur_gethrtime= gethrtime(); - /* - Due to bugs in the Solaris (x86) implementation of gethrtime(), - the time returned by it might not be monotonic. Don't use the - cached time(2) value if this is a case. - */ - if ((prev_gethrtime > cur_gethrtime) || - ((cur_gethrtime - prev_gethrtime) > DELTA_FOR_SECONDS)) - { - cur_time= time(0); - prev_gethrtime= cur_gethrtime; - } - *time_arg= cur_time; - pthread_mutex_unlock(&THR_LOCK_time); - return cur_gethrtime/1000; + newtime -= OFFSET_TO_EPOC; + hrtime.val= newtime/10; +#elif defined(HAVE_CLOCK_GETTIME) + struct timespec tp; + clock_gettime(CLOCK_REALTIME, &tp); + hrtime.val= tp.tv_sec*1000000ULL+tp.tv_nsec/1000ULL; #else - ulonglong newtime; struct timeval t; - /* - The following loop is here because gettimeofday may fail on some systems - */ - while (gettimeofday(&t, NULL) != 0) - {} - *time_arg= t.tv_sec; - newtime= (ulonglong)t.tv_sec * 1000000 + t.tv_usec; - return newtime; -#endif /* defined(__WIN__) */ + /* The following loop is here because gettimeofday may fail */ + while (gettimeofday(&t, NULL) != 0) {} + hrtime.val= t.tv_sec*1000000ULL + t.tv_usec; +#endif + return hrtime; } -/* - Returns current time - - SYNOPSIS - my_time_possible_from_micro() - microtime Value from very recent my_micro_time() - - NOTES - This function returns the current time. The microtime argument is only used - if my_micro_time() uses a function that can safely be converted to the - current time. - - RETURN - current time -*/ - -time_t my_time_possible_from_micro(ulonglong microtime __attribute__((unused))) +void my_time_init() { -#if defined(__WIN__) - time_t t; - while ((t= time(0)) == (time_t) -1) - {} - return t; -#elif defined(HAVE_GETHRTIME) - return my_time(0); /* Cached time */ -#else - return (time_t) (microtime / 1000000); -#endif /* defined(__WIN__) */ +#ifdef __WIN__ + compile_time_assert(sizeof(LARGE_INTEGER) == + sizeof(query_performance_frequency)); + if (QueryPerformanceFrequency((LARGE_INTEGER *)&query_performance_frequency) == 0) + query_performance_frequency= 0; +#endif } diff --git a/mysys/my_init.c b/mysys/my_init.c index e7ab9ba7a1f..356dbe6070f 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -102,6 +102,7 @@ my_bool my_init(void) DBUG_PROCESS((char*) (my_progname ? my_progname : "unknown")); if (!home_dir) { /* Don't initialize twice */ + my_time_init(); my_win_init(); if ((home_dir=getenv("HOME")) != 0) home_dir=intern_filename(home_dir_buff,home_dir); @@ -258,7 +259,6 @@ void my_debug_put_break_here(void) #ifdef __WIN__ - /* my_parameter_handler @@ -332,54 +332,6 @@ static void my_win_init(void) _tzset(); - - - - - - - - - - - - - - - - - - - - - - - - - /* The following is used by time functions */ -#define OFFSET_TO_EPOC ((__int64) 134774 * 24 * 60 * 60 * 1000 * 1000 * 10) -#define MS 10000000 - { - FILETIME ft; - LARGE_INTEGER li, t_cnt; - DBUG_ASSERT(sizeof(LARGE_INTEGER) == sizeof(query_performance_frequency)); - if (QueryPerformanceFrequency((LARGE_INTEGER *)&query_performance_frequency) == 0) - query_performance_frequency= 0; - else - { - GetSystemTimeAsFileTime(&ft); - li.LowPart= ft.dwLowDateTime; - li.HighPart= ft.dwHighDateTime; - query_performance_offset= li.QuadPart-OFFSET_TO_EPOC; - QueryPerformanceCounter(&t_cnt); - query_performance_offset-= (t_cnt.QuadPart / - query_performance_frequency * MS + - t_cnt.QuadPart % - query_performance_frequency * MS / - query_performance_frequency); - } - } - { /* Open HKEY_LOCAL_MACHINE\SOFTWARE\MySQL and set any strings found diff --git a/mysys/my_static.c b/mysys/my_static.c index 08653d03d21..52c8c6aff0e 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -112,11 +112,6 @@ const char *(*proc_info_hook)(void *, const char *, const char *, const char *, void (*debug_sync_C_callback_ptr)(const char *, size_t); #endif /* defined(ENABLED_DEBUG_SYNC) */ -#ifdef __WIN__ -/* from my_getsystime.c */ -ulonglong query_performance_frequency, query_performance_offset; -#endif - /* How to disable options */ my_bool NEAR my_disable_locking=0; my_bool NEAR my_disable_sync=0; diff --git a/mysys/my_static.h b/mysys/my_static.h index 90168b099a8..5e853c2a559 100644 --- a/mysys/my_static.h +++ b/mysys/my_static.h @@ -66,8 +66,6 @@ extern struct st_irem *sf_malloc_root; extern struct st_my_file_info my_file_info_default[MY_NFILE]; -extern ulonglong query_performance_frequency, query_performance_offset; - #if defined(THREAD) && !defined(__WIN__) extern sigset_t my_signals; /* signals blocked by mf_brkhant */ #endif diff --git a/mysys/my_uuid.c b/mysys/my_uuid.c index e2372391b06..3df2dda2af5 100644 --- a/mysys/my_uuid.c +++ b/mysys/my_uuid.c @@ -47,6 +47,7 @@ static my_bool my_uuid_inited= 0; static struct my_rnd_struct uuid_rand; static uint nanoseq; static ulonglong uuid_time= 0; +static longlong interval_timer_offset; static uchar uuid_suffix[2+6]; /* clock_seq and node */ #ifdef THREAD @@ -70,6 +71,8 @@ static void set_clock_seq() { uint16 clock_seq= ((uint)(my_rnd(&uuid_rand)*16383)) | UUID_VARIANT; mi_int2store(uuid_suffix, clock_seq); + interval_timer_offset= (my_hrtime().val * 10 - my_interval_timer()/100 + + UUID_TIME_OFFSET); } @@ -93,7 +96,7 @@ void my_uuid_init(ulong seed1, ulong seed2) if (my_uuid_inited) return; my_uuid_inited= 1; - now= my_getsystime(); + now= my_interval_timer()/100 + interval_timer_offset; nanoseq= 0; if (my_gethwaddr(mac)) @@ -134,7 +137,7 @@ void my_uuid(uchar *to) DBUG_ASSERT(my_uuid_inited); pthread_mutex_lock(&LOCK_uuid_generator); - tv= my_getsystime() + UUID_TIME_OFFSET + nanoseq; + tv= my_interval_timer()/100 + interval_timer_offset + nanoseq; if (likely(tv > uuid_time)) { @@ -187,7 +190,7 @@ void my_uuid(uchar *to) irrelevant in the new numberspace. */ set_clock_seq(); - tv= my_getsystime() + UUID_TIME_OFFSET; + tv= my_interval_timer()/100 + interval_timer_offset; nanoseq= 0; DBUG_PRINT("uuid",("making new numberspace")); } @@ -228,7 +231,8 @@ void my_uuid2str(const uchar *guid, char *s) { *s++= _dig_vec_lower[guid[i] >>4]; *s++= _dig_vec_lower[guid[i] & 15]; - if(i == 3 || i == 5 || i == 7 || i == 9) + /* Set '-' at intervals 3, 5, 7 and 9 */ + if ((1 << i) & ((1 << 3) | (1 << 5) | (1 << 7) | (1 << 9))) *s++= '-'; } } diff --git a/mysys/waiting_threads.c b/mysys/waiting_threads.c index 732929f6d99..6ee79cb8e87 100644 --- a/mysys/waiting_threads.c +++ b/mysys/waiting_threads.c @@ -479,9 +479,9 @@ void wt_end() (or even most) of them will never be used for deadlock detection. @param ds a pointer to deadlock search depth short value - @param ts a pointer to deadlock timeout short value + @param ts a pointer to deadlock timeout short value (microseconds) @param dl a pointer to deadlock search depth long value - @param tl a pointer to deadlock timeout long value + @param tl a pointer to deadlock timeout long value (microseconds) @note these are pointers to values, and WT_THD stores them as pointers. It allows one later to change search depths and timeouts for existing @@ -1037,8 +1037,9 @@ int wt_thd_cond_timedwait(WT_THD *thd, pthread_mutex_t *mutex) { int ret= WT_TIMEOUT; struct timespec timeout; - ulonglong before, after, starttime; + my_hrtime_t before, after, starttime; WT_RESOURCE *rc= thd->waiting_for; + ulonglong end_wait_time; DBUG_ENTER("wt_thd_cond_timedwait"); DBUG_PRINT("wt", ("enter: thd=%s, rc=%p", thd->name, rc)); @@ -1050,29 +1051,15 @@ int wt_thd_cond_timedwait(WT_THD *thd, pthread_mutex_t *mutex) safe_mutex_assert_owner(mutex); #endif - before= starttime= my_getsystime(); - -#ifdef __WIN__ - /* - only for the sake of Windows we distinguish between - 'before' and 'starttime': - - my_getsystime() returns high-resolution value, that cannot be used for - waiting (it doesn't follow system clock changes), but is good for time - intervals. - - GetSystemTimeAsFileTime() follows system clock, but is low-resolution - and will result in lousy intervals. - */ - GetSystemTimeAsFileTime((PFILETIME)&starttime); -#endif + before= starttime= my_hrtime(); rc_wrlock(rc); if (rc->owners.elements == 0) ret= WT_OK; rc_unlock(rc); - set_timespec_time_nsec(timeout, starttime, (*thd->timeout_short)*ULL(1000)); + end_wait_time= starttime.val *1000 + (*thd->timeout_short)*ULL(1000000); + set_timespec_time_nsec(timeout, end_wait_time); if (ret == WT_TIMEOUT && !thd->killed) ret= pthread_cond_timedwait(&rc->cond, mutex, &timeout); if (ret == WT_TIMEOUT && !thd->killed) @@ -1084,15 +1071,16 @@ int wt_thd_cond_timedwait(WT_THD *thd, pthread_mutex_t *mutex) ret= WT_DEADLOCK; else if (*thd->timeout_long > *thd->timeout_short) { - set_timespec_time_nsec(timeout, starttime, (*thd->timeout_long)*ULL(1000)); + end_wait_time= starttime.val *1000 + (*thd->timeout_long)*ULL(1000000); + set_timespec_time_nsec(timeout, end_wait_time); if (!thd->killed) ret= pthread_cond_timedwait(&rc->cond, mutex, &timeout); } } - after= my_getsystime(); + after= my_hrtime(); if (stop_waiting(thd) == WT_DEADLOCK) /* if we're killed */ ret= WT_DEADLOCK; - increment_wait_stats(after-before, ret); + increment_wait_stats(after.val-before.val, ret); if (ret == WT_OK) increment_success_stats(); DBUG_RETURN(ret); |