xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/profile/InstrProfilingUtil.c (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
10b57cec5SDimitry Andric /*===- InstrProfilingUtil.c - Support library for PGO instrumentation -----===*\
20b57cec5SDimitry Andric |*
30b57cec5SDimitry Andric |* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric |* See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric |*
70b57cec5SDimitry Andric \*===----------------------------------------------------------------------===*/
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifdef _WIN32
100b57cec5SDimitry Andric #include <direct.h>
110b57cec5SDimitry Andric #include <process.h>
120b57cec5SDimitry Andric #include <windows.h>
130b57cec5SDimitry Andric #include "WindowsMMap.h"
140b57cec5SDimitry Andric #else
15fe6060f1SDimitry Andric #include <errno.h>
16fe6060f1SDimitry Andric #include <fcntl.h>
1768d75effSDimitry Andric #include <sys/file.h>
18fe6060f1SDimitry Andric #include <sys/mman.h>
190b57cec5SDimitry Andric #include <sys/stat.h>
200b57cec5SDimitry Andric #include <sys/types.h>
210b57cec5SDimitry Andric #include <unistd.h>
220b57cec5SDimitry Andric #endif
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric #ifdef COMPILER_RT_HAS_UNAME
250b57cec5SDimitry Andric #include <sys/utsname.h>
260b57cec5SDimitry Andric #endif
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric #include <stdlib.h>
290b57cec5SDimitry Andric #include <string.h>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric #if defined(__linux__)
320b57cec5SDimitry Andric #include <signal.h>
330b57cec5SDimitry Andric #include <sys/prctl.h>
340b57cec5SDimitry Andric #endif
350b57cec5SDimitry Andric 
36fe6060f1SDimitry Andric #if defined(__Fuchsia__)
37349cc55cSDimitry Andric #include <zircon/process.h>
38fe6060f1SDimitry Andric #include <zircon/syscalls.h>
39fe6060f1SDimitry Andric #endif
40fe6060f1SDimitry Andric 
41349cc55cSDimitry Andric #if defined(__FreeBSD__)
42349cc55cSDimitry Andric #include <signal.h>
43349cc55cSDimitry Andric #include <sys/procctl.h>
44349cc55cSDimitry Andric #endif
45349cc55cSDimitry Andric 
460b57cec5SDimitry Andric #include "InstrProfiling.h"
470b57cec5SDimitry Andric #include "InstrProfilingUtil.h"
480b57cec5SDimitry Andric 
49*81ad6265SDimitry Andric COMPILER_RT_VISIBILITY unsigned lprofDirMode = 0755;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric COMPILER_RT_VISIBILITY
__llvm_profile_recursive_mkdir(char * path)520b57cec5SDimitry Andric void __llvm_profile_recursive_mkdir(char *path) {
530b57cec5SDimitry Andric   int i;
5468d75effSDimitry Andric   int start = 1;
550b57cec5SDimitry Andric 
5668d75effSDimitry Andric #if defined(__ANDROID__) && defined(__ANDROID_API__) &&                        \
5768d75effSDimitry Andric     defined(__ANDROID_API_FUTURE__) &&                                         \
5868d75effSDimitry Andric     __ANDROID_API__ == __ANDROID_API_FUTURE__
5968d75effSDimitry Andric   // Avoid spammy selinux denial messages in Android by not attempting to
6068d75effSDimitry Andric   // create directories in GCOV_PREFIX.  These denials occur when creating (or
6168d75effSDimitry Andric   // even attempting to stat()) top-level directories like "/data".
6268d75effSDimitry Andric   //
6368d75effSDimitry Andric   // Do so by ignoring ${GCOV_PREFIX} when invoking mkdir().
6468d75effSDimitry Andric   const char *gcov_prefix = getenv("GCOV_PREFIX");
6568d75effSDimitry Andric   if (gcov_prefix != NULL) {
6668d75effSDimitry Andric     const int gcov_prefix_len = strlen(gcov_prefix);
6768d75effSDimitry Andric     if (strncmp(path, gcov_prefix, gcov_prefix_len) == 0)
6868d75effSDimitry Andric       start = gcov_prefix_len;
6968d75effSDimitry Andric   }
7068d75effSDimitry Andric #endif
7168d75effSDimitry Andric 
7268d75effSDimitry Andric   for (i = start; path[i] != '\0'; ++i) {
730b57cec5SDimitry Andric     char save = path[i];
740b57cec5SDimitry Andric     if (!IS_DIR_SEPARATOR(path[i]))
750b57cec5SDimitry Andric       continue;
760b57cec5SDimitry Andric     path[i] = '\0';
770b57cec5SDimitry Andric #ifdef _WIN32
780b57cec5SDimitry Andric     _mkdir(path);
790b57cec5SDimitry Andric #else
800b57cec5SDimitry Andric     /* Some of these will fail, ignore it. */
810b57cec5SDimitry Andric     mkdir(path, __llvm_profile_get_dir_mode());
820b57cec5SDimitry Andric #endif
830b57cec5SDimitry Andric     path[i] = save;
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric COMPILER_RT_VISIBILITY
__llvm_profile_set_dir_mode(unsigned Mode)880b57cec5SDimitry Andric void __llvm_profile_set_dir_mode(unsigned Mode) { lprofDirMode = Mode; }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric COMPILER_RT_VISIBILITY
__llvm_profile_get_dir_mode(void)910b57cec5SDimitry Andric unsigned __llvm_profile_get_dir_mode(void) { return lprofDirMode; }
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric #if COMPILER_RT_HAS_ATOMICS != 1
940b57cec5SDimitry Andric COMPILER_RT_VISIBILITY
lprofBoolCmpXchg(void ** Ptr,void * OldV,void * NewV)950b57cec5SDimitry Andric uint32_t lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV) {
960b57cec5SDimitry Andric   void *R = *Ptr;
970b57cec5SDimitry Andric   if (R == OldV) {
980b57cec5SDimitry Andric     *Ptr = NewV;
990b57cec5SDimitry Andric     return 1;
1000b57cec5SDimitry Andric   }
1010b57cec5SDimitry Andric   return 0;
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric COMPILER_RT_VISIBILITY
lprofPtrFetchAdd(void ** Mem,long ByteIncr)1040b57cec5SDimitry Andric void *lprofPtrFetchAdd(void **Mem, long ByteIncr) {
1050b57cec5SDimitry Andric   void *Old = *Mem;
1060b57cec5SDimitry Andric   *((char **)Mem) += ByteIncr;
1070b57cec5SDimitry Andric   return Old;
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric #endif
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric #ifdef _WIN32
lprofGetHostName(char * Name,int Len)1130b57cec5SDimitry Andric COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) {
1140b57cec5SDimitry Andric   WCHAR Buffer[COMPILER_RT_MAX_HOSTLEN];
1150b57cec5SDimitry Andric   DWORD BufferSize = sizeof(Buffer);
1160b57cec5SDimitry Andric   BOOL Result =
1170b57cec5SDimitry Andric       GetComputerNameExW(ComputerNameDnsFullyQualified, Buffer, &BufferSize);
1180b57cec5SDimitry Andric   if (!Result)
1190b57cec5SDimitry Andric     return -1;
1200b57cec5SDimitry Andric   if (WideCharToMultiByte(CP_UTF8, 0, Buffer, -1, Name, Len, NULL, NULL) == 0)
1210b57cec5SDimitry Andric     return -1;
1220b57cec5SDimitry Andric   return 0;
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric #elif defined(COMPILER_RT_HAS_UNAME)
lprofGetHostName(char * Name,int Len)1250b57cec5SDimitry Andric COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) {
1260b57cec5SDimitry Andric   struct utsname N;
1270b57cec5SDimitry Andric   int R = uname(&N);
1280b57cec5SDimitry Andric   if (R >= 0) {
1290b57cec5SDimitry Andric     strncpy(Name, N.nodename, Len);
1300b57cec5SDimitry Andric     return 0;
1310b57cec5SDimitry Andric   }
1320b57cec5SDimitry Andric   return R;
1330b57cec5SDimitry Andric }
1340b57cec5SDimitry Andric #endif
1350b57cec5SDimitry Andric 
lprofLockFd(int fd)1360b57cec5SDimitry Andric COMPILER_RT_VISIBILITY int lprofLockFd(int fd) {
1370b57cec5SDimitry Andric #ifdef COMPILER_RT_HAS_FCNTL_LCK
1380b57cec5SDimitry Andric   struct flock s_flock;
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   s_flock.l_whence = SEEK_SET;
1410b57cec5SDimitry Andric   s_flock.l_start = 0;
1420b57cec5SDimitry Andric   s_flock.l_len = 0; /* Until EOF.  */
1430b57cec5SDimitry Andric   s_flock.l_pid = getpid();
1440b57cec5SDimitry Andric   s_flock.l_type = F_WRLCK;
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   while (fcntl(fd, F_SETLKW, &s_flock) == -1) {
1470b57cec5SDimitry Andric     if (errno != EINTR) {
1480b57cec5SDimitry Andric       if (errno == ENOLCK) {
1490b57cec5SDimitry Andric         return -1;
1500b57cec5SDimitry Andric       }
1510b57cec5SDimitry Andric       break;
1520b57cec5SDimitry Andric     }
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric   return 0;
1550b57cec5SDimitry Andric #else
1560b57cec5SDimitry Andric   flock(fd, LOCK_EX);
1570b57cec5SDimitry Andric   return 0;
1580b57cec5SDimitry Andric #endif
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
lprofUnlockFd(int fd)1610b57cec5SDimitry Andric COMPILER_RT_VISIBILITY int lprofUnlockFd(int fd) {
1620b57cec5SDimitry Andric #ifdef COMPILER_RT_HAS_FCNTL_LCK
1630b57cec5SDimitry Andric   struct flock s_flock;
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   s_flock.l_whence = SEEK_SET;
1660b57cec5SDimitry Andric   s_flock.l_start = 0;
1670b57cec5SDimitry Andric   s_flock.l_len = 0; /* Until EOF.  */
1680b57cec5SDimitry Andric   s_flock.l_pid = getpid();
1690b57cec5SDimitry Andric   s_flock.l_type = F_UNLCK;
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   while (fcntl(fd, F_SETLKW, &s_flock) == -1) {
1720b57cec5SDimitry Andric     if (errno != EINTR) {
1730b57cec5SDimitry Andric       if (errno == ENOLCK) {
1740b57cec5SDimitry Andric         return -1;
1750b57cec5SDimitry Andric       }
1760b57cec5SDimitry Andric       break;
1770b57cec5SDimitry Andric     }
1780b57cec5SDimitry Andric   }
1790b57cec5SDimitry Andric   return 0;
1800b57cec5SDimitry Andric #else
1810b57cec5SDimitry Andric   flock(fd, LOCK_UN);
1820b57cec5SDimitry Andric   return 0;
1830b57cec5SDimitry Andric #endif
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric 
lprofLockFileHandle(FILE * F)1860b57cec5SDimitry Andric COMPILER_RT_VISIBILITY int lprofLockFileHandle(FILE *F) {
1870b57cec5SDimitry Andric   int fd;
1880b57cec5SDimitry Andric #if defined(_WIN32)
1890b57cec5SDimitry Andric   fd = _fileno(F);
1900b57cec5SDimitry Andric #else
1910b57cec5SDimitry Andric   fd = fileno(F);
1920b57cec5SDimitry Andric #endif
1930b57cec5SDimitry Andric   return lprofLockFd(fd);
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric 
lprofUnlockFileHandle(FILE * F)1960b57cec5SDimitry Andric COMPILER_RT_VISIBILITY int lprofUnlockFileHandle(FILE *F) {
1970b57cec5SDimitry Andric   int fd;
1980b57cec5SDimitry Andric #if defined(_WIN32)
1990b57cec5SDimitry Andric   fd = _fileno(F);
2000b57cec5SDimitry Andric #else
2010b57cec5SDimitry Andric   fd = fileno(F);
2020b57cec5SDimitry Andric #endif
2030b57cec5SDimitry Andric   return lprofUnlockFd(fd);
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric 
lprofOpenFileEx(const char * ProfileName)2060b57cec5SDimitry Andric COMPILER_RT_VISIBILITY FILE *lprofOpenFileEx(const char *ProfileName) {
2070b57cec5SDimitry Andric   FILE *f;
2080b57cec5SDimitry Andric   int fd;
2090b57cec5SDimitry Andric #ifdef COMPILER_RT_HAS_FCNTL_LCK
2100b57cec5SDimitry Andric   fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
2110b57cec5SDimitry Andric   if (fd < 0)
2120b57cec5SDimitry Andric     return NULL;
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   if (lprofLockFd(fd) != 0)
2150b57cec5SDimitry Andric     PROF_WARN("Data may be corrupted during profile merging : %s\n",
2160b57cec5SDimitry Andric               "Fail to obtain file lock due to system limit.");
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   f = fdopen(fd, "r+b");
2190b57cec5SDimitry Andric #elif defined(_WIN32)
2200b57cec5SDimitry Andric   // FIXME: Use the wide variants to handle Unicode filenames.
221c14a5a88SDimitry Andric   HANDLE h = CreateFileA(ProfileName, GENERIC_READ | GENERIC_WRITE,
222c14a5a88SDimitry Andric                          FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
223c14a5a88SDimitry Andric                          FILE_ATTRIBUTE_NORMAL, 0);
2240b57cec5SDimitry Andric   if (h == INVALID_HANDLE_VALUE)
2250b57cec5SDimitry Andric     return NULL;
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   fd = _open_osfhandle((intptr_t)h, 0);
2280b57cec5SDimitry Andric   if (fd == -1) {
2290b57cec5SDimitry Andric     CloseHandle(h);
2300b57cec5SDimitry Andric     return NULL;
2310b57cec5SDimitry Andric   }
2320b57cec5SDimitry Andric 
233c14a5a88SDimitry Andric   if (lprofLockFd(fd) != 0)
234c14a5a88SDimitry Andric     PROF_WARN("Data may be corrupted during profile merging : %s\n",
235c14a5a88SDimitry Andric               "Fail to obtain file lock due to system limit.");
236c14a5a88SDimitry Andric 
2370b57cec5SDimitry Andric   f = _fdopen(fd, "r+b");
2380b57cec5SDimitry Andric   if (f == 0) {
2390b57cec5SDimitry Andric     CloseHandle(h);
2400b57cec5SDimitry Andric     return NULL;
2410b57cec5SDimitry Andric   }
2420b57cec5SDimitry Andric #else
2430b57cec5SDimitry Andric   /* Worst case no locking applied.  */
2440b57cec5SDimitry Andric   PROF_WARN("Concurrent file access is not supported : %s\n",
2450b57cec5SDimitry Andric             "lack file locking");
2460b57cec5SDimitry Andric   fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
2470b57cec5SDimitry Andric   if (fd < 0)
2480b57cec5SDimitry Andric     return NULL;
2490b57cec5SDimitry Andric   f = fdopen(fd, "r+b");
2500b57cec5SDimitry Andric #endif
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   return f;
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric 
lprofGetPathPrefix(int * PrefixStrip,size_t * PrefixLen)2550b57cec5SDimitry Andric COMPILER_RT_VISIBILITY const char *lprofGetPathPrefix(int *PrefixStrip,
2560b57cec5SDimitry Andric                                                       size_t *PrefixLen) {
2570b57cec5SDimitry Andric   const char *Prefix = getenv("GCOV_PREFIX");
2580b57cec5SDimitry Andric   const char *PrefixStripStr = getenv("GCOV_PREFIX_STRIP");
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   *PrefixLen = 0;
2610b57cec5SDimitry Andric   *PrefixStrip = 0;
2620b57cec5SDimitry Andric   if (Prefix == NULL || Prefix[0] == '\0')
2630b57cec5SDimitry Andric     return NULL;
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   if (PrefixStripStr) {
2660b57cec5SDimitry Andric     *PrefixStrip = atoi(PrefixStripStr);
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric     /* Negative GCOV_PREFIX_STRIP values are ignored */
2690b57cec5SDimitry Andric     if (*PrefixStrip < 0)
2700b57cec5SDimitry Andric       *PrefixStrip = 0;
2710b57cec5SDimitry Andric   } else {
2720b57cec5SDimitry Andric     *PrefixStrip = 0;
2730b57cec5SDimitry Andric   }
2740b57cec5SDimitry Andric   *PrefixLen = strlen(Prefix);
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   return Prefix;
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric COMPILER_RT_VISIBILITY void
lprofApplyPathPrefix(char * Dest,const char * PathStr,const char * Prefix,size_t PrefixLen,int PrefixStrip)2800b57cec5SDimitry Andric lprofApplyPathPrefix(char *Dest, const char *PathStr, const char *Prefix,
2810b57cec5SDimitry Andric                      size_t PrefixLen, int PrefixStrip) {
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric   const char *Ptr;
2840b57cec5SDimitry Andric   int Level;
2850b57cec5SDimitry Andric   const char *StrippedPathStr = PathStr;
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   for (Level = 0, Ptr = PathStr + 1; Level < PrefixStrip; ++Ptr) {
2880b57cec5SDimitry Andric     if (*Ptr == '\0')
2890b57cec5SDimitry Andric       break;
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric     if (!IS_DIR_SEPARATOR(*Ptr))
2920b57cec5SDimitry Andric       continue;
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric     StrippedPathStr = Ptr;
2950b57cec5SDimitry Andric     ++Level;
2960b57cec5SDimitry Andric   }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric   memcpy(Dest, Prefix, PrefixLen);
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric   if (!IS_DIR_SEPARATOR(Prefix[PrefixLen - 1]))
3010b57cec5SDimitry Andric     Dest[PrefixLen++] = DIR_SEPARATOR;
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   memcpy(Dest + PrefixLen, StrippedPathStr, strlen(StrippedPathStr) + 1);
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric COMPILER_RT_VISIBILITY const char *
lprofFindFirstDirSeparator(const char * Path)3070b57cec5SDimitry Andric lprofFindFirstDirSeparator(const char *Path) {
3080b57cec5SDimitry Andric   const char *Sep = strchr(Path, DIR_SEPARATOR);
3090b57cec5SDimitry Andric #if defined(DIR_SEPARATOR_2)
3100b57cec5SDimitry Andric   const char *Sep2 = strchr(Path, DIR_SEPARATOR_2);
3110b57cec5SDimitry Andric   if (Sep2 && (!Sep || Sep2 < Sep))
3120b57cec5SDimitry Andric     Sep = Sep2;
3130b57cec5SDimitry Andric #endif
3140b57cec5SDimitry Andric   return Sep;
3150b57cec5SDimitry Andric }
3160b57cec5SDimitry Andric 
lprofFindLastDirSeparator(const char * Path)3170b57cec5SDimitry Andric COMPILER_RT_VISIBILITY const char *lprofFindLastDirSeparator(const char *Path) {
3180b57cec5SDimitry Andric   const char *Sep = strrchr(Path, DIR_SEPARATOR);
3190b57cec5SDimitry Andric #if defined(DIR_SEPARATOR_2)
3200b57cec5SDimitry Andric   const char *Sep2 = strrchr(Path, DIR_SEPARATOR_2);
3210b57cec5SDimitry Andric   if (Sep2 && (!Sep || Sep2 > Sep))
3220b57cec5SDimitry Andric     Sep = Sep2;
3230b57cec5SDimitry Andric #endif
3240b57cec5SDimitry Andric   return Sep;
3250b57cec5SDimitry Andric }
3260b57cec5SDimitry Andric 
lprofSuspendSigKill(void)327*81ad6265SDimitry Andric COMPILER_RT_VISIBILITY int lprofSuspendSigKill(void) {
3280b57cec5SDimitry Andric #if defined(__linux__)
3290b57cec5SDimitry Andric   int PDeachSig = 0;
3300b57cec5SDimitry Andric   /* Temporarily suspend getting SIGKILL upon exit of the parent process. */
3310b57cec5SDimitry Andric   if (prctl(PR_GET_PDEATHSIG, &PDeachSig) == 0 && PDeachSig == SIGKILL)
3320b57cec5SDimitry Andric     prctl(PR_SET_PDEATHSIG, 0);
3330b57cec5SDimitry Andric   return (PDeachSig == SIGKILL);
334349cc55cSDimitry Andric #elif defined(__FreeBSD__)
335349cc55cSDimitry Andric   int PDeachSig = 0, PDisableSig = 0;
336349cc55cSDimitry Andric   if (procctl(P_PID, 0, PROC_PDEATHSIG_STATUS, &PDeachSig) == 0 &&
337349cc55cSDimitry Andric       PDeachSig == SIGKILL)
338349cc55cSDimitry Andric     procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &PDisableSig);
339349cc55cSDimitry Andric   return (PDeachSig == SIGKILL);
3400b57cec5SDimitry Andric #else
3410b57cec5SDimitry Andric   return 0;
3420b57cec5SDimitry Andric #endif
3430b57cec5SDimitry Andric }
3440b57cec5SDimitry Andric 
lprofRestoreSigKill(void)345*81ad6265SDimitry Andric COMPILER_RT_VISIBILITY void lprofRestoreSigKill(void) {
3460b57cec5SDimitry Andric #if defined(__linux__)
3470b57cec5SDimitry Andric   prctl(PR_SET_PDEATHSIG, SIGKILL);
348349cc55cSDimitry Andric #elif defined(__FreeBSD__)
349349cc55cSDimitry Andric   int PEnableSig = SIGKILL;
350349cc55cSDimitry Andric   procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &PEnableSig);
3510b57cec5SDimitry Andric #endif
3520b57cec5SDimitry Andric }
353fe6060f1SDimitry Andric 
lprofReleaseMemoryPagesToOS(uintptr_t Begin,uintptr_t End)354fe6060f1SDimitry Andric COMPILER_RT_VISIBILITY int lprofReleaseMemoryPagesToOS(uintptr_t Begin,
355fe6060f1SDimitry Andric                                                        uintptr_t End) {
356349cc55cSDimitry Andric #if defined(__ve__)
357349cc55cSDimitry Andric   // VE doesn't support madvise.
358349cc55cSDimitry Andric   return 0;
359349cc55cSDimitry Andric #else
360fe6060f1SDimitry Andric   size_t PageSize = getpagesize();
361fe6060f1SDimitry Andric   uintptr_t BeginAligned = lprofRoundUpTo((uintptr_t)Begin, PageSize);
362fe6060f1SDimitry Andric   uintptr_t EndAligned = lprofRoundDownTo((uintptr_t)End, PageSize);
363fe6060f1SDimitry Andric   if (BeginAligned < EndAligned) {
364fe6060f1SDimitry Andric #if defined(__Fuchsia__)
365fe6060f1SDimitry Andric     return _zx_vmar_op_range(_zx_vmar_root_self(), ZX_VMAR_OP_DECOMMIT,
366fe6060f1SDimitry Andric                              (zx_vaddr_t)BeginAligned,
367fe6060f1SDimitry Andric                              EndAligned - BeginAligned, NULL, 0);
368fe6060f1SDimitry Andric #else
369fe6060f1SDimitry Andric     return madvise((void *)BeginAligned, EndAligned - BeginAligned,
370fe6060f1SDimitry Andric                    MADV_DONTNEED);
371fe6060f1SDimitry Andric #endif
372fe6060f1SDimitry Andric   }
373fe6060f1SDimitry Andric   return 0;
374349cc55cSDimitry Andric #endif
375fe6060f1SDimitry Andric }
376