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
31COMPILER_RT_VISIBILITY
32void __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
50COMPILER_RT_VISIBILITY
51uint32_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}
59COMPILER_RT_VISIBILITY
60void *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
69COMPILER_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
78COMPILER_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