Home | History | Annotate | Download | only in profile
      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
     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
     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
     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
     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 
     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