@@ -92,15 +92,71 @@ static lprofFilename lprofCurFilename = {0, 0, 0, {0}, NULL,
92
92
{0 }, 0 , 0 , 0 , PNS_unknown };
93
93
94
94
static int ProfileMergeRequested = 0 ;
95
+ static int getProfileFileSizeForMerging (FILE * ProfileFile ,
96
+ uint64_t * ProfileFileSize );
95
97
96
98
#if defined(__APPLE__ )
97
99
static const int ContinuousModeSupported = 1 ;
98
100
static const int UseBiasVar = 0 ;
99
101
static const char * FileOpenMode = "a+b" ;
100
- static intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_VAR ;
101
102
static void * BiasAddr = NULL ;
102
103
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
+ }
104
160
#elif defined(__ELF__ ) || defined(_WIN32 )
105
161
106
162
#define INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR \
@@ -134,15 +190,46 @@ static const char *FileOpenMode = "w+b";
134
190
* used and runtime provides a weak alias so we can check if it's defined. */
135
191
static void * BiasAddr = & INSTR_PROF_PROFILE_COUNTER_BIAS_VAR ;
136
192
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
+ }
138
224
#else
139
225
static const int ContinuousModeSupported = 0 ;
140
226
static const int UseBiasVar = 0 ;
141
227
static const char * FileOpenMode = "a+b" ;
142
- static intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_VAR ;
143
228
static void * BiasAddr = NULL ;
144
229
static void * BiasDefaultAddr = NULL ;
145
- static int MmapFlags = MAP_SHARED ;
230
+ static int mmapForContinuousMode (uint64_t CurrentFileOffset , FILE * File ) {
231
+ return 0 ;
232
+ }
146
233
#endif
147
234
148
235
static int isProfileMergeRequested () { return ProfileMergeRequested ; }
@@ -154,18 +241,6 @@ static FILE *ProfileFile = NULL;
154
241
static FILE * getProfileFile () { return ProfileFile ; }
155
242
static void setProfileFile (FILE * File ) { ProfileFile = File ; }
156
243
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
-
169
244
static int getCurFilenameLength ();
170
245
static const char * getCurFilename (char * FilenameBuf , int ForceUseBuf );
171
246
static unsigned doMerging () {
@@ -502,16 +577,9 @@ static void initializeProfileForContinuousMode(void) {
502
577
return ;
503
578
}
504
579
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. */
509
581
const uint64_t * CountersBegin = __llvm_profile_begin_counters ();
510
582
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 );
515
583
uint64_t CountersSize = CountersEnd - CountersBegin ;
516
584
517
585
int Length = getCurFilenameLength ();
@@ -577,75 +645,8 @@ static void initializeProfileForContinuousMode(void) {
577
645
578
646
/* mmap() the profile counters so long as there is at least one counter.
579
647
* 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 );
649
650
650
651
if (doMerging ()) {
651
652
lprofUnlockFileHandle (File );
@@ -1143,4 +1144,49 @@ int __llvm_profile_register_write_file_atexit(void) {
1143
1144
return atexit (writeFileWithoutReturn );
1144
1145
}
1145
1146
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
+
1146
1192
#endif
0 commit comments