Index: lib/profile/GCDAProfiling.c =================================================================== --- lib/profile/GCDAProfiling.c +++ lib/profile/GCDAProfiling.c @@ -29,6 +29,8 @@ #include #if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include #include "WindowsMMap.h" #else #include @@ -86,6 +88,9 @@ static uint64_t cur_pos = 0; static uint64_t file_size = 0; static int new_file = 0; +#if defined(_WIN32) +static HANDLE mmap_handle = NULL; +#endif static int fd = -1; typedef void (*fn_ptr)(); @@ -255,6 +260,28 @@ if (file_size == 0) return -1; +#if defined(_WIN32) + HANDLE mmap_fd; + if (fd == -1) + mmap_fd = INVALID_HANDLE_VALUE; + else + mmap_fd = (HANDLE)_get_osfhandle(fd); + + mmap_handle = CreateFileMapping(mmap_fd, NULL, PAGE_READWRITE, DWORD_HI(file_size), DWORD_LO(file_size), NULL); + if (mmap_handle == NULL) { + fprintf(stderr, "profiling: %s: cannot create file mapping: %d\n", filename, + GetLastError()); + return -1; + } + + write_buffer = MapViewOfFile(mmap_handle, FILE_MAP_WRITE, 0, 0, file_size); + if (write_buffer == NULL) { + fprintf(stderr, "profiling: %s: cannot map: %d\n", filename, + GetLastError()); + CloseHandle(mmap_handle); + return -1; + } +#else write_buffer = mmap(0, file_size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0); if (write_buffer == (void *)-1) { @@ -263,10 +290,30 @@ strerror(errnum)); return -1; } +#endif + return 0; } static void unmap_file() { +#if defined(_WIN32) + if (!FlushViewOfFile(write_buffer, file_size)) { + fprintf(stderr, "profiling: %s: cannot flush mapped view: %d\n", filename, + GetLastError()); + } + + if (!UnmapViewOfFile(write_buffer)) { + fprintf(stderr, "profiling: %s: cannot unmap mapped view: %d\n", filename, + GetLastError()); + } + + if (!CloseHandle(mmap_handle)) { + fprintf(stderr, "profiling: %s: cannot close file mapping handle: %d\n", filename, + GetLastError()); + } + + mmap_handle = NULL; +#else if (msync(write_buffer, file_size, MS_SYNC) == -1) { int errnum = errno; fprintf(stderr, "profiling: %s: cannot msync: %s\n", filename, @@ -277,6 +324,8 @@ * is written and we don't care. */ (void)munmap(write_buffer, file_size); +#endif + write_buffer = NULL; file_size = 0; } Index: lib/profile/WindowsMMap.h =================================================================== --- lib/profile/WindowsMMap.h +++ lib/profile/WindowsMMap.h @@ -45,6 +45,14 @@ #define LOCK_NB 4 /* don't block when locking */ #define LOCK_UN 8 /* unlock */ +#ifdef __USE_FILE_OFFSET64 +# define DWORD_HI(x) (x >> 32) +# define DWORD_LO(x) ((x) & 0xffffffff) +#else +# define DWORD_HI(x) (0) +# define DWORD_LO(x) (x) +#endif + void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); Index: lib/profile/WindowsMMap.c =================================================================== --- lib/profile/WindowsMMap.c +++ lib/profile/WindowsMMap.c @@ -24,14 +24,6 @@ #include "InstrProfiling.h" -#ifdef __USE_FILE_OFFSET64 -# define DWORD_HI(x) (x >> 32) -# define DWORD_LO(x) ((x) & 0xffffffff) -#else -# define DWORD_HI(x) (0) -# define DWORD_LO(x) (x) -#endif - COMPILER_RT_VISIBILITY void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) { Index: test/profile/Inputs/instrprof-gcov-__gcov_flush-multiple.c =================================================================== --- test/profile/Inputs/instrprof-gcov-__gcov_flush-multiple.c +++ test/profile/Inputs/instrprof-gcov-__gcov_flush-multiple.c @@ -0,0 +1,16 @@ +int main(void) { + __gcov_flush(); + + if (remove("instrprof-gcov-__gcov_flush-multiple.gcda") != 0) { + return 1; + } + + __gcov_flush(); + __gcov_flush(); + + if (remove("instrprof-gcov-__gcov_flush-multiple.gcda") != 0) { + return 1; + } + + return 0; +} Index: test/profile/Inputs/instrprof-gcov-__gcov_flush-multiple.c.gcov =================================================================== --- test/profile/Inputs/instrprof-gcov-__gcov_flush-multiple.c.gcov +++ test/profile/Inputs/instrprof-gcov-__gcov_flush-multiple.c.gcov @@ -0,0 +1,21 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-gcov-__gcov_flush-multiple.c +// CHECK-NEXT: -: 0:Graph:instrprof-gcov-__gcov_flush-multiple.gcno +// CHECK-NEXT: -: 0:Data:instrprof-gcov-__gcov_flush-multiple.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: #####: 1:int main(void) { +// CHECK-NEXT: #####: 2: __gcov_flush(); +// CHECK-NEXT: -: 3: +// CHECK-NEXT: #####: 4: if (remove("instrprof-gcov-__gcov_flush-multiple.gcda") != 0) { +// CHECK-NEXT: #####: 5: return 1; +// CHECK-NEXT: -: 6: } +// CHECK-NEXT: -: 7: +// CHECK-NEXT: #####: 8: __gcov_flush(); +// CHECK-NEXT: #####: 9: __gcov_flush(); +// CHECK-NEXT: -: 10: +// CHECK-NEXT: #####: 11: if (remove("instrprof-gcov-__gcov_flush-multiple.gcda") != 0) { +// CHECK-NEXT: #####: 12: return 1; +// CHECK-NEXT: -: 13: } +// CHECK-NEXT: -: 14: +// CHECK-NEXT: 1: 15: return 0; +// CHECK-NEXT: 1: 16:} Index: test/profile/instrprof-gcov-__gcov_flush-multiple.test =================================================================== --- test/profile/instrprof-gcov-__gcov_flush-multiple.test +++ test/profile/instrprof-gcov-__gcov_flush-multiple.test @@ -0,0 +1,10 @@ +RUN: mkdir -p %t.d +RUN: cd %t.d + +RUN: %clang --coverage -o %t %S/Inputs/instrprof-gcov-__gcov_flush-multiple.c +RUN: test -f instrprof-gcov-__gcov_flush-multiple.gcno + +RUN: rm -f instrprof-gcov-__gcov_flush-multiple.gcda +RUN: %run %t +RUN: llvm-cov gcov instrprof-gcov-__gcov_flush-multiple.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-gcov-__gcov_flush-multiple.c.gcov %S/Inputs/instrprof-gcov-__gcov_flush-multiple.c.gcov