Skip to content

Commit 1b05245

Browse files
committed
[Profile] Support __llvm_profile_set_file_object in continuous mode.
Replace D107203, because __llvm_profile_set_file_object is usually used when the process doesn't have permission to open/create file. That patch trying to copy from old profile to new profile contradicts with the usage. Differential Revision: https://reviews.llvm.org/D108242
1 parent 8f859cc commit 1b05245

File tree

3 files changed

+220
-124
lines changed

3 files changed

+220
-124
lines changed

compiler-rt/lib/profile/InstrProfiling.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ int __llvm_orderfile_dump(void);
194194
void __llvm_profile_set_filename(const char *Name);
195195

196196
/*!
197-
* \brief Set the FILE object for writing instrumentation data.
197+
* \brief Set the FILE object for writing instrumentation data. Return 0 if set
198+
* successfully or return 1 if failed.
198199
*
199200
* Sets the FILE object to be used for subsequent calls to
200201
* \a __llvm_profile_write_file(). The profile file name set by environment
@@ -213,13 +214,12 @@ void __llvm_profile_set_filename(const char *Name);
213214
* instrumented image/DSO). This API only modifies the file object within the
214215
* copy of the runtime available to the calling image.
215216
*
216-
* Warning: This is a no-op if continuous mode (\ref
217-
* __llvm_profile_is_continuous_mode_enabled) is on. The reason for this is
218-
* that in continuous mode, profile counters are mmap()'d to the profile at
219-
* program initialization time. Support for transferring the mmap'd profile
220-
* counts to a new file has not been implemented.
217+
* Warning: This is a no-op if EnableMerge is 0 in continuous mode (\ref
218+
* __llvm_profile_is_continuous_mode_enabled), because disable merging requires
219+
* copying the old profile file to new profile file and this function is usually
220+
* used when the proess doesn't have permission to open file.
221221
*/
222-
void __llvm_profile_set_file_object(FILE *File, int EnableMerge);
222+
int __llvm_profile_set_file_object(FILE *File, int EnableMerge);
223223

224224
/*! \brief Register to write instrumentation data to file at exit. */
225225
int __llvm_profile_register_write_file_atexit(void);

compiler-rt/lib/profile/InstrProfilingFile.c

Lines changed: 140 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,71 @@ static lprofFilename lprofCurFilename = {0, 0, 0, {0}, NULL,
9292
{0}, 0, 0, 0, PNS_unknown};
9393

9494
static int ProfileMergeRequested = 0;
95+
static int getProfileFileSizeForMerging(FILE *ProfileFile,
96+
uint64_t *ProfileFileSize);
9597

