Skip to content

Commit 1cb7e9c

Browse files
Yinan Liuchenshanpei
authored andcommitted
anolis: scripts: ftrace_init optimization about sorting
OpenAnolis Bug Tracker: 0000558 When the kernel starts, the initialization of fTrace takes up a portion of the time (approximately 6~8ms) to sort mcount addresses. We can save this time by moving mcount-sorting to compile time. Signed-off-by: Yinan Liu <[email protected]> Reviewed-by: Shanpei Chen <[email protected]>
1 parent 1fab5b3 commit 1cb7e9c

File tree

5 files changed

+119
-10
lines changed

5 files changed

+119
-10
lines changed

kernel/trace/ftrace.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5550,8 +5550,10 @@ static int ftrace_process_locs(struct module *mod,
55505550
if (!count)
55515551
return 0;
55525552

5553-
sort(start, count, sizeof(*start),
5554-
ftrace_cmp_ips, NULL);
5553+
if (mod) {
5554+
sort(start, count, sizeof(*start),
5555+
ftrace_cmp_ips, NULL);
5556+
}
55555557

55565558
start_pg = ftrace_allocate_pages(count);
55575559
if (!start_pg)

scripts/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
2222
hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
2323

2424
HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
25+
HOSTLDLIBS_sorttable = -lpthread
2526
HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
2627
HOSTLDLIBS_sign-file = -lcrypto
2728
HOSTLDLIBS_extract-cert = -lcrypto
2829

2930
ifdef CONFIG_UNWINDER_ORC
3031
HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/objtool/arch/$(SRCARCH)/include
3132
HOSTCFLAGS_sorttable.o += -DUNWINDER_ORC_ENABLED
32-
HOSTLDLIBS_sorttable = -lpthread
3333
endif
3434

3535
always := $(hostprogs-y) $(hostprogs-m)

scripts/link-vmlinux.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ fi
295295
info LD vmlinux
296296
vmlinux_link "${kallsymso}" vmlinux
297297

298+
info SYSMAP System.map
299+
mksysmap vmlinux System.map
300+
298301
if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then
299302
info SORTTAB vmlinux
300303
if ! sorttable vmlinux; then
@@ -303,9 +306,6 @@ if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then
303306
fi
304307
fi
305308

306-
info SYSMAP System.map
307-
mksysmap vmlinux System.map
308-
309309
# step a (see comment above)
310310
if [ -n "${CONFIG_KALLSYMS}" ]; then
311311
mksysmap ${kallsyms_vmlinux} .tmp_System.map

scripts/sorttable.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include <stdlib.h>
3131
#include <string.h>
3232
#include <unistd.h>
33+
#include <errno.h>
34+
#include <pthread.h>
3335

3436
#include <tools/be_byteshift.h>
3537
#include <tools/le_byteshift.h>

scripts/sorttable.h

Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121

2222
#undef extable_ent_size
2323
#undef compare_extable
24+
#undef get_mcount_loc
25+
#undef sort_mcount_loc
26+
#undef elf_mcount_loc
2427
#undef do_sort
2528
#undef Elf_Addr
2629
#undef Elf_Ehdr
@@ -43,6 +46,9 @@
4346
#ifdef SORTTABLE_64
4447
# define extable_ent_size 16
4548
# define compare_extable compare_extable_64
49+
# define get_mcount_loc get_mcount_loc_64
50+
# define sort_mcount_loc sort_mcount_loc_64
51+
# define elf_mcount_loc elf_mcount_loc_64
4652
# define do_sort do_sort_64
4753
# define Elf_Addr Elf64_Addr
4854
# define Elf_Ehdr Elf64_Ehdr
@@ -64,6 +70,9 @@
6470
#else
6571
# define extable_ent_size 8
6672
# define compare_extable compare_extable_32
73+
# define get_mcount_loc get_mcount_loc_32
74+
# define sort_mcount_loc sort_mcount_loc_32
75+
# define elf_mcount_loc elf_mcount_loc_32
6776
# define do_sort do_sort_32
6877
# define Elf_Addr Elf32_Addr
6978
# define Elf_Ehdr Elf32_Ehdr
@@ -86,8 +95,6 @@
8695

8796
#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
8897
/* ORC unwinder only support X86_64 */
89-
#include <errno.h>
90-
#include <pthread.h>
9198
#include <asm/orc_types.h>
9299

93100
#define ERRSTR_MAXSZ 256
@@ -193,6 +200,62 @@ static int compare_extable(const void *a, const void *b)
193200
return 1;
194201
return 0;
195202
}
203+
struct elf_mcount_loc {
204+
Elf_Ehdr *ehdr;
205+
Elf_Shdr *init_data_sec;
206+
uint_t start_mcount_loc;
207+
uint_t stop_mcount_loc;
208+
};
209+
210+
/* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */
211+
static void *sort_mcount_loc(void *arg)
212+
{
213+
struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg;
214+
uint_t offset = emloc->start_mcount_loc - _r(&(emloc->init_data_sec)->sh_addr)
215+
+ _r(&(emloc->init_data_sec)->sh_offset);
216+
uint_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc;
217+
unsigned char *start_loc = (void *)emloc->ehdr + offset;
218+
219+
qsort(start_loc, count/sizeof(uint_t), sizeof(uint_t), compare_extable);
220+
return NULL;
221+
}
222+
223+
/* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */
224+
static void get_mcount_loc(uint_t *_start, uint_t *_stop)
225+
{
226+
FILE *file_start, *file_stop;
227+
char start_buff[20];
228+
char stop_buff[20];
229+
int len = 0;
230+
231+
file_start = popen(" grep start_mcount System.map | awk '{print $1}' ", "r");
232+
if (!file_start) {
233+
fprintf(stderr, "get start_mcount_loc error!");
234+
return;
235+
}
236+
237+
file_stop = popen(" grep stop_mcount System.map | awk '{print $1}' ", "r");
238+
if (!file_stop) {
239+
fprintf(stderr, "get stop_mcount_loc error!");
240+
pclose(file_start);
241+
return;
242+
}
243+
244+
while (fgets(start_buff, sizeof(start_buff), file_start) != NULL) {
245+
len = strlen(start_buff);
246+
start_buff[len - 1] = '\0';
247+
}
248+
*_start = strtoul(start_buff, NULL, 16);
249+
250+
while (fgets(stop_buff, sizeof(stop_buff), file_stop) != NULL) {
251+
len = strlen(stop_buff);
252+
stop_buff[len - 1] = '\0';
253+
}
254+
*_stop = strtoul(stop_buff, NULL, 16);
255+
256+
pclose(file_start);
257+
pclose(file_stop);
258+
}
196259

197260
static int do_sort(Elf_Ehdr *ehdr,
198261
char const *const fname,
@@ -219,6 +282,10 @@ static int do_sort(Elf_Ehdr *ehdr,
219282
int idx;
220283
unsigned int shnum;
221284
unsigned int shstrndx;
285+
struct elf_mcount_loc mstruct;
286+
uint_t _start_mcount_loc = 0;
287+
uint_t _stop_mcount_loc = 0;
288+
pthread_t mcount_sort_thread;
222289
#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
223290
unsigned int orc_ip_size = 0;
224291
unsigned int orc_size = 0;
@@ -255,6 +322,14 @@ static int do_sort(Elf_Ehdr *ehdr,
255322
symtab_shndx = (Elf32_Word *)((const char *)ehdr +
256323
_r(&s->sh_offset));
257324

325+
/* locate the .init.data section in vmlinux */
326+
if (!strcmp(secstrings + idx, ".init.data")) {
327+
get_mcount_loc(&_start_mcount_loc, &_stop_mcount_loc);
328+
mstruct.ehdr = ehdr;
329+
mstruct.init_data_sec = s;
330+
mstruct.start_mcount_loc = _start_mcount_loc;
331+
mstruct.stop_mcount_loc = _stop_mcount_loc;
332+
}
258333
#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
259334
/* locate the ORC unwind tables */
260335
if (!strcmp(secstrings + idx, ".orc_unwind_ip")) {
@@ -296,6 +371,21 @@ static int do_sort(Elf_Ehdr *ehdr,
296371
goto out;
297372
}
298373
#endif
374+
if (!mstruct.init_data_sec || !_start_mcount_loc || !_stop_mcount_loc) {
375+
fprintf(stderr,
376+
"incomplete mcount's sort in file: %s\n",
377+
fname);
378+
goto out;
379+
}
380+
381+
/* create thread to sort mcount_loc concurrently */
382+
if (pthread_create(&mcount_sort_thread, NULL, &sort_mcount_loc, &mstruct)) {
383+
fprintf(stderr,
384+
"pthread_create mcount_sort_thread failed '%s': %s\n",
385+
strerror(errno), fname);
386+
goto out;
387+
}
388+
299389
if (!extab_sec) {
300390
fprintf(stderr, "no __ex_table in file: %s\n", fname);
301391
goto out;
@@ -366,17 +456,32 @@ static int do_sort(Elf_Ehdr *ehdr,
366456
void *retval = NULL;
367457
/* wait for ORC tables sort done */
368458
rc = pthread_join(orc_sort_thread, &retval);
369-
if (rc)
459+
if (rc) {
370460
fprintf(stderr,
371461
"pthread_join failed '%s': %s\n",
372462
strerror(errno), fname);
373-
else if (retval) {
463+
} else if (retval) {
374464
rc = -1;
375465
fprintf(stderr,
376466
"failed to sort ORC tables '%s': %s\n",
377467
(char *)retval, fname);
378468
}
379469
}
380470
#endif
471+
if (mcount_sort_thread) {
472+
void *retval = NULL;
473+
/* wait for mcount sort done */
474+
rc = pthread_join(mcount_sort_thread, &retval);
475+
if (rc) {
476+
fprintf(stderr,
477+
"pthread_join failed '%s': %s\n",
478+
strerror(errno), fname);
479+
} else if (retval) {
480+
rc = -1;
481+
fprintf(stderr,
482+
"failed to sort mcount '%s': %s\n",
483+
(char *)retval, fname);
484+
}
485+
}
381486
return rc;
382487
}

0 commit comments

Comments
 (0)