1 /*===- InstrProfilingUtil.c - Support library for PGO instrumentation -----===*\
3 |* The LLVM Compiler Infrastructure
5 |* This file is distributed under the University of Illinois Open Source
6 |* License. See LICENSE.TXT for details.
8 \*===----------------------------------------------------------------------===*/
13 #include "WindowsMMap.h"
16 #include <sys/types.h>
22 #ifdef COMPILER_RT_HAS_UNAME
23 #include <sys/utsname.h>
29 #if defined(__linux__)
31 #include <sys/prctl.h>
34 #include "InstrProfiling.h"
35 #include "InstrProfilingUtil.h"
37 COMPILER_RT_VISIBILITY
38 void __llvm_profile_recursive_mkdir(char *path) {
41 for (i = 1; path[i] != '\0'; ++i) {
43 if (!IS_DIR_SEPARATOR(path[i]))
49 mkdir(path, 0755); /* Some of these will fail, ignore it. */
55 #if COMPILER_RT_HAS_ATOMICS != 1
56 COMPILER_RT_VISIBILITY
57 uint32_t lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV) {
65 COMPILER_RT_VISIBILITY
66 void *lprofPtrFetchAdd(void **Mem, long ByteIncr) {
68 *((char **)Mem) += ByteIncr;
75 COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) {
76 WCHAR Buffer[COMPILER_RT_MAX_HOSTLEN];
77 DWORD BufferSize = sizeof(Buffer);
79 GetComputerNameExW(ComputerNameDnsFullyQualified, Buffer, &BufferSize);
82 if (WideCharToMultiByte(CP_UTF8, 0, Buffer, -1, Name, Len, NULL, NULL) == 0)
86 #elif defined(COMPILER_RT_HAS_UNAME)
87 COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) {
91 strncpy(Name, N.nodename, Len);
98 COMPILER_RT_VISIBILITY int lprofLockFd(int fd) {
99 #ifdef COMPILER_RT_HAS_FCNTL_LCK
100 struct flock s_flock;
102 s_flock.l_whence = SEEK_SET;
104 s_flock.l_len = 0; /* Until EOF. */
105 s_flock.l_pid = getpid();
106 s_flock.l_type = F_WRLCK;
108 while (fcntl(fd, F_SETLKW, &s_flock) == -1) {
109 if (errno != EINTR) {
110 if (errno == ENOLCK) {
123 COMPILER_RT_VISIBILITY int lprofUnlockFd(int fd) {
124 #ifdef COMPILER_RT_HAS_FCNTL_LCK
125 struct flock s_flock;
127 s_flock.l_whence = SEEK_SET;
129 s_flock.l_len = 0; /* Until EOF. */
130 s_flock.l_pid = getpid();
131 s_flock.l_type = F_UNLCK;
133 while (fcntl(fd, F_SETLKW, &s_flock) == -1) {
134 if (errno != EINTR) {
135 if (errno == ENOLCK) {
148 COMPILER_RT_VISIBILITY FILE *lprofOpenFileEx(const char *ProfileName) {
151 #ifdef COMPILER_RT_HAS_FCNTL_LCK
152 fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
156 if (lprofLockFd(fd) != 0)
157 PROF_WARN("Data may be corrupted during profile merging : %s\n",
158 "Fail to obtain file lock due to system limit.");
160 f = fdopen(fd, "r+b");
161 #elif defined(_WIN32)
162 // FIXME: Use the wide variants to handle Unicode filenames.
163 HANDLE h = CreateFileA(ProfileName, GENERIC_READ | GENERIC_WRITE, 0, 0,
164 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
165 if (h == INVALID_HANDLE_VALUE)
168 fd = _open_osfhandle((intptr_t)h, 0);
174 f = _fdopen(fd, "r+b");
180 /* Worst case no locking applied. */
181 PROF_WARN("Concurrent file access is not supported : %s\n",
182 "lack file locking");
183 fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
186 f = fdopen(fd, "r+b");
192 COMPILER_RT_VISIBILITY const char *lprofGetPathPrefix(int *PrefixStrip,
194 const char *Prefix = getenv("GCOV_PREFIX");
195 const char *PrefixStripStr = getenv("GCOV_PREFIX_STRIP");
199 if (Prefix == NULL || Prefix[0] == '\0')
202 if (PrefixStripStr) {
203 *PrefixStrip = atoi(PrefixStripStr);
205 /* Negative GCOV_PREFIX_STRIP values are ignored */
206 if (*PrefixStrip < 0)
211 *PrefixLen = strlen(Prefix);
216 COMPILER_RT_VISIBILITY void
217 lprofApplyPathPrefix(char *Dest, const char *PathStr, const char *Prefix,
218 size_t PrefixLen, int PrefixStrip) {
222 const char *StrippedPathStr = PathStr;
224 for (Level = 0, Ptr = PathStr + 1; Level < PrefixStrip; ++Ptr) {
228 if (!IS_DIR_SEPARATOR(*Ptr))
231 StrippedPathStr = Ptr;
235 memcpy(Dest, Prefix, PrefixLen);
237 if (!IS_DIR_SEPARATOR(Prefix[PrefixLen - 1]))
238 Dest[PrefixLen++] = DIR_SEPARATOR;
240 memcpy(Dest + PrefixLen, StrippedPathStr, strlen(StrippedPathStr) + 1);
243 COMPILER_RT_VISIBILITY const char *
244 lprofFindFirstDirSeparator(const char *Path) {
246 Sep = strchr(Path, DIR_SEPARATOR);
249 #if defined(DIR_SEPARATOR_2)
250 Sep = strchr(Path, DIR_SEPARATOR_2);
255 COMPILER_RT_VISIBILITY const char *lprofFindLastDirSeparator(const char *Path) {
257 Sep = strrchr(Path, DIR_SEPARATOR);
260 #if defined(DIR_SEPARATOR_2)
261 Sep = strrchr(Path, DIR_SEPARATOR_2);
266 COMPILER_RT_VISIBILITY int lprofSuspendSigKill() {
267 #if defined(__linux__)
269 /* Temporarily suspend getting SIGKILL upon exit of the parent process. */
270 if (prctl(PR_GET_PDEATHSIG, &PDeachSig) == 0 && PDeachSig == SIGKILL)
271 prctl(PR_SET_PDEATHSIG, 0);
272 return (PDeachSig == SIGKILL);
278 COMPILER_RT_VISIBILITY void lprofRestoreSigKill() {
279 #if defined(__linux__)
280 prctl(PR_SET_PDEATHSIG, SIGKILL);