diff options
Diffstat (limited to 'lib/profile')
-rw-r--r-- | lib/profile/CMakeLists.txt | 14 | ||||
-rw-r--r-- | lib/profile/GCDAProfiling.c | 19 | ||||
-rw-r--r-- | lib/profile/InstrProfData.inc | 4 | ||||
-rw-r--r-- | lib/profile/InstrProfiling.c | 6 | ||||
-rw-r--r-- | lib/profile/InstrProfilingFile.c | 16 | ||||
-rw-r--r-- | lib/profile/InstrProfilingInternal.h | 3 | ||||
-rw-r--r-- | lib/profile/InstrProfilingPlatformLinux.c | 6 | ||||
-rw-r--r-- | lib/profile/InstrProfilingPlatformOther.c | 7 | ||||
-rw-r--r-- | lib/profile/InstrProfilingPort.h | 14 | ||||
-rw-r--r-- | lib/profile/InstrProfilingUtil.c | 68 | ||||
-rw-r--r-- | lib/profile/InstrProfilingUtil.h | 3 | ||||
-rw-r--r-- | lib/profile/InstrProfilingValue.c | 10 | ||||
-rw-r--r-- | lib/profile/InstrProfilingWriter.c | 5 | ||||
-rw-r--r-- | lib/profile/WindowsMMap.c | 61 |
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 |