9698
#if defined(__APPLE__)
9799
static const int ContinuousModeSupported = 1;
98100
static const int UseBiasVar = 0;
99101
static const char *FileOpenMode = "a+b";
100-
static intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_VAR;
101102
static void *BiasAddr = NULL;
102103
static void *BiasDefaultAddr = NULL;
103-
static int MmapFlags = MAP_FIXED | MAP_SHARED;
104+
static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
105+
/* Get the sizes of various profile data sections. Taken from
106+
* __llvm_profile_get_size_for_buffer(). */
107+
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
108+
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
109+
const uint64_t *CountersBegin = __llvm_profile_begin_counters();
110+
const uint64_t *CountersEnd = __llvm_profile_end_counters();
111+
const char *NamesBegin = __llvm_profile_begin_names();
112+
const char *NamesEnd = __llvm_profile_end_names();
113+
const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
114+
uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
115+
uint64_t CountersSize = CountersEnd - CountersBegin;
116+
117+
/* Check that the counter and data sections in this image are
118+
* page-aligned. */
119+
unsigned PageSize = getpagesize();
120+
if ((intptr_t)CountersBegin % PageSize != 0) {
121+
PROF_ERR("Counters section not page-aligned (start = %p, pagesz = %u).\n",
122+
CountersBegin, PageSize);
123+
return 1;
124+
}
125+
if ((intptr_t)DataBegin % PageSize != 0) {
126+
PROF_ERR("Data section not page-aligned (start = %p, pagesz = %u).\n",
127+
DataBegin, PageSize);
128+
return 1;
129+
}
130+
int Fileno = fileno(File);
131+
/* Determine how much padding is needed before/after the counters and
132+
* after the names. */
133+
uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
134+
PaddingBytesAfterNames;
135+
__llvm_profile_get_padding_sizes_for_counters(
136+
DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
137+
&PaddingBytesAfterCounters, &PaddingBytesAfterNames);
138+
139+
uint64_t PageAlignedCountersLength =
140+
(CountersSize * sizeof(uint64_t)) + PaddingBytesAfterCounters;
141+
uint64_t FileOffsetToCounters =
142+
CurrentFileOffset + sizeof(__llvm_profile_header) +
143+
(DataSize * sizeof(__llvm_profile_data)) + PaddingBytesBeforeCounters;
144+
uint64_t *CounterMmap = (uint64_t *)mmap(
145+
(void *)CountersBegin, PageAlignedCountersLength, PROT_READ | PROT_WRITE,
146+
MAP_FIXED | MAP_SHARED, Fileno, FileOffsetToCounters);
147+
if (CounterMmap != CountersBegin) {
148+
PROF_ERR(
149+
"Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
150+
" - CountersBegin: %p\n"
151+
" - PageAlignedCountersLength: %" PRIu64 "\n"
152+
" - Fileno: %d\n"
153+
" - FileOffsetToCounters: %" PRIu64 "\n",
154+
strerror(errno), CountersBegin, PageAlignedCountersLength, Fileno,
155+
FileOffsetToCounters);
156+
return 1;
157+
}
158+
return 0;
159+
}
104160
#elif defined(__ELF__) || defined(_WIN32)
105161

106162
#define INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR \
@@ -134,15 +190,46 @@ static const char *FileOpenMode = "w+b";
134190
* used and runtime provides a weak alias so we can check if it's defined. */
135191
static void *BiasAddr = &INSTR_PROF_PROFILE_COUNTER_BIAS_VAR;
136192
static void *BiasDefaultAddr = &INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR;
137-
static int MmapFlags = MAP_SHARED;
193+
static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
194+
/* Get the sizes of various profile data sections. Taken from
195+
* __llvm_profile_get_size_for_buffer(). */
196+
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
197+
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
198+
const uint64_t *CountersBegin = __llvm_profile_begin_counters();
199+
const uint64_t *CountersEnd = __llvm_profile_end_counters();
200+
uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
201+
/* Get the file size. */
202+
uint64_t FileSize = 0;
203+
if (getProfileFileSizeForMerging(File, &FileSize))
204+
return 1;
205+
206+
/* Map the profile. */
207+
char *Profile = (char *)mmap(NULL, FileSize, PROT_READ | PROT_WRITE,
208+
MAP_SHARED, fileno(File), 0);
209+
if (Profile == MAP_FAILED) {
210+
PROF_ERR("Unable to mmap profile: %s\n", strerror(errno));
211+
return 1;
212+
}
213+
const uint64_t CountersOffsetInBiasMode =
214+
sizeof(__llvm_profile_header) + __llvm_write_binary_ids(NULL) +
215+
(DataSize * sizeof(__llvm_profile_data));
216+
/* Update the profile fields based on the current mapping. */
217+
INSTR_PROF_PROFILE_COUNTER_BIAS_VAR =
218+
(intptr_t)Profile - (uintptr_t)CountersBegin + CountersOffsetInBiasMode;
219+
220+
/* Return the memory allocated for counters to OS. */
221+
lprofReleaseMemoryPagesToOS((uintptr_t)CountersBegin, (uintptr_t)CountersEnd);
222+
return 0;
223+
}
138224
#else
139225
static const int ContinuousModeSupported = 0;
140226
static const int UseBiasVar = 0;
141227
static const char *FileOpenMode = "a+b";
142-
static intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_VAR;
143228
static void *BiasAddr = NULL;
144229
static void *BiasDefaultAddr = NULL;
145-
static int MmapFlags = MAP_SHARED;
230+
static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
231+
return 0;
232+
}
146233
#endif
147234

