From 1f4e39984b2197cce91a2bc9356b17e7df76df6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jurko=20Gospodneti=C4=87?= Date: Sat, 14 Jul 2012 18:55:06 +0000 Subject: [PATCH] Windows Boost Jam implementation now uses finer resolution than 1 second when creating timestamps based on the current system time. Since these are never (and should never be!) compared to file system timestamps - this causes no conflicts with file system timestamps still using 1 second resolution at best. Related stylistic changes: - filetime_to_timestamp() function renamed to timestamp_from_filetime() and moved to the timestamp.c module. - filetime_to_seconds() function moved back to the execnt.c module as a static function as it only used from there after the timestamp_from_filetime() reimplementation in revision [79494]. - filent.h header now empty and removed. [SVN r79511] --- v2/engine/execnt.c | 24 +++++++++++++++----- v2/engine/filent.c | 51 +++++-------------------------------------- v2/engine/filent.h | 22 ------------------- v2/engine/timestamp.c | 38 ++++++++++++++++++++++++++++++++ v2/engine/timestamp.h | 22 +++++++++++++------ 5 files changed, 77 insertions(+), 80 deletions(-) delete mode 100644 v2/engine/filent.h diff --git a/v2/engine/execnt.c b/v2/engine/execnt.c index dc21b7b85..5aa47d195 100644 --- a/v2/engine/execnt.c +++ b/v2/engine/execnt.c @@ -30,13 +30,15 @@ * exec_check() - preprocess and validate the command * exec_cmd() - launch an async command execution * exec_wait() - wait for any of the async command processes to terminate + * + * Internal routines: + * filetime_to_seconds() - Windows FILETIME --> number of seconds conversion */ #include "jam.h" #ifdef USE_EXECNT #include "execcmd.h" -#include "filent.h" #include "lists.h" #include "output.h" #include "pathsys.h" @@ -47,6 +49,8 @@ #include #include +#define WIN32_LEAN_AND_MEAN +#include #include #include @@ -663,6 +667,17 @@ static FILETIME negate_FILETIME( FILETIME t ) } +/* + * filetime_to_seconds() - Windows FILETIME --> number of seconds conversion + */ + +static double filetime_to_seconds( FILETIME const ft ) +{ + return ft.dwHighDateTime * ( (double)( 1UL << 31 ) * 2.0 * 1.0e-7 ) + + ft.dwLowDateTime * 1.0e-7; +} + + static void record_times( HANDLE const process, timing_info * const time ) { FILETIME creation; @@ -673,8 +688,8 @@ static void record_times( HANDLE const process, timing_info * const time ) { time->system = filetime_to_seconds( kernel ); time->user = filetime_to_seconds( user ); - filetime_to_timestamp( creation, &time->start ); - filetime_to_timestamp( exit, &time->end ); + timestamp_from_filetime( &time->start, &creation ); + timestamp_from_filetime( &time->end, &exit ); } } @@ -850,10 +865,10 @@ static double running_time( HANDLE const process ) FILETIME exit; FILETIME kernel; FILETIME user; - FILETIME current; if ( GetProcessTimes( process, &creation, &exit, &kernel, &user ) ) { /* Compute the elapsed time. */ + FILETIME current; GetSystemTimeAsFileTime( ¤t ); return filetime_to_seconds( add_FILETIME( current, negate_FILETIME( creation ) ) ); @@ -907,7 +922,6 @@ static double creation_time( HANDLE const process ) FILETIME exit; FILETIME kernel; FILETIME user; - FILETIME current; return GetProcessTimes( process, &creation, &exit, &kernel, &user ) ? filetime_to_seconds( creation ) : 0.0; diff --git a/v2/engine/filent.c b/v2/engine/filent.c index f796b298b..7d7ba9388 100644 --- a/v2/engine/filent.c +++ b/v2/engine/filent.c @@ -15,10 +15,8 @@ * filent.c - scan directories and archives on NT * * External routines: - * file_archscan() - scan an archive for files - * file_mkdir() - create a directory - * filetime_to_seconds() - Windows FILETIME --> number of seconds conversion - * filetime_to_timestamp() - Windows FILETIME --> timestamp conversion + * file_archscan() - scan an archive for files + * file_mkdir() - create a directory * * External routines called only via routines in filesys.c: * file_collect_dir_content_() - collects directory content information @@ -28,7 +26,6 @@ #include "jam.h" #ifdef OS_NT -#include "filent.h" #include "filesys.h" #include "object.h" @@ -44,6 +41,9 @@ # define _finddata_t ffblk #endif +#define WIN32_LEAN_AND_MEAN +#include + #include #include #include @@ -351,45 +351,4 @@ void file_archscan( char const * archive, scanback func, void * closure ) close( fd ); } - -/* - * filetime_to_seconds() - Windows FILETIME --> number of seconds conversion - */ - -double filetime_to_seconds( FILETIME const t ) -{ - return t.dwHighDateTime * ( (double)( 1UL << 31 ) * 2.0 * 1.0e-7 ) + - t.dwLowDateTime * 1.0e-7; -} - - -/* - * filetime_to_timestamp() - Windows FILETIME --> timestamp conversion - * - * Lifted shamelessly from the CPython implementation. - */ - -void filetime_to_timestamp( FILETIME const ft, timestamp * const time ) -{ - /* Seconds between 1.1.1601 and 1.1.1970 */ - static __int64 const secs_between_epochs = 11644473600; - - /* We can not simply cast and dereference a FILETIME, since it might not be - * aligned properly. __int64 type variables are expected to be aligned to an - * 8 byte boundary while FILETIME structures may be aligned to any 4 byte - * boundary. Using an incorrectly aligned __int64 variable may cause a - * performance penalty on some platforms or even exceptions on others - * (documented on MSDN). - */ - __int64 in; - memcpy( &in, &ft, sizeof( in ) ); - - /* FILETIME resolution: 100ns. */ - /* For resolutions finer than 1 second use the following: - * nsec = (int)( in % 10000000 ) * 100; - */ - timestamp_init( time, (time_t)( ( in / 10000000 ) - secs_between_epochs ), 0 - ); -} - #endif /* OS_NT */ diff --git a/v2/engine/filent.h b/v2/engine/filent.h deleted file mode 100644 index 2bf177a22..000000000 --- a/v2/engine/filent.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2012 Jurko Gospodnetic - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - */ - -/* - * filent.h - Windows specific file routines - */ - -#ifndef FILENT_JG20120714_H -#define FILENT_JG20120714_H - -#include "timestamp.h" - -#define WIN32_LEAN_AND_MEAN -#include - -double filetime_to_seconds( FILETIME const ft ); -void filetime_to_timestamp( FILETIME const ft, timestamp * const time ); - -#endif diff --git a/v2/engine/timestamp.c b/v2/engine/timestamp.c index 81fefcaec..551581d46 100644 --- a/v2/engine/timestamp.c +++ b/v2/engine/timestamp.c @@ -69,6 +69,35 @@ static char * time_progress[] = }; +#ifdef OS_NT +/* + * timestamp_from_filetime() - Windows FILETIME --> timestamp conversion + * + * Lifted shamelessly from the CPython implementation. + */ + +void timestamp_from_filetime( timestamp * const t, FILETIME const * const ft ) +{ + /* Seconds between 1.1.1601 and 1.1.1970 */ + static __int64 const secs_between_epochs = 11644473600; + + /* We can not simply cast and dereference a FILETIME, since it might not be + * aligned properly. __int64 type variables are expected to be aligned to an + * 8 byte boundary while FILETIME structures may be aligned to any 4 byte + * boundary. Using an incorrectly aligned __int64 variable may cause a + * performance penalty on some platforms or even exceptions on others + * (documented on MSDN). + */ + __int64 in; + memcpy( &in, ft, sizeof( in ) ); + + /* FILETIME resolution: 100ns. */ + timestamp_init( t, (time_t)( ( in / 10000000 ) - secs_between_epochs ), + (int)( in % 10000000 ) * 100 ); +} +#endif /* OS_NT */ + + void timestamp_clear( timestamp * const time ) { time->secs = time->nsecs = 0; @@ -92,7 +121,16 @@ void timestamp_copy( timestamp * const target, timestamp const * const source ) void timestamp_current( timestamp * const t ) { +#ifdef OS_NT + /* GetSystemTimeAsFileTime()'s resolution seems to be about 15 ms on Windows + * XP and under a millisecond on Windows 7. + */ + FILETIME ft; + GetSystemTimeAsFileTime( &ft ); + timestamp_from_filetime( t, &ft ); +#else /* OS_NT */ timestamp_init( t, time( 0 ), 0 ); +#endif /* OS_NT */ } diff --git a/v2/engine/timestamp.h b/v2/engine/timestamp.h index 80d6fd8df..043816afa 100644 --- a/v2/engine/timestamp.h +++ b/v2/engine/timestamp.h @@ -13,6 +13,11 @@ #include "object.h" +#ifdef OS_NT +# define WIN32_LEAN_AND_MEAN +# include +#endif + #include typedef struct timestamp @@ -21,17 +26,20 @@ typedef struct timestamp int nsecs; } timestamp; -void timestamp_clear( timestamp * const time ); +void timestamp_clear( timestamp * const ); int timestamp_cmp( timestamp const * const lhs, timestamp const * const rhs ); void timestamp_copy( timestamp * const target, timestamp const * const source ); -void timestamp_current( timestamp * const time ); -int timestamp_empty( timestamp const * const time ); -void timestamp_from_path( timestamp * const time, OBJECT * const path ); -void timestamp_init( timestamp * const time, time_t const secs, int const nsecs - ); +void timestamp_current( timestamp * const ); +int timestamp_empty( timestamp const * const ); +void timestamp_from_path( timestamp * const, OBJECT * const path ); +void timestamp_init( timestamp * const, time_t const secs, int const nsecs ); void timestamp_max( timestamp * const max, timestamp const * const lhs, timestamp const * const rhs ); -char const * timestamp_str( timestamp const * const time ); +char const * timestamp_str( timestamp const * const ); + +#ifdef OS_NT +void timestamp_from_filetime( timestamp * const, FILETIME const * const ); +#endif void timestamp_done();