• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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