148235
static int isProfileMergeRequested() { return ProfileMergeRequested; }
@@ -154,18 +241,6 @@ static FILE *ProfileFile = NULL;
154241
static FILE *getProfileFile() { return ProfileFile; }
155242
static void setProfileFile(FILE *File) { ProfileFile = File; }
156243

157-
COMPILER_RT_VISIBILITY void __llvm_profile_set_file_object(FILE *File,
158-
int EnableMerge) {
159-
if (__llvm_profile_is_continuous_mode_enabled()) {
160-
PROF_WARN("__llvm_profile_set_file_object(fd=%d) not supported, because "
161-
"continuous sync mode (%%c) is enabled",
162-
fileno(File));
163-
return;
164-
}
165-
setProfileFile(File);
166-
setProfileMergeRequested(EnableMerge);
167-
}
168-
169244
static int getCurFilenameLength();
170245
static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf);
171246
static unsigned doMerging() {
@@ -502,16 +577,9 @@ static void initializeProfileForContinuousMode(void) {
502577
return;
503578
}
504579

505-
/* Get the sizes of various profile data sections. Taken from
506-
* __llvm_profile_get_size_for_buffer(). */
507-
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
508-
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
580+
/* Get the sizes of counter section. */
509581
const uint64_t *CountersBegin = __llvm_profile_begin_counters();
510582
const uint64_t *CountersEnd = __llvm_profile_end_counters();
511-
const char *NamesBegin = __llvm_profile_begin_names();
512-
const char *NamesEnd = __llvm_profile_end_names();
513-
const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
514-
uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
515583
uint64_t CountersSize = CountersEnd - CountersBegin;
516584

517585
int Length = getCurFilenameLength();
@@ -577,75 +645,8 @@ static void initializeProfileForContinuousMode(void) {
577645

578646
/* mmap() the profile counters so long as there is at least one counter.
579647
* If there aren't any counters, mmap() would fail with EINVAL. */
580-
if (CountersSize > 0) {
581-
int Fileno = fileno(File);
582-
if (UseBiasVar) {
583-
/* Get the file size. */
584-
uint64_t FileSize = ftell(File);
585-
586-
/* Map the profile. */
587-
char *Profile = (char *)mmap(NULL, FileSize, PROT_READ | PROT_WRITE,
588-
MmapFlags, Fileno, 0);
589-
if (Profile == MAP_FAILED) {
590-
PROF_ERR("Unable to mmap profile: %s\n", strerror(errno));
591-
return;
592-
}
593-
const uint64_t CountersOffsetInBiasMode =
594-
sizeof(__llvm_profile_header) + __llvm_write_binary_ids(NULL) +
595-
(DataSize * sizeof(__llvm_profile_data));
596-
/* Update the profile fields based on the current mapping. */
597-
INSTR_PROF_PROFILE_COUNTER_BIAS_VAR = (intptr_t)Profile -
598-
(uintptr_t)CountersBegin +
599-
CountersOffsetInBiasMode;
600-
601-
/* Return the memory allocated for counters to OS. */
602-
lprofReleaseMemoryPagesToOS((uintptr_t)CountersBegin,
603-
(uintptr_t)CountersEnd);
604-
} else {
605-
/* Check that the counter and data sections in this image are
606-
* page-aligned. */
607-
unsigned PageSize = getpagesize();
608-
if ((intptr_t)CountersBegin % PageSize != 0) {
609-
PROF_ERR(
610-
"Counters section not page-aligned (start = %p, pagesz = %u).\n",
611-
CountersBegin, PageSize);
612-
return;
613-
}
614-
if ((intptr_t)DataBegin % PageSize != 0) {
615-
PROF_ERR("Data section not page-aligned (start = %p, pagesz = %u).\n",
616-
DataBegin, PageSize);
617-
return;
618-
}
619-
/* Determine how much padding is needed before/after the counters and
620-
* after the names. */
621-
uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
622-
PaddingBytesAfterNames;
623-
__llvm_profile_get_padding_sizes_for_counters(
624-
DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
625-
&PaddingBytesAfterCounters, &PaddingBytesAfterNames);
626-
627-
uint64_t PageAlignedCountersLength =
628-
(CountersSize * sizeof(uint64_t)) + PaddingBytesAfterCounters;
629-
uint64_t FileOffsetToCounters =
630-
CurrentFileOffset + sizeof(__llvm_profile_header) +
631-
(DataSize * sizeof(__llvm_profile_data)) + PaddingBytesBeforeCounters;
632-
633-
uint64_t *CounterMmap =
634-
(uint64_t *)mmap((void *)CountersBegin, PageAlignedCountersLength,
635-
PROT_READ | PROT_WRITE, MmapFlags,
636-
Fileno, FileOffsetToCounters);
637-
if (CounterMmap != CountersBegin) {
638-
PROF_ERR(
639-
"Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
640-
" - CountersBegin: %p\n"
641-
" - PageAlignedCountersLength: %" PRIu64 "\n"
642-
" - Fileno: %d\n"
643-
" - FileOffsetToCounters: %" PRIu64 "\n",
644-
strerror(errno), CountersBegin, PageAlignedCountersLength, Fileno,
645-
FileOffsetToCounters);
646-
}
647-
}
648-
}
648+
if (CountersSize > 0)
649+
mmapForContinuousMode(CurrentFileOffset, File);
649650

650651
if (doMerging()) {
651652
lprofUnlockFileHandle(File);
@@ -1143,4 +1144,49 @@ int __llvm_profile_register_write_file_atexit(void) {
11431144
return atexit(writeFileWithoutReturn);
11441145
}
11451146

1147+
COMPILER_RT_VISIBILITY int __llvm_profile_set_file_object(FILE *File,
1148+
int EnableMerge) {
1149+
if (__llvm_profile_is_continuous_mode_enabled()) {
1150+
if (!EnableMerge) {
1151+
PROF_WARN("__llvm_profile_set_file_object(fd=%d) not supported in "
1152+
"continuous sync mode when merging is disabled\n",
1153+
fileno(File));
1154+
return 1;
1155+
}
1156+
lprofLockFileHandle(File);
1157+
uint64_t ProfileFileSize = 0;
1158+
if (getProfileFileSizeForMerging(File, &ProfileFileSize) == -1) {
1159+
lprofUnlockFileHandle(File);
1160+
return 1;
1161+
}
1162+
if (ProfileFileSize == 0) {
1163+
FreeHook = &free;
1164+
setupIOBuffer();
1165+
ProfDataWriter fileWriter;
1166+
initFileWriter(&fileWriter, File);
1167+
if (lprofWriteData(&fileWriter, 0, 0)) {
1168+
lprofUnlockFileHandle(File);
1169+
PROF_ERR("Failed to write file \"%d\": %s\n", fileno(File),
1170+
strerror(errno));
1171+
return 1;
1172+
}
1173+
} else {
1174+
/* The merged profile has a non-zero length. Check that it is compatible
1175+
* with the data in this process. */
1176+
char *ProfileBuffer;
1177+
if (mmapProfileForMerging(File, ProfileFileSize, &ProfileBuffer) == -1) {
1178+
lprofUnlockFileHandle(File);
1179+
return 1;
1180+
}
1181+
(void)munmap(ProfileBuffer, ProfileFileSize);
1182+
}
1183+
mmapForContinuousMode(0, File);
1184+
lprofUnlockFileHandle(File);
1185+
} else {
1186+
setProfileFile(File);
1187+
setProfileMergeRequested(EnableMerge);
1188+
}
1189+
return 0;
1190+
}
1191+
11461192
#endif

0 commit comments

Comments
 (0)