[GCOV] Close file mapping handle on Windows, so flushed gcda files can be removed while the process is in execution

llvm-svn: 346300
This commit is contained in:
Marco Castelluccio 2018-11-07 09:38:26 +00:00
parent a8ffa52498
commit ed4bb266c8
6 changed files with 104 additions and 8 deletions

View File

@ -29,6 +29,8 @@
#include <string.h> #include <string.h>
#if defined(_WIN32) #if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "WindowsMMap.h" #include "WindowsMMap.h"
#else #else
#include <sys/mman.h> #include <sys/mman.h>
@ -86,6 +88,9 @@ static uint64_t cur_buffer_size = 0;
static uint64_t cur_pos = 0; static uint64_t cur_pos = 0;
static uint64_t file_size = 0; static uint64_t file_size = 0;
static int new_file = 0; static int new_file = 0;
#if defined(_WIN32)
static HANDLE mmap_handle = NULL;
#endif
static int fd = -1; static int fd = -1;
typedef void (*fn_ptr)(); typedef void (*fn_ptr)();
@ -255,6 +260,28 @@ static int map_file() {
if (file_size == 0) if (file_size == 0)
return -1; 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, write_buffer = mmap(0, file_size, PROT_READ | PROT_WRITE,
MAP_FILE | MAP_SHARED, fd, 0); MAP_FILE | MAP_SHARED, fd, 0);
if (write_buffer == (void *)-1) { if (write_buffer == (void *)-1) {
@ -263,10 +290,30 @@ static int map_file() {
strerror(errnum)); strerror(errnum));
return -1; return -1;
} }
#endif
return 0; return 0;
} }
static void unmap_file() { 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) { if (msync(write_buffer, file_size, MS_SYNC) == -1) {
int errnum = errno; int errnum = errno;
fprintf(stderr, "profiling: %s: cannot msync: %s\n", filename, fprintf(stderr, "profiling: %s: cannot msync: %s\n", filename,
@ -277,6 +324,8 @@ static void unmap_file() {
* is written and we don't care. * is written and we don't care.
*/ */
(void)munmap(write_buffer, file_size); (void)munmap(write_buffer, file_size);
#endif
write_buffer = NULL; write_buffer = NULL;
file_size = 0; file_size = 0;
} }

View File

@ -24,14 +24,6 @@
#include "InstrProfiling.h" #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 COMPILER_RT_VISIBILITY
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
{ {

View File

@ -45,6 +45,14 @@
#define LOCK_NB 4 /* don't block when locking */ #define LOCK_NB 4 /* don't block when locking */
#define LOCK_UN 8 /* unlock */ #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, void *mmap(void *start, size_t length, int prot, int flags, int fd,
off_t offset); off_t offset);

View File

@ -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;
}

View File

@ -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:}

View File

@ -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