]> git.proxmox.com Git - rustc.git/blame - src/compiler-rt/lib/profile/InstrProfilingUtil.c
New upstream version 1.12.0+dfsg1
[rustc.git] / src / compiler-rt / lib / profile / InstrProfilingUtil.c
CommitLineData
92a42be0
SL
1/*===- InstrProfilingUtil.c - Support library for PGO instrumentation -----===*\
2|*
3|* The LLVM Compiler Infrastructure
4|*
5|* This file is distributed under the University of Illinois Open Source
6|* License. See LICENSE.TXT for details.
7|*
8\*===----------------------------------------------------------------------===*/
9
10#include "InstrProfilingUtil.h"
3157f602 11#include "InstrProfiling.h"
92a42be0
SL
12
13#ifdef _WIN32
14#include <direct.h>
5bcae85e
SL
15#include <io.h>
16#include <windows.h>
92a42be0
SL
17#else
18#include <sys/stat.h>
19#include <sys/types.h>
5bcae85e
SL
20#include <unistd.h>
21#include <fcntl.h>
22#include <errno.h>
92a42be0
SL
23#endif
24
5bcae85e
SL
25#ifdef COMPILER_RT_HAS_UNAME
26#include <sys/utsname.h>
27#endif
28
29#include <stdlib.h>
30#include <string.h>
31
3157f602 32COMPILER_RT_VISIBILITY
92a42be0
SL
33void __llvm_profile_recursive_mkdir(char *path) {
34 int i;
35
36 for (i = 1; path[i] != '\0'; ++i) {
5bcae85e
SL
37 char save = path[i];
38 if (!(path[i] == '/' || path[i] == '\\'))
39 continue;
92a42be0
SL
40 path[i] = '\0';
41#ifdef _WIN32
42 _mkdir(path);
43#else
5bcae85e 44 mkdir(path, 0755); /* Some of these will fail, ignore it. */
92a42be0 45#endif
5bcae85e
SL
46 path[i] = save;
47 }
48}
49
50#if COMPILER_RT_HAS_ATOMICS != 1
51COMPILER_RT_VISIBILITY
52uint32_t lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV) {
53 void *R = *Ptr;
54 if (R == OldV) {
55 *Ptr = NewV;
56 return 1;
57 }
58 return 0;
59}
60COMPILER_RT_VISIBILITY
61void *lprofPtrFetchAdd(void **Mem, long ByteIncr) {
62 void *Old = *Mem;
63 *((char **)Mem) += ByteIncr;
64 return Old;
65}
66
67#endif
68
69#ifdef COMPILER_RT_HAS_UNAME
70COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) {
71 struct utsname N;
72 int R;
73 if (!(R = uname(&N)))
74 strncpy(Name, N.nodename, Len);
75 return R;
76}
77#endif
78
79COMPILER_RT_VISIBILITY FILE *lprofOpenFileEx(const char *ProfileName) {
80 FILE *f;
81 int fd;
82#ifdef COMPILER_RT_HAS_FCNTL_LCK
83 struct flock s_flock;
84
85 s_flock.l_whence = SEEK_SET;
86 s_flock.l_start = 0;
87 s_flock.l_len = 0; /* Until EOF. */
88 s_flock.l_pid = getpid();
89
90 s_flock.l_type = F_WRLCK;
91 fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
92 if (fd < 0)
93 return NULL;
94
95 while (fcntl(fd, F_SETLKW, &s_flock) == -1) {
96 if (errno != EINTR) {
97 if (errno == ENOLCK) {
98 PROF_WARN("Data may be corrupted during profile merging : %s\n",
99 "Fail to obtain file lock due to system limit.");
100 }
101 break;
102 }
103 }
104
105 f = fdopen(fd, "r+b");
106#elif defined(_WIN32)
107 // FIXME: Use the wide variants to handle Unicode filenames.
108 HANDLE h = CreateFileA(ProfileName, GENERIC_READ | GENERIC_WRITE, 0, 0,
109 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
110 if (h == INVALID_HANDLE_VALUE)
111 return NULL;
112
113 fd = _open_osfhandle((intptr_t)h, 0);
114 if (fd == -1) {
115 CloseHandle(h);
116 return NULL;
92a42be0 117 }
5bcae85e
SL
118
119 f = _fdopen(fd, "r+b");
120 if (f == 0) {
121 CloseHandle(h);
122 return NULL;
123 }
124#else
125 /* Worst case no locking applied. */
126 PROF_WARN("Concurrent file access is not supported : %s\n",
127 "lack file locking");
128 fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
129 if (fd < 0)
130 return NULL;
131 f = fdopen(fd, "r+b");
132#endif
133
134 return f;
135}
136
137COMPILER_RT_VISIBILITY const char *lprofGetPathPrefix(int *PrefixStrip,
138 size_t *PrefixLen) {
139 const char *Prefix = getenv("GCOV_PREFIX");
140 const char *PrefixStripStr = getenv("GCOV_PREFIX_STRIP");
141
142 *PrefixLen = 0;
143 *PrefixStrip = 0;
144 if (Prefix == NULL || Prefix[0] == '\0')
145 return NULL;
146
147 if (PrefixStripStr) {
148 *PrefixStrip = atoi(PrefixStripStr);
149
150 /* Negative GCOV_PREFIX_STRIP values are ignored */
151 if (*PrefixStrip < 0)
152 *PrefixStrip = 0;
153 } else {
154 *PrefixStrip = 0;
155 }
156 *PrefixLen = strlen(Prefix);
157
158 return Prefix;
159}
160
161COMPILER_RT_VISIBILITY void
162lprofApplyPathPrefix(char *Dest, const char *PathStr, const char *Prefix,
163 size_t PrefixLen, int PrefixStrip) {
164
165 const char *Ptr;
166 int Level;
167 const char *StrippedPathStr = PathStr;
168
169 for (Level = 0, Ptr = PathStr + 1; Level < PrefixStrip; ++Ptr) {
170 if (*Ptr == '\0')
171 break;
172
173 if (!IS_DIR_SEPARATOR(*Ptr))
174 continue;
175
176 StrippedPathStr = Ptr;
177 ++Level;
178 }
179
180 memcpy(Dest, Prefix, PrefixLen);
181
182 if (!IS_DIR_SEPARATOR(Prefix[PrefixLen - 1]))
183 Dest[PrefixLen++] = DIR_SEPARATOR;
184
185 memcpy(Dest + PrefixLen, StrippedPathStr, strlen(StrippedPathStr) + 1);
92a42be0 186}