Skip to content

Commit a799298

Browse files
committed
[BOLT][Instrumentation] Keep profile open in WatchProcess
When a binary is instrumented with --instrumentation-sleep-time and instrumentation-wait-forks options and lauched, the profile is periodically written until all the forks die. The problem is that we cannot wait for the whole process tree, and we have no way to tell when it's safe to read the profile. Hovewer, if we keep profile open throughout the life of the process tree, we can use fuser to determine when writing is finished. Reviewed By: rafauler Differential Revision: https://reviews.llvm.org/D154436
1 parent 66c623b commit a799298

File tree

2 files changed

+25
-9
lines changed

2 files changed

+25
-9
lines changed

bolt/runtime/common.h

+10
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,16 @@ uint64_t __lseek(uint64_t fd, uint64_t pos, uint64_t whence) {
458458
return ret;
459459
}
460460

461+
int __ftruncate(uint64_t fd, uint64_t length) {
462+
int ret;
463+
__asm__ __volatile__("movq $77, %%rax\n"
464+
"syscall\n"
465+
: "=a"(ret)
466+
: "D"(fd), "S"(length)
467+
: "cc", "rcx", "r11", "memory");
468+
return ret;
469+
}
470+
461471
int __close(uint64_t fd) {
462472
uint64_t ret;
463473
__asm__ __volatile__("movq $3, %%rax\n"

bolt/runtime/instr.cpp

+15-9
Original file line numberDiff line numberDiff line change
@@ -1515,20 +1515,22 @@ extern "C" void __bolt_instr_clear_counters() {
15151515
/// on demand.
15161516
///
15171517
extern "C" void __attribute((force_align_arg_pointer))
1518-
__bolt_instr_data_dump() {
1518+
__bolt_instr_data_dump(int FD) {
15191519
// Already dumping
15201520
if (!GlobalWriteProfileMutex->acquire())
15211521
return;
15221522

1523+
int ret = __lseek(FD, 0, SEEK_SET);
1524+
assert(ret == 0, "Failed to lseek!");
1525+
ret = __ftruncate(FD, 0);
1526+
assert(ret == 0, "Failed to ftruncate!");
15231527
BumpPtrAllocator HashAlloc;
15241528
HashAlloc.setMaxSize(0x6400000);
15251529
ProfileWriterContext Ctx = readDescriptions();
15261530
Ctx.CallFlowTable = new (HashAlloc, 0) CallFlowHashTable(HashAlloc);
15271531

15281532
DEBUG(printStats(Ctx));
15291533

1530-
int FD = openProfile();
1531-
15321534
BumpPtrAllocator Alloc;
15331535
Alloc.setMaxSize(0x6400000);
15341536
const uint8_t *FuncDesc = Ctx.FuncDescriptions;
@@ -1544,7 +1546,6 @@ __bolt_instr_data_dump() {
15441546
Ctx.CallFlowTable->forEachElement(visitCallFlowEntry, FD, &Ctx);
15451547

15461548
__fsync(FD);
1547-
__close(FD);
15481549
__munmap(Ctx.MMapPtr, Ctx.MMapSize);
15491550
__close(Ctx.FileDesc);
15501551
HashAlloc.destroy();
@@ -1557,6 +1558,7 @@ __bolt_instr_data_dump() {
15571558
void watchProcess() {
15581559
timespec ts, rem;
15591560
uint64_t Ellapsed = 0ull;
1561+
int FD = openProfile();
15601562
uint64_t ppid;
15611563
if (__bolt_instr_wait_forks) {
15621564
// Store parent pgid
@@ -1568,7 +1570,7 @@ void watchProcess() {
15681570
ppid = __getppid();
15691571
if (ppid == 1) {
15701572
// Parent already dead
1571-
__bolt_instr_data_dump();
1573+
__bolt_instr_data_dump(FD);
15721574
goto out;
15731575
}
15741576
}
@@ -1581,21 +1583,22 @@ void watchProcess() {
15811583
// so no need for us to keep dumping.
15821584
if (__kill(ppid, 0) < 0) {
15831585
if (__bolt_instr_no_counters_clear)
1584-
__bolt_instr_data_dump();
1586+
__bolt_instr_data_dump(FD);
15851587
break;
15861588
}
15871589

15881590
if (++Ellapsed < __bolt_instr_sleep_time)
15891591
continue;
15901592

15911593
Ellapsed = 0;
1592-
__bolt_instr_data_dump();
1594+
__bolt_instr_data_dump(FD);
15931595
if (__bolt_instr_no_counters_clear == false)
15941596
__bolt_instr_clear_counters();
15951597
}
15961598

15971599
out:;
15981600
DEBUG(report("My parent process is dead, bye!\n"));
1601+
__close(FD);
15991602
__exit(0);
16001603
}
16011604

@@ -1691,8 +1694,11 @@ extern "C" __attribute((naked)) void __bolt_instr_start()
16911694
/// This is hooking into ELF's DT_FINI
16921695
extern "C" void __bolt_instr_fini() {
16931696
__bolt_fini_trampoline();
1694-
if (__bolt_instr_sleep_time == 0)
1695-
__bolt_instr_data_dump();
1697+
if (__bolt_instr_sleep_time == 0) {
1698+
int FD = openProfile();
1699+
__bolt_instr_data_dump(FD);
1700+
__close(FD);
1701+
}
16961702
DEBUG(report("Finished.\n"));
16971703
}
16981704

0 commit comments

Comments
 (0)