summaryrefslogtreecommitdiff
path: root/lib/profile
diff options
context:
space:
mode:
Diffstat (limited to 'lib/profile')
-rw-r--r--lib/profile/CMakeLists.txt14
-rw-r--r--lib/profile/GCDAProfiling.c19
-rw-r--r--lib/profile/InstrProfData.inc4
-rw-r--r--lib/profile/InstrProfiling.c6
-rw-r--r--lib/profile/InstrProfilingFile.c16
-rw-r--r--lib/profile/InstrProfilingInternal.h3
-rw-r--r--lib/profile/InstrProfilingPlatformLinux.c6
-rw-r--r--lib/profile/InstrProfilingPlatformOther.c7
-rw-r--r--lib/profile/InstrProfilingPort.h14
-rw-r--r--lib/profile/InstrProfilingUtil.c68
-rw-r--r--lib/profile/InstrProfilingUtil.h3
-rw-r--r--lib/profile/InstrProfilingValue.c10
-rw-r--r--lib/profile/InstrProfilingWriter.c5
-rw-r--r--lib/profile/WindowsMMap.c61
14 files changed, 180 insertions, 56 deletions
diff --git a/lib/profile/CMakeLists.txt b/lib/profile/CMakeLists.txt
index 342f8ee7ebbc..91d67ec365c5 100644
--- a/lib/profile/CMakeLists.txt
+++ b/lib/profile/CMakeLists.txt
@@ -38,6 +38,14 @@ int main() {
" COMPILER_RT_TARGET_HAS_FCNTL_LCK)
+CHECK_CXX_SOURCE_COMPILES("
+#include <sys/utsname.h>
+int main() {
+ return 0;
+}
+
+" COMPILER_RT_TARGET_HAS_UNAME)
+
add_compiler_rt_component(profile)
set(PROFILE_SOURCES
@@ -78,6 +86,12 @@ if(COMPILER_RT_TARGET_HAS_FCNTL_LCK)
-DCOMPILER_RT_HAS_FCNTL_LCK=1)
endif()
+if(COMPILER_RT_TARGET_HAS_UNAME)
+ set(EXTRA_FLAGS
+ ${EXTRA_FLAGS}
+ -DCOMPILER_RT_HAS_UNAME=1)
+endif()
+
# This appears to be a C-only warning banning the use of locals in aggregate
# initializers. All other compilers accept this, though.
# nonstandard extension used : 'identifier' : cannot be initialized using address of automatic variable
diff --git a/lib/profile/GCDAProfiling.c b/lib/profile/GCDAProfiling.c
index 138af6ec4033..ef299f002e20 100644
--- a/lib/profile/GCDAProfiling.c
+++ b/lib/profile/GCDAProfiling.c
@@ -20,9 +20,6 @@
|*
\*===----------------------------------------------------------------------===*/
-#include "InstrProfilingPort.h"
-#include "InstrProfilingUtil.h"
-
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
@@ -34,9 +31,6 @@
#else
#include <sys/mman.h>
#include <sys/file.h>
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif
#endif
#if defined(__FreeBSD__) && defined(__i386__)
@@ -62,6 +56,9 @@ typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
#endif
+#include "InstrProfiling.h"
+#include "InstrProfilingUtil.h"
+
/* #define DEBUG_GCDAPROFILING */
/*
@@ -238,17 +235,17 @@ void llvm_gcda_start_file(const char *orig_filename, const char version[4],
/* Try just opening the file. */
new_file = 0;
- fd = open(filename, O_RDWR);
+ fd = open(filename, O_RDWR | O_BINARY);
if (fd == -1) {
/* Try opening the file, creating it if necessary. */
new_file = 1;
mode = "w+b";
- fd = open(filename, O_RDWR | O_CREAT, 0644);
+ fd = open(filename, O_RDWR | O_CREAT | O_BINARY, 0644);
if (fd == -1) {
/* Try creating the directories first then opening the file. */
__llvm_profile_recursive_mkdir(filename);
- fd = open(filename, O_RDWR | O_CREAT, 0644);
+ fd = open(filename, O_RDWR | O_CREAT | O_BINARY, 0644);
if (fd == -1) {
/* Bah! It's hopeless. */
int errnum = errno;
@@ -263,7 +260,7 @@ void llvm_gcda_start_file(const char *orig_filename, const char version[4],
* same GCDA. This can fail if the filesystem doesn't support it, but in that
* case we'll just carry on with the old racy behaviour and hope for the best.
*/
- flock(fd, LOCK_EX);
+ lprofLockFd(fd);
output_file = fdopen(fd, mode);
/* Initialize the write buffer. */
@@ -462,7 +459,7 @@ void llvm_gcda_end_file() {
unmap_file();
}
- flock(fd, LOCK_UN);
+ lprofUnlockFd(fd);
fclose(output_file);
output_file = NULL;
write_buffer = NULL;
diff --git a/lib/profile/InstrProfData.inc b/lib/profile/InstrProfData.inc
index be0dd4ad04bf..6a98dc7b9b85 100644
--- a/lib/profile/InstrProfData.inc
+++ b/lib/profile/InstrProfData.inc
@@ -628,9 +628,9 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
/* Raw profile format version (start from 1). */
#define INSTR_PROF_RAW_VERSION 4
/* Indexed profile format version (start from 1). */
-#define INSTR_PROF_INDEX_VERSION 4
+#define INSTR_PROF_INDEX_VERSION 5
/* Coverage mapping format vresion (start from 0). */
-#define INSTR_PROF_COVMAP_VERSION 1
+#define INSTR_PROF_COVMAP_VERSION 2
/* Profile version is always of type uint64_t. Reserve the upper 8 bits in the
* version for other variants of profile. We set the lowest bit of the upper 8
diff --git a/lib/profile/InstrProfiling.c b/lib/profile/InstrProfiling.c
index fe66fec50658..00b31e1ee7d4 100644
--- a/lib/profile/InstrProfiling.c
+++ b/lib/profile/InstrProfiling.c
@@ -7,12 +7,14 @@
|*
\*===----------------------------------------------------------------------===*/
-#include "InstrProfiling.h"
-#include "InstrProfilingInternal.h"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+
#define INSTR_PROF_VALUE_PROF_DATA
#include "InstrProfData.inc"
diff --git a/lib/profile/InstrProfilingFile.c b/lib/profile/InstrProfilingFile.c
index d038bb9cb5b0..d7c0abbc16e3 100644
--- a/lib/profile/InstrProfilingFile.c
+++ b/lib/profile/InstrProfilingFile.c
@@ -7,9 +7,6 @@
|*
\*===----------------------------------------------------------------------===*/
-#include "InstrProfiling.h"
-#include "InstrProfilingInternal.h"
-#include "InstrProfilingUtil.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -31,6 +28,10 @@
#endif
#endif
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+#include "InstrProfilingUtil.h"
+
/* From where is profile name specified.
* The order the enumerators define their
* precedence. Re-order them may lead to
@@ -85,7 +86,6 @@ typedef struct lprofFilename {
COMPILER_RT_WEAK lprofFilename lprofCurFilename = {0, 0, 0, {0}, {0},
0, 0, 0, PNS_unknown};
-int getpid(void);
static int getCurFilenameLength();
static const char *getCurFilename(char *FilenameBuf);
static unsigned doMerging() { return lprofCurFilename.MergePoolSize; }
@@ -325,7 +325,7 @@ static int parseFilenamePattern(const char *FilenamePat,
if (FilenamePat[I] == '%') {
if (FilenamePat[++I] == 'p') {
if (!NumPids++) {
- if (snprintf(PidChars, MAX_PID_SIZE, "%d", getpid()) <= 0) {
+ if (snprintf(PidChars, MAX_PID_SIZE, "%ld", (long)getpid()) <= 0) {
PROF_WARN("Unable to get pid for filename pattern %s. Using the "
"default name.",
FilenamePat);
@@ -519,8 +519,10 @@ void __llvm_profile_initialize_file(void) {
EnvFilenamePat = getFilenamePatFromEnv();
if (EnvFilenamePat) {
- SelectedPat = EnvFilenamePat;
- PNS = PNS_environment;
+ /* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
+ at the moment when __llvm_profile_write_file() gets executed. */
+ parseAndSetFilename(EnvFilenamePat, PNS_environment, 1);
+ return;
} else if (hasCommandLineOverrider) {
SelectedPat = INSTR_PROF_PROFILE_NAME_VAR;
PNS = PNS_command_line;
diff --git a/lib/profile/InstrProfilingInternal.h b/lib/profile/InstrProfilingInternal.h
index 36490ef7d433..40540ab5f205 100644
--- a/lib/profile/InstrProfilingInternal.h
+++ b/lib/profile/InstrProfilingInternal.h
@@ -10,8 +10,9 @@
#ifndef PROFILE_INSTRPROFILING_INTERNALH_
#define PROFILE_INSTRPROFILING_INTERNALH_
+#include <stddef.h>
+
#include "InstrProfiling.h"
-#include "stddef.h"
/*!
* \brief Write instrumentation data to the given buffer, given explicit
diff --git a/lib/profile/InstrProfilingPlatformLinux.c b/lib/profile/InstrProfilingPlatformLinux.c
index b6c780ff514f..89f1ab4cfeda 100644
--- a/lib/profile/InstrProfilingPlatformLinux.c
+++ b/lib/profile/InstrProfilingPlatformLinux.c
@@ -7,11 +7,13 @@
|*
\*===----------------------------------------------------------------------===*/
-#include "InstrProfiling.h"
+#if defined(__linux__) || defined(__FreeBSD__) || \
+ (defined(__sun__) && defined(__svr4__))
-#if defined(__linux__) || defined(__FreeBSD__)
#include <stdlib.h>
+#include "InstrProfiling.h"
+
#define PROF_DATA_START INSTR_PROF_SECT_START(INSTR_PROF_DATA_SECT_NAME)
#define PROF_DATA_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_DATA_SECT_NAME)
#define PROF_NAME_START INSTR_PROF_SECT_START(INSTR_PROF_NAME_SECT_NAME)
diff --git a/lib/profile/InstrProfilingPlatformOther.c b/lib/profile/InstrProfilingPlatformOther.c
index b25966487e91..a339abc7f883 100644
--- a/lib/profile/InstrProfilingPlatformOther.c
+++ b/lib/profile/InstrProfilingPlatformOther.c
@@ -7,12 +7,13 @@
|*
\*===----------------------------------------------------------------------===*/
-#include "InstrProfiling.h"
-
-#if !defined(__APPLE__) && !defined(__linux__) && !defined(__FreeBSD__)
+#if !defined(__APPLE__) && !defined(__linux__) && !defined(__FreeBSD__) && \
+ !(defined(__sun__) && defined(__svr4__))
#include <stdlib.h>
+#include "InstrProfiling.h"
+
static const __llvm_profile_data *DataFirst = NULL;
static const __llvm_profile_data *DataLast = NULL;
static const char *NamesFirst = NULL;
diff --git a/lib/profile/InstrProfilingPort.h b/lib/profile/InstrProfilingPort.h
index 5789351956b9..cd1264b0e575 100644
--- a/lib/profile/InstrProfilingPort.h
+++ b/lib/profile/InstrProfilingPort.h
@@ -7,6 +7,9 @@
|*
\*===----------------------------------------------------------------------===*/
+/* This header must be included after all others so it can provide fallback
+ definitions for stuff missing in system headers. */
+
#ifndef PROFILE_INSTRPROFILING_PORT_H_
#define PROFILE_INSTRPROFILING_PORT_H_
@@ -44,9 +47,6 @@
#define COMPILER_RT_GETHOSTNAME(Name, Len) ((void)(Name), (void)(Len), (-1))
#else
#define COMPILER_RT_GETHOSTNAME(Name, Len) lprofGetHostName(Name, Len)
-#ifndef _MSC_VER
-#define COMPILER_RT_HAS_UNAME 1
-#endif
#endif
#if COMPILER_RT_HAS_ATOMICS == 1
@@ -107,6 +107,14 @@
#define PROF_NOTE(Format, ...) \
fprintf(stderr, "LLVM Profile Note: " Format, __VA_ARGS__);
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
#if defined(__FreeBSD__)
#include <inttypes.h>
diff --git a/lib/profile/InstrProfilingUtil.c b/lib/profile/InstrProfilingUtil.c
index fb68f30a5e1f..110562383412 100644
--- a/lib/profile/InstrProfilingUtil.c
+++ b/lib/profile/InstrProfilingUtil.c
@@ -7,13 +7,10 @@
|*
\*===----------------------------------------------------------------------===*/
-#include "InstrProfilingUtil.h"
-#include "InstrProfiling.h"
-
#ifdef _WIN32
#include <direct.h>
-#include <io.h>
#include <windows.h>
+#include "WindowsMMap.h"
#else
#include <sys/stat.h>
#include <sys/types.h>
@@ -34,6 +31,9 @@
#include <sys/prctl.h>
#endif
+#include "InstrProfiling.h"
+#include "InstrProfilingUtil.h"
+
COMPILER_RT_VISIBILITY
void __llvm_profile_recursive_mkdir(char *path) {
int i;
@@ -86,16 +86,16 @@ COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) {
#elif defined(COMPILER_RT_HAS_UNAME)
COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) {
struct utsname N;
- int R;
- if (!(R = uname(&N)))
+ int R = uname(&N);
+ if (R >= 0) {
strncpy(Name, N.nodename, Len);
+ return 0;
+ }
return R;
}
#endif
-COMPILER_RT_VISIBILITY FILE *lprofOpenFileEx(const char *ProfileName) {
- FILE *f;
- int fd;
+COMPILER_RT_VISIBILITY int lprofLockFd(int fd) {
#ifdef COMPILER_RT_HAS_FCNTL_LCK
struct flock s_flock;
@@ -103,21 +103,59 @@ COMPILER_RT_VISIBILITY FILE *lprofOpenFileEx(const char *ProfileName) {
s_flock.l_start = 0;
s_flock.l_len = 0; /* Until EOF. */
s_flock.l_pid = getpid();
-
s_flock.l_type = F_WRLCK;
- fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
- if (fd < 0)
- return NULL;
while (fcntl(fd, F_SETLKW, &s_flock) == -1) {
if (errno != EINTR) {
if (errno == ENOLCK) {
- PROF_WARN("Data may be corrupted during profile merging : %s\n",
- "Fail to obtain file lock due to system limit.");
+ return -1;
}
break;
}
}
+ return 0;
+#else
+ flock(fd, LOCK_EX);
+ return 0;
+#endif
+}
+
+COMPILER_RT_VISIBILITY int lprofUnlockFd(int fd) {
+#ifdef COMPILER_RT_HAS_FCNTL_LCK
+ struct flock s_flock;
+
+ s_flock.l_whence = SEEK_SET;
+ s_flock.l_start = 0;
+ s_flock.l_len = 0; /* Until EOF. */
+ s_flock.l_pid = getpid();
+ s_flock.l_type = F_UNLCK;
+
+ while (fcntl(fd, F_SETLKW, &s_flock) == -1) {
+ if (errno != EINTR) {
+ if (errno == ENOLCK) {
+ return -1;
+ }
+ break;
+ }
+ }
+ return 0;
+#else
+ flock(fd, LOCK_UN);
+ return 0;
+#endif
+}
+
+COMPILER_RT_VISIBILITY FILE *lprofOpenFileEx(const char *ProfileName) {
+ FILE *f;
+ int fd;
+#ifdef COMPILER_RT_HAS_FCNTL_LCK
+ fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
+ if (fd < 0)
+ return NULL;
+
+ if (lprofLockFd(fd) != 0)
+ PROF_WARN("Data may be corrupted during profile merging : %s\n",
+ "Fail to obtain file lock due to system limit.");
f = fdopen(fd, "r+b");
#elif defined(_WIN32)
diff --git a/lib/profile/InstrProfilingUtil.h b/lib/profile/InstrProfilingUtil.h
index 9698599606e0..2f2ea1b876a8 100644
--- a/lib/profile/InstrProfilingUtil.h
+++ b/lib/profile/InstrProfilingUtil.h
@@ -16,6 +16,9 @@
/*! \brief Create a directory tree. */
void __llvm_profile_recursive_mkdir(char *Pathname);
+int lprofLockFd(int fd);
+int lprofUnlockFd(int fd);
+
/*! Open file \c Filename for read+write with write
* lock for exclusive access. The caller will block
* if the lock is already held by another process. */
diff --git a/lib/profile/InstrProfilingValue.c b/lib/profile/InstrProfilingValue.c
index 44263da80097..3db0de8a6723 100644
--- a/lib/profile/InstrProfilingValue.c
+++ b/lib/profile/InstrProfilingValue.c
@@ -7,13 +7,15 @@
|*
\*===----------------------------------------------------------------------===*/
-#include "InstrProfiling.h"
-#include "InstrProfilingInternal.h"
-#include "InstrProfilingUtil.h" /* For PS4 getenv shim. */
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+#include "InstrProfilingUtil.h"
+
#define INSTR_PROF_VALUE_PROF_DATA
#define INSTR_PROF_COMMON_API_IMPL
#include "InstrProfData.inc"
@@ -22,7 +24,7 @@ static int hasStaticCounters = 1;
static int OutOfNodesWarnings = 0;
static int hasNonDefaultValsPerSite = 0;
#define INSTR_PROF_MAX_VP_WARNS 10
-#define INSTR_PROF_DEFAULT_NUM_VAL_PER_SITE 8
+#define INSTR_PROF_DEFAULT_NUM_VAL_PER_SITE 16
#define INSTR_PROF_VNODE_POOL_SIZE 1024
#ifndef _MSC_VER
diff --git a/lib/profile/InstrProfilingWriter.c b/lib/profile/InstrProfilingWriter.c
index d4c9b9bd663c..7c6061d2c65a 100644
--- a/lib/profile/InstrProfilingWriter.c
+++ b/lib/profile/InstrProfilingWriter.c
@@ -7,14 +7,15 @@
|*
\*===----------------------------------------------------------------------===*/
-#include "InstrProfiling.h"
-#include "InstrProfilingInternal.h"
#ifdef _MSC_VER
/* For _alloca */
#include <malloc.h>
#endif
#include <string.h>
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+
#define INSTR_PROF_VALUE_PROF_DATA
#include "InstrProfData.inc"
diff --git a/lib/profile/WindowsMMap.c b/lib/profile/WindowsMMap.c
index f81d7da5389e..dc87a888ae7b 100644
--- a/lib/profile/WindowsMMap.c
+++ b/lib/profile/WindowsMMap.c
@@ -18,11 +18,12 @@
#if defined(_WIN32)
#include "WindowsMMap.h"
-#include "InstrProfiling.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+#include "InstrProfiling.h"
+
#ifdef __USE_FILE_OFFSET64
# define DWORD_HI(x) (x >> 32)
# define DWORD_LO(x) ((x) & 0xffffffff)
@@ -120,9 +121,61 @@ int msync(void *addr, size_t length, int flags)
}
COMPILER_RT_VISIBILITY
-int flock(int fd, int operation)
-{
- return -1; /* Not supported. */
+int lock(HANDLE handle, DWORD lockType, BOOL blocking) {
+ DWORD flags = lockType;
+ if (!blocking)
+ flags |= LOCKFILE_FAIL_IMMEDIATELY;
+
+ OVERLAPPED overlapped;
+ ZeroMemory(&overlapped, sizeof(OVERLAPPED));
+ overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ BOOL result = LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped);
+ if (!result) {
+ DWORD dw = GetLastError();
+
+ // In non-blocking mode, return an error if the file is locked.
+ if (!blocking && dw == ERROR_LOCK_VIOLATION)
+ return -1; // EWOULDBLOCK
+
+ // If the error is ERROR_IO_PENDING, we need to wait until the operation
+ // finishes. Otherwise, we return an error.
+ if (dw != ERROR_IO_PENDING)
+ return -1;
+
+ DWORD dwNumBytes;
+ if (!GetOverlappedResult(handle, &overlapped, &dwNumBytes, TRUE))
+ return -1;
+ }
+
+ return 0;
+}
+
+COMPILER_RT_VISIBILITY
+int flock(int fd, int operation) {
+ HANDLE handle = (HANDLE)_get_osfhandle(fd);
+ if (handle == INVALID_HANDLE_VALUE)
+ return -1;
+
+ BOOL blocking = (operation & LOCK_NB) == 0;
+ int op = operation & ~LOCK_NB;
+
+ switch (op) {
+ case LOCK_EX:
+ return lock(handle, LOCKFILE_EXCLUSIVE_LOCK, blocking);
+
+ case LOCK_SH:
+ return lock(handle, 0, blocking);
+
+ case LOCK_UN:
+ if (!UnlockFile(handle, 0, 0, MAXDWORD, MAXDWORD))
+ return -1;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
}
#undef DWORD_HI