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"
11 #include "InstrProfiling.h"
12
13 #ifdef _WIN32
14 #include <direct.h>
15 #include <io.h>
16 #include <windows.h>
17 #else
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <errno.h>
23 #endif
24
25 #ifdef COMPILER_RT_HAS_UNAME
26 #include <sys/utsname.h>
27 #endif
28
29 #include <string.h>
30
31 COMPILER_RT_VISIBILITY
__llvm_profile_recursive_mkdir(char * path)32 void __llvm_profile_recursive_mkdir(char *path) {
33 int i;
34
35 for (i = 1; path[i] != '\0'; ++i) {
36 char save = path[i];
37 if (!(path[i] == '/' || path[i] == '\\'))
38 continue;
39 path[i] = '\0';
40 #ifdef _WIN32
41 _mkdir(path);
42 #else
43 mkdir(path, 0755); /* Some of these will fail, ignore it. */
44 #endif
45 path[i] = save;
46 }
47 }
48
49 #if COMPILER_RT_HAS_ATOMICS != 1
50 COMPILER_RT_VISIBILITY
lprofBoolCmpXchg(void ** Ptr,void * OldV,void * NewV)51 uint32_t lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV) {
52 void *R = *Ptr;
53 if (R == OldV) {
54 *Ptr = NewV;
55 return 1;
56 }
57 return 0;
58 }
59 COMPILER_RT_VISIBILITY
lprofPtrFetchAdd(void ** Mem,long ByteIncr)60 void *lprofPtrFetchAdd(void **Mem, long ByteIncr) {
61 void *Old = *Mem;
62 *((char **)Mem) += ByteIncr;
63 return Old;
64 }
65
66 #endif
67
68 #ifdef COMPILER_RT_HAS_UNAME
lprofGetHostName(char * Name,int Len)69 COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) {
70 struct utsname N;
71 int R;
72 if (!(R = uname(&N)))
73 strncpy(Name, N.nodename, Len);
74 return R;
75 }
76 #endif
77
lprofOpenFileEx(const char * ProfileName)78 COMPILER_RT_VISIBILITY FILE *lprofOpenFileEx(const char *ProfileName) {
79 FILE *f;
80 int fd;
81 #ifdef COMPILER_RT_HAS_FCNTL_LCK
82 struct flock s_flock;
83
84 s_flock.l_whence = SEEK_SET;
85 s_flock.l_start = 0;
86 s_flock.l_len = 0; /* Until EOF. */
87 s_flock.l_pid = getpid();
88
89 s_flock.l_type = F_WRLCK;
90 fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
91 if (fd < 0)
92 return NULL;
93
94 while (fcntl(fd, F_SETLKW, &s_flock) == -1) {
95 if (errno != EINTR) {
96 if (errno == ENOLCK) {
97 PROF_WARN("Data may be corrupted during profile merging : %s\n",
98 "Fail to obtain file lock due to system limit.");
99 }
100 break;
101 }
102 }
103
104 f = fdopen(fd, "r+b");
105 #elif defined(_WIN32)
106 // FIXME: Use the wide variants to handle Unicode filenames.
107 HANDLE h = CreateFileA(ProfileName, GENERIC_READ | GENERIC_WRITE, 0, 0,
108 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
109 if (h == INVALID_HANDLE_VALUE)
110 return NULL;
111
112 fd = _open_osfhandle((intptr_t)h, 0);
113 if (fd == -1) {
114 CloseHandle(h);
115 return NULL;
116 }
117
118 f = _fdopen(fd, "r+b");
119 if (f == 0) {
120 CloseHandle(h);
121 return NULL;
122 }
123 #else
124 /* Worst case no locking applied. */
125 PROF_WARN("Concurrent file access is not supported : %s\n",
126 "lack file locking");
127 fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
128 if (fd < 0)
129 return NULL;
130 f = fdopen(fd, "r+b");
131 #endif
132
133 return f;
134 }
135