mirror of
https://github.com/reactos/ninja.git
synced 2024-11-23 03:39:48 +00:00
Merge pull request #1219 from QuLogic/resolution
Use high-resolution timestamps
This commit is contained in:
commit
e234a7bdb6
@ -290,7 +290,7 @@ bool BuildLog::Load(const string& path, string* err) {
|
||||
if (!end)
|
||||
continue;
|
||||
*end = 0;
|
||||
restat_mtime = atol(start);
|
||||
restat_mtime = strtoll(start, NULL, 10);
|
||||
start = end + 1;
|
||||
|
||||
end = (char*)memchr(start, kFieldSeparator, line_end - start);
|
||||
@ -353,7 +353,7 @@ BuildLog::LogEntry* BuildLog::LookupByOutput(const string& path) {
|
||||
}
|
||||
|
||||
bool BuildLog::WriteEntry(FILE* f, const LogEntry& entry) {
|
||||
return fprintf(f, "%d\t%d\t%d\t%s\t%" PRIx64 "\n",
|
||||
return fprintf(f, "%d\t%d\t%" PRId64 "\t%s\t%" PRIx64 "\n",
|
||||
entry.start_time, entry.end_time, entry.mtime,
|
||||
entry.output.c_str(), entry.command_hash) > 0;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
// The version is stored as 4 bytes after the signature and also serves as a
|
||||
// byte order mark. Signature and version combined are 16 bytes long.
|
||||
const char kFileSignature[] = "# ninjadeps\n";
|
||||
const int kCurrentVersion = 3;
|
||||
const int kCurrentVersion = 4;
|
||||
|
||||
// Record size is currently limited to less than the full 32 bit, due to
|
||||
// internal buffers having to have this size.
|
||||
@ -124,7 +124,7 @@ bool DepsLog::RecordDeps(Node* node, TimeStamp mtime,
|
||||
return true;
|
||||
|
||||
// Update on-disk representation.
|
||||
unsigned size = 4 * (1 + 1 + node_count);
|
||||
unsigned size = 4 * (1 + 2 + node_count);
|
||||
if (size > kMaxRecordSize) {
|
||||
errno = ERANGE;
|
||||
return false;
|
||||
@ -135,8 +135,11 @@ bool DepsLog::RecordDeps(Node* node, TimeStamp mtime,
|
||||
int id = node->id();
|
||||
if (fwrite(&id, 4, 1, file_) < 1)
|
||||
return false;
|
||||
int timestamp = mtime;
|
||||
if (fwrite(×tamp, 4, 1, file_) < 1)
|
||||
uint32_t mtime_part = static_cast<uint32_t>(mtime & 0xffffffff);
|
||||
if (fwrite(&mtime_part, 4, 1, file_) < 1)
|
||||
return false;
|
||||
mtime_part = static_cast<uint32_t>((mtime >> 32) & 0xffffffff);
|
||||
if (fwrite(&mtime_part, 4, 1, file_) < 1)
|
||||
return false;
|
||||
for (int i = 0; i < node_count; ++i) {
|
||||
id = nodes[i]->id();
|
||||
@ -218,9 +221,11 @@ bool DepsLog::Load(const string& path, State* state, string* err) {
|
||||
assert(size % 4 == 0);
|
||||
int* deps_data = reinterpret_cast<int*>(buf);
|
||||
int out_id = deps_data[0];
|
||||
int mtime = deps_data[1];
|
||||
deps_data += 2;
|
||||
int deps_count = (size / 4) - 2;
|
||||
TimeStamp mtime;
|
||||
mtime = (TimeStamp)(((uint64_t)(unsigned int)deps_data[2] << 32) |
|
||||
(uint64_t)(unsigned int)deps_data[1]);
|
||||
deps_data += 3;
|
||||
int deps_count = (size / 4) - 3;
|
||||
|
||||
Deps* deps = new Deps(mtime, deps_count);
|
||||
for (int i = 0; i < deps_count; ++i) {
|
||||
|
@ -57,7 +57,9 @@ struct State;
|
||||
/// one's complement of the expected index of the record (to detect
|
||||
/// concurrent writes of multiple ninja processes to the log).
|
||||
/// dependency records are an array of 4-byte integers
|
||||
/// [output path id, output path mtime, input path id, input path id...]
|
||||
/// [output path id,
|
||||
/// output path mtime (lower 4 bytes), output path mtime (upper 4 bytes),
|
||||
/// input path id, input path id...]
|
||||
/// (The mtime is compared against the on-disk output path mtime
|
||||
/// to verify the stored data is up-to-date.)
|
||||
/// If two records reference the same output the latter one in the file
|
||||
@ -75,10 +77,10 @@ struct DepsLog {
|
||||
|
||||
// Reading (startup-time) interface.
|
||||
struct Deps {
|
||||
Deps(int mtime, int node_count)
|
||||
Deps(int64_t mtime, int node_count)
|
||||
: mtime(mtime), node_count(node_count), nodes(new Node*[node_count]) {}
|
||||
~Deps() { delete [] nodes; }
|
||||
int mtime;
|
||||
TimeStamp mtime;
|
||||
int node_count;
|
||||
Node** nodes;
|
||||
};
|
||||
|
@ -61,12 +61,11 @@ int MakeDir(const string& path) {
|
||||
TimeStamp TimeStampFromFileTime(const FILETIME& filetime) {
|
||||
// FILETIME is in 100-nanosecond increments since the Windows epoch.
|
||||
// We don't much care about epoch correctness but we do want the
|
||||
// resulting value to fit in an integer.
|
||||
// resulting value to fit in a 64-bit integer.
|
||||
uint64_t mtime = ((uint64_t)filetime.dwHighDateTime << 32) |
|
||||
((uint64_t)filetime.dwLowDateTime);
|
||||
mtime /= 1000000000LL / 100; // 100ns -> s.
|
||||
mtime -= 12622770400LL; // 1600 epoch -> 2000 epoch (subtract 400 years).
|
||||
return (TimeStamp)mtime;
|
||||
// 1600 epoch -> 2000 epoch (subtract 400 years).
|
||||
return (TimeStamp)mtime - 12622770400LL * (1000000000LL / 100);
|
||||
}
|
||||
|
||||
TimeStamp StatSingleFile(const string& path, string* err) {
|
||||
@ -192,7 +191,19 @@ TimeStamp RealDiskInterface::Stat(const string& path, string* err) const {
|
||||
// that it doesn't exist.
|
||||
if (st.st_mtime == 0)
|
||||
return 1;
|
||||
return st.st_mtime;
|
||||
#if defined(__APPLE__) && !defined(_POSIX_C_SOURCE)
|
||||
return ((int64_t)st.st_mtimespec.tv_sec * 1000000000LL +
|
||||
st.st_mtimespec.tv_nsec);
|
||||
#elif (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700 || defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || \
|
||||
defined(__BIONIC__))
|
||||
// For glibc, see "Timestamp files" in the Notes of http://www.kernel.org/doc/man-pages/online/pages/man2/stat.2.html
|
||||
// newlib, uClibc and musl follow the kernel (or Cygwin) headers and define the right macro values above.
|
||||
// For bsd, see https://github.com/freebsd/freebsd/blob/master/sys/sys/stat.h and similar
|
||||
// For bionic, C and POSIX API is always enabled.
|
||||
return (int64_t)st.st_mtim.tv_sec * 1000000000LL + st.st_mtim.tv_nsec;
|
||||
#else
|
||||
return (int64_t)st.st_mtime * 1000000000LL + st.st_mtimensec;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -233,7 +233,7 @@ bool DependencyScan::RecomputeOutputDirty(Edge* edge,
|
||||
|
||||
if (output_mtime < most_recent_input->mtime()) {
|
||||
EXPLAIN("%soutput %s older than most recent input %s "
|
||||
"(%d vs %d)",
|
||||
"(%" PRId64 " vs %" PRId64 ")",
|
||||
used_restat ? "restat of " : "", output->path().c_str(),
|
||||
most_recent_input->path().c_str(),
|
||||
output_mtime, most_recent_input->mtime());
|
||||
@ -257,7 +257,7 @@ bool DependencyScan::RecomputeOutputDirty(Edge* edge,
|
||||
// mtime of the most recent input. This can occur even when the mtime
|
||||
// on disk is newer if a previous run wrote to the output file but
|
||||
// exited with an error or was interrupted.
|
||||
EXPLAIN("recorded mtime of %s older than most recent input %s (%d vs %d)",
|
||||
EXPLAIN("recorded mtime of %s older than most recent input %s (%" PRId64 " vs %" PRId64 ")",
|
||||
output->path().c_str(), most_recent_input->path().c_str(),
|
||||
entry->mtime, most_recent_input->mtime());
|
||||
return true;
|
||||
@ -441,7 +441,7 @@ string Node::PathDecanonicalized(const string& path, uint64_t slash_bits) {
|
||||
}
|
||||
|
||||
void Node::Dump(const char* prefix) const {
|
||||
printf("%s <%s 0x%p> mtime: %d%s, (:%s), ",
|
||||
printf("%s <%s 0x%p> mtime: %" PRId64 "%s, (:%s), ",
|
||||
prefix, path().c_str(), this,
|
||||
mtime(), mtime() ? "" : " (:missing)",
|
||||
dirty() ? " dirty" : " clean");
|
||||
@ -547,7 +547,7 @@ bool ImplicitDepLoader::LoadDepsFromLog(Edge* edge, string* err) {
|
||||
|
||||
// Deps are invalid if the output is newer than the deps.
|
||||
if (output->mtime() > deps->mtime) {
|
||||
EXPLAIN("stored deps info out of date for '%s' (%d vs %d)",
|
||||
EXPLAIN("stored deps info out of date for '%s' (%" PRId64 " vs %" PRId64 ")",
|
||||
output->path().c_str(), deps->mtime, output->mtime());
|
||||
return false;
|
||||
}
|
||||
|
@ -494,7 +494,7 @@ int NinjaMain::ToolDeps(const Options* options, int argc, char** argv) {
|
||||
TimeStamp mtime = disk_interface.Stat((*it)->path(), &err);
|
||||
if (mtime == -1)
|
||||
Error("%s", err.c_str()); // Log and ignore Stat() errors;
|
||||
printf("%s: #deps %d, deps mtime %d (%s)\n",
|
||||
printf("%s: #deps %d, deps mtime %" PRId64 " (%s)\n",
|
||||
(*it)->path().c_str(), deps->node_count, deps->mtime,
|
||||
(!mtime || mtime > deps->mtime ? "STALE":"VALID"));
|
||||
for (int i = 0; i < deps->node_count; ++i)
|
||||
|
@ -15,10 +15,19 @@
|
||||
#ifndef NINJA_TIMESTAMP_H_
|
||||
#define NINJA_TIMESTAMP_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "win32port.h"
|
||||
#else
|
||||
#ifndef __STDC_FORMAT_MACROS
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
// When considering file modification times we only care to compare
|
||||
// them against one another -- we never convert them to an absolute
|
||||
// real time. On POSIX we use time_t (seconds since epoch) and on
|
||||
// Windows we use a different value. Both fit in an int.
|
||||
typedef int TimeStamp;
|
||||
// real time. On POSIX we use timespec (seconds&nanoseconds since epoch)
|
||||
// and on Windows we use a different value. Both fit in an int64.
|
||||
typedef int64_t TimeStamp;
|
||||
|
||||
#endif // NINJA_TIMESTAMP_H_
|
||||
|
@ -15,6 +15,13 @@
|
||||
#ifndef NINJA_WIN32PORT_H_
|
||||
#define NINJA_WIN32PORT_H_
|
||||
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
#ifndef __STDC_FORMAT_MACROS
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
typedef signed short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
/// A 64-bit integer type
|
||||
@ -23,6 +30,7 @@ typedef unsigned long long uint64_t;
|
||||
|
||||
// printf format specifier for uint64_t, from C99.
|
||||
#ifndef PRIu64
|
||||
#define PRId64 "I64d"
|
||||
#define PRIu64 "I64u"
|
||||
#define PRIx64 "I64x"
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user