mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-28 10:46:11 +00:00
[profile] in-process mergeing support (part-2)
(Part-1 merging API is in profile runtime) This patch implements a portable file opening API with exclusive access for the process. In-process profile merge requires profile file update to be atomic/fully sychronized. llvm-svn: 271864
This commit is contained in:
parent
04a89fd826
commit
5cd1f94d4f
@ -22,6 +22,22 @@ int main() {
|
||||
}
|
||||
" COMPILER_RT_TARGET_HAS_ATOMICS)
|
||||
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#if defined(__linux__)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
int fd;
|
||||
int main() {
|
||||
struct flock s_flock;
|
||||
|
||||
s_flock.l_type = F_WRLCK;
|
||||
fcntl(fd, F_SETLKW, &s_flock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
" COMPILER_RT_TARGET_HAS_FCNTL_LCK)
|
||||
|
||||
add_custom_target(profile)
|
||||
|
||||
set(PROFILE_SOURCES
|
||||
@ -55,6 +71,12 @@ if(COMPILER_RT_TARGET_HAS_ATOMICS)
|
||||
-DCOMPILER_RT_HAS_ATOMICS=1)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_TARGET_HAS_FCNTL_LCK)
|
||||
set(EXTRA_FLAGS
|
||||
${EXTRA_FLAGS}
|
||||
-DCOMPILER_RT_HAS_FCNTL_LCK=1)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
add_compiler_rt_runtime(clang_rt.profile
|
||||
STATIC
|
||||
|
@ -12,9 +12,15 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#if defined(__linux__)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#ifdef COMPILER_RT_HAS_UNAME
|
||||
@ -35,7 +41,7 @@ void __llvm_profile_recursive_mkdir(char *path) {
|
||||
#ifdef _WIN32
|
||||
_mkdir(path);
|
||||
#else
|
||||
mkdir(path, 0755); /* Some of these will fail, ignore it. */
|
||||
mkdir(path, 0755); /* Some of these will fail, ignore it. */
|
||||
#endif
|
||||
path[i] = save;
|
||||
}
|
||||
@ -70,4 +76,51 @@ int lprofGetHostName(char *Name, int Len) {
|
||||
}
|
||||
#endif
|
||||
|
||||
FILE *lprofOpenFileEx(const char *ProfileName) {
|
||||
FILE *f;
|
||||
int fd;
|
||||
#ifdef COMPILER_RT_HAS_FCNTL_LCK
|
||||
struct flock s_flock;
|
||||
|
||||
s_flock.l_whence = SEEK_SET;
|
||||
s_flock.l_start = 0;
|
||||
s_flock.l_len = 0; /* Until EOF. */
|
||||
s_flock.l_pid = getpid();
|
||||
|
||||
s_flock.l_type = F_WRLCK;
|
||||
fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
|
||||
while (fcntl(fd, F_SETLKW, &s_flock) && errno == EINTR)
|
||||
continue;
|
||||
|
||||
f = fdopen(fd, "r+b");
|
||||
#elif defined(_WIN32)
|
||||
HANDLE h = CreateFile(ProfileName, GENERIC_READ | GENERIC_WRITE, 0, 0,
|
||||
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
fd = _open_osfhandle((intptr_t)h, 0);
|
||||
if (fd == -1) {
|
||||
CloseHandle(h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
f = _fdopen(fd, "r+b");
|
||||
if (f == 0) {
|
||||
CloseHandle(h);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
/* Worst case no locking applied. */
|
||||
PROF_WARN("Concurrent file access is not supported : %s\n", "lack file locking");
|
||||
fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
f = fdopen(fd, "r+b");
|
||||
#endif
|
||||
|
||||
return f;
|
||||
}
|
||||
|
@ -11,10 +11,15 @@
|
||||
#define PROFILE_INSTRPROFILINGUTIL_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*! \brief Create a directory tree. */
|
||||
void __llvm_profile_recursive_mkdir(char *Pathname);
|
||||
|
||||
/*! Open file \c Filename for read+write with write
|
||||
* lock for exclusive access. The caller will block
|
||||
* if the lock is already held by another process. */
|
||||
FILE *lprofOpenFileEx(const char *Filename);
|
||||
/* PS4 doesn't have getenv. Define a shim. */
|
||||
#if __ORBIS__
|
||||
static inline char *getenv(const char *name) { return NULL; }
|
||||
|
59
compiler-rt/test/profile/Inputs/instrprof-file_ex.c
Normal file
59
compiler-rt/test/profile/Inputs/instrprof-file_ex.c
Normal file
@ -0,0 +1,59 @@
|
||||
/* This is a test case where the parent process forks 10
|
||||
* children which contend to write to the same file. With
|
||||
* file locking support, the data from each child should not
|
||||
* be lost.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
extern FILE *lprofOpenFileEx(const char *);
|
||||
int main(int argc, char *argv[]) {
|
||||
pid_t tid;
|
||||
FILE *F;
|
||||
const char *FN;
|
||||
int child[10];
|
||||
int c;
|
||||
int i;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Requires one argument \n");
|
||||
exit(1);
|
||||
}
|
||||
FN = argv[1];
|
||||
truncate(FN, 0);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
c = fork();
|
||||
// in child:
|
||||
if (c == 0) {
|
||||
FILE *F = lprofOpenFileEx(FN);
|
||||
if (!F) {
|
||||
fprintf(stderr, "Can not open file %s from child\n", FN);
|
||||
exit(1);
|
||||
}
|
||||
fseek(F, 0, SEEK_END);
|
||||
fprintf(F, "Dump from Child %d\n", i + 11);
|
||||
fclose(F);
|
||||
exit(0);
|
||||
} else {
|
||||
child[i] = c;
|
||||
}
|
||||
}
|
||||
|
||||
// In parent
|
||||
for (i = 0; i < 10; i++) {
|
||||
int child_status;
|
||||
if ((tid = waitpid(child[i], &child_status, 0) == -1))
|
||||
break;
|
||||
}
|
||||
F = lprofOpenFileEx(FN);
|
||||
if (!F) {
|
||||
fprintf(stderr, "Can not open file %s from parent\n", FN);
|
||||
exit(1);
|
||||
}
|
||||
fseek(F, 0, SEEK_END);
|
||||
fprintf(F, "Dump from parent %d\n", i + 11);
|
||||
return 0;
|
||||
}
|
16
compiler-rt/test/profile/Linux/instrprof-file_ex.test
Normal file
16
compiler-rt/test/profile/Linux/instrprof-file_ex.test
Normal file
@ -0,0 +1,16 @@
|
||||
RUN: mkdir -p %t.d
|
||||
RUN: %clang_profgen -fprofile-instr-generate %S/../Inputs/instrprof-file_ex.c -o %t
|
||||
RUN: %run %t %t.d/run.dump
|
||||
RUN: sort %t.d/run.dump | FileCheck %s
|
||||
|
||||
CHECK: Dump from Child 11
|
||||
CHECK-NEXT: Dump from Child 12
|
||||
CHECK-NEXT: Dump from Child 13
|
||||
CHECK-NEXT: Dump from Child 14
|
||||
CHECK-NEXT: Dump from Child 15
|
||||
CHECK-NEXT: Dump from Child 16
|
||||
CHECK-NEXT: Dump from Child 17
|
||||
CHECK-NEXT: Dump from Child 18
|
||||
CHECK-NEXT: Dump from Child 19
|
||||
CHECK-NEXT: Dump from Child 20
|
||||
CHECK-NEXT: Dump from parent 21
|
Loading…
Reference in New Issue
Block a user