COMPILER_RT_VISIBILITY FILE *lprofOpenFileEx(const char *ProfileName) { FILE *f; 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_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."); } break; } } f = fdopen(fd, "r+b"); #elif defined(_WIN32) // FIXME: Use the wide variants to handle Unicode filenames. HANDLE h = CreateFileA(ProfileName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (h == INVALID_HANDLE_VALUE) return NULL; fd = _open_osfhandle((intptr_t)h, 0); if (fd == -1) { CloseHandle(h); return NULL; } f = _fdopen(fd, "r+b"); if (f == 0) { CloseHandle(h); return NULL; } #else /* Worst case no locking applied. */ PROF_WARN("Concurrent file access is not supported : %s\n", "lack file locking"); fd = open(ProfileName, O_RDWR | O_CREAT, 0666); if (fd < 0) return NULL; f = fdopen(fd, "r+b"); #endif return f; }
/* Parses the pattern string \p FilenamePat and stores the result to * lprofcurFilename structure. */ static int parseFilenamePattern(const char *FilenamePat) { int NumPids = 0, NumHosts = 0, I; char *PidChars = &lprofCurFilename.PidChars[0]; char *Hostname = &lprofCurFilename.Hostname[0]; int MergingEnabled = 0; lprofCurFilename.FilenamePat = FilenamePat; /* Check the filename for "%p", which indicates a pid-substitution. */ for (I = 0; FilenamePat[I]; ++I) if (FilenamePat[I] == '%') { if (FilenamePat[++I] == 'p') { if (!NumPids++) { if (snprintf(PidChars, MAX_PID_SIZE, "%d", getpid()) <= 0) { PROF_WARN( "Unable to parse filename pattern %s. Using the default name.", FilenamePat); return -1; } } } else if (FilenamePat[I] == 'h') { if (!NumHosts++) if (COMPILER_RT_GETHOSTNAME(Hostname, COMPILER_RT_MAX_HOSTLEN)) { PROF_WARN( "Unable to parse filename pattern %s. Using the default name.", FilenamePat); return -1; } } else if (containsMergeSpecifier(FilenamePat, I)) { if (MergingEnabled) { PROF_WARN( "%%m specifier can only be specified once at the end of %s.\n", FilenamePat); return -1; } MergingEnabled = 1; if (FilenamePat[I] == 'm') lprofCurFilename.MergePoolSize = 1; else { lprofCurFilename.MergePoolSize = FilenamePat[I] - '0'; I++; /* advance to 'm' */ } } } lprofCurFilename.NumPids = NumPids; lprofCurFilename.NumHosts = NumHosts; return 0; }
/* Read profile data in \c ProfileFile and merge with in-memory profile counters. Returns -1 if there is fatal error, otheriwse 0 is returned. */ static int doProfileMerging(FILE *ProfileFile) { uint64_t ProfileFileSize; char *ProfileBuffer; if (fseek(ProfileFile, 0L, SEEK_END) == -1) { PROF_ERR("Unable to merge profile data, unable to get size: %s\n", strerror(errno)); return -1; } ProfileFileSize = ftell(ProfileFile); /* Restore file offset. */ if (fseek(ProfileFile, 0L, SEEK_SET) == -1) { PROF_ERR("Unable to merge profile data, unable to rewind: %s\n", strerror(errno)); return -1; } /* Nothing to merge. */ if (ProfileFileSize < sizeof(__llvm_profile_header)) { if (ProfileFileSize) PROF_WARN("Unable to merge profile data: %s\n", "source profile file is too small."); return 0; } ProfileBuffer = mmap(NULL, ProfileFileSize, PROT_READ, MAP_SHARED | MAP_FILE, fileno(ProfileFile), 0); if (ProfileBuffer == MAP_FAILED) { PROF_ERR("Unable to merge profile data, mmap failed: %s\n", strerror(errno)); return -1; } if (__llvm_profile_check_compatibility(ProfileBuffer, ProfileFileSize)) { (void)munmap(ProfileBuffer, ProfileFileSize); PROF_WARN("Unable to merge profile data: %s\n", "source profile file is not compatible."); return 0; } /* Now start merging */ __llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize); (void)munmap(ProfileBuffer, ProfileFileSize); return 0; }
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) // FIXME: Use the wide variants to handle Unicode filenames. HANDLE h = CreateFileA(ProfileName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (h == INVALID_HANDLE_VALUE) return NULL; fd = _open_osfhandle((intptr_t)h, 0); if (fd == -1) { CloseHandle(h); return NULL; } f = _fdopen(fd, "r+b"); if (f == 0) { CloseHandle(h); return NULL; } #else /* Worst case no locking applied. */ PROF_WARN("Concurrent file access is not supported : %s\n", "lack file locking"); fd = open(ProfileName, O_RDWR | O_CREAT, 0666); if (fd < 0) return NULL; f = fdopen(fd, "r+b"); #endif return f; }