Skip to content

Commit ba7b1f8

Browse files
committed
lib/test_scanf: split up number parsing test routines
It turns out that gcc has real trouble merging all the temporary on-stack buffer allocation. So despite the fact that their lifetimes do not overlap, gcc will allocate stack for all of them when they have different types. Which they do in the number scanning test routines. This is unfortunate in general, but with lots of test-cases in one function, it becomes a real problem. gcc will allocate a huge stack frame for no actual good reason. We have tried to counteract this tendency of gcc not merging stack slots (see "-fconserve-stack"), but that has limited effect (and should be on by default these days, iirc). So with all the debug options enabled on an i386 allmodconfig build, we end up with overly big stack frames, and the resulting stack frame size warnings (now errors): lib/test_scanf.c: In function ‘numbers_list_field_width_val_width’: lib/test_scanf.c:530:1: error: the frame size of 2088 bytes is larger than 2048 bytes [-Werror=frame-larger-than=] 530 | } | ^ lib/test_scanf.c: In function ‘numbers_list_field_width_typemax’: lib/test_scanf.c:488:1: error: the frame size of 2568 bytes is larger than 2048 bytes [-Werror=frame-larger-than=] 488 | } | ^ lib/test_scanf.c: In function ‘numbers_list’: lib/test_scanf.c:437:1: error: the frame size of 2088 bytes is larger than 2048 bytes [-Werror=frame-larger-than=] 437 | } | ^ In this particular case, the reasonably straightforward solution is to just split out the test routines into multiple more targeted versions. That way we don't have one huge stack, but several smaller ones, and they aren't active all at the same time. Signed-off-by: Linus Torvalds <[email protected]>
1 parent 1476ff2 commit ba7b1f8

File tree

1 file changed

+71
-8
lines changed

1 file changed

+71
-8
lines changed

lib/test_scanf.c

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -398,36 +398,48 @@ do { \
398398
test_array_8(fn, expect, test_buffer, fmt_buffer, result); \
399399
} while (0)
400400

401-
static void __init numbers_list(const char *delim)
401+
static void __init numbers_list_ll(const char *delim)
402402
{
403403
numbers_list_8(unsigned long long, "%llu", delim, "llu", check_ull);
404404
numbers_list_8(long long, "%lld", delim, "lld", check_ll);
405405
numbers_list_8(long long, "%lld", delim, "lli", check_ll);
406406
numbers_list_8(unsigned long long, "%llx", delim, "llx", check_ull);
407407
numbers_list_8(unsigned long long, "0x%llx", delim, "llx", check_ull);
408408
numbers_list_8(long long, "0x%llx", delim, "lli", check_ll);
409+
}
409410

411+
static void __init numbers_list_l(const char *delim)
412+
{
410413
numbers_list_8(unsigned long, "%lu", delim, "lu", check_ulong);
411414
numbers_list_8(long, "%ld", delim, "ld", check_long);
412415
numbers_list_8(long, "%ld", delim, "li", check_long);
413416
numbers_list_8(unsigned long, "%lx", delim, "lx", check_ulong);
414417
numbers_list_8(unsigned long, "0x%lx", delim, "lx", check_ulong);
415418
numbers_list_8(long, "0x%lx", delim, "li", check_long);
419+
}
416420

421+
static void __init numbers_list_d(const char *delim)
422+
{
417423
numbers_list_8(unsigned int, "%u", delim, "u", check_uint);
418424
numbers_list_8(int, "%d", delim, "d", check_int);
419425
numbers_list_8(int, "%d", delim, "i", check_int);
420426
numbers_list_8(unsigned int, "%x", delim, "x", check_uint);
421427
numbers_list_8(unsigned int, "0x%x", delim, "x", check_uint);
422428
numbers_list_8(int, "0x%x", delim, "i", check_int);
429+
}
423430

431+
static void __init numbers_list_h(const char *delim)
432+
{
424433
numbers_list_8(unsigned short, "%hu", delim, "hu", check_ushort);
425434
numbers_list_8(short, "%hd", delim, "hd", check_short);
426435
numbers_list_8(short, "%hd", delim, "hi", check_short);
427436
numbers_list_8(unsigned short, "%hx", delim, "hx", check_ushort);
428437
numbers_list_8(unsigned short, "0x%hx", delim, "hx", check_ushort);
429438
numbers_list_8(short, "0x%hx", delim, "hi", check_short);
439+
}
430440

441+
static void __init numbers_list_hh(const char *delim)
442+
{
431443
numbers_list_8(unsigned char, "%hhu", delim, "hhu", check_uchar);
432444
numbers_list_8(signed char, "%hhd", delim, "hhd", check_char);
433445
numbers_list_8(signed char, "%hhd", delim, "hhi", check_char);
@@ -436,19 +448,27 @@ static void __init numbers_list(const char *delim)
436448
numbers_list_8(signed char, "0x%hhx", delim, "hhi", check_char);
437449
}
438450

439-
/*
440-
* List of numbers separated by delim. Each field width specifier is the
441-
* maximum possible digits for the given type and base.
442-
*/
443-
static void __init numbers_list_field_width_typemax(const char *delim)
451+
static void __init numbers_list(const char *delim)
452+
{
453+
numbers_list_ll(delim);
454+
numbers_list_l(delim);
455+
numbers_list_d(delim);
456+
numbers_list_h(delim);
457+
numbers_list_hh(delim);
458+
}
459+
460+
static void __init numbers_list_field_width_ll(const char *delim)
444461
{
445462
numbers_list_fix_width(unsigned long long, "%llu", delim, 20, "llu", check_ull);
446463
numbers_list_fix_width(long long, "%lld", delim, 20, "lld", check_ll);
447464
numbers_list_fix_width(long long, "%lld", delim, 20, "lli", check_ll);
448465
numbers_list_fix_width(unsigned long long, "%llx", delim, 16, "llx", check_ull);
449466
numbers_list_fix_width(unsigned long long, "0x%llx", delim, 18, "llx", check_ull);
450467
numbers_list_fix_width(long long, "0x%llx", delim, 18, "lli", check_ll);
468+
}
451469

470+
static void __init numbers_list_field_width_l(const char *delim)
471+
{
452472
#if BITS_PER_LONG == 64
453473
numbers_list_fix_width(unsigned long, "%lu", delim, 20, "lu", check_ulong);
454474
numbers_list_fix_width(long, "%ld", delim, 20, "ld", check_long);
@@ -464,21 +484,30 @@ static void __init numbers_list_field_width_typemax(const char *delim)
464484
numbers_list_fix_width(unsigned long, "0x%lx", delim, 10, "lx", check_ulong);
465485
numbers_list_fix_width(long, "0x%lx", delim, 10, "li", check_long);
466486
#endif
487+
}
467488

489+
static void __init numbers_list_field_width_d(const char *delim)
490+
{
468491
numbers_list_fix_width(unsigned int, "%u", delim, 10, "u", check_uint);
469492
numbers_list_fix_width(int, "%d", delim, 11, "d", check_int);
470493
numbers_list_fix_width(int, "%d", delim, 11, "i", check_int);
471494
numbers_list_fix_width(unsigned int, "%x", delim, 8, "x", check_uint);
472495
numbers_list_fix_width(unsigned int, "0x%x", delim, 10, "x", check_uint);
473496
numbers_list_fix_width(int, "0x%x", delim, 10, "i", check_int);
497+
}
474498

499+
static void __init numbers_list_field_width_h(const char *delim)
500+
{
475501
numbers_list_fix_width(unsigned short, "%hu", delim, 5, "hu", check_ushort);
476502
numbers_list_fix_width(short, "%hd", delim, 6, "hd", check_short);
477503
numbers_list_fix_width(short, "%hd", delim, 6, "hi", check_short);
478504
numbers_list_fix_width(unsigned short, "%hx", delim, 4, "hx", check_ushort);
479505
numbers_list_fix_width(unsigned short, "0x%hx", delim, 6, "hx", check_ushort);
480506
numbers_list_fix_width(short, "0x%hx", delim, 6, "hi", check_short);
507+
}
481508

509+
static void __init numbers_list_field_width_hh(const char *delim)
510+
{
482511
numbers_list_fix_width(unsigned char, "%hhu", delim, 3, "hhu", check_uchar);
483512
numbers_list_fix_width(signed char, "%hhd", delim, 4, "hhd", check_char);
484513
numbers_list_fix_width(signed char, "%hhd", delim, 4, "hhi", check_char);
@@ -489,38 +518,59 @@ static void __init numbers_list_field_width_typemax(const char *delim)
489518

490519
/*
491520
* List of numbers separated by delim. Each field width specifier is the
492-
* exact length of the corresponding value digits in the string being scanned.
521+
* maximum possible digits for the given type and base.
493522
*/
494-
static void __init numbers_list_field_width_val_width(const char *delim)
523+
static void __init numbers_list_field_width_typemax(const char *delim)
524+
{
525+
numbers_list_field_width_ll(delim);
526+
numbers_list_field_width_l(delim);
527+
numbers_list_field_width_d(delim);
528+
numbers_list_field_width_h(delim);
529+
numbers_list_field_width_hh(delim);
530+
}
531+
532+
static void __init numbers_list_field_width_val_ll(const char *delim)
495533
{
496534
numbers_list_val_width(unsigned long long, "%llu", delim, "llu", check_ull);
497535
numbers_list_val_width(long long, "%lld", delim, "lld", check_ll);
498536
numbers_list_val_width(long long, "%lld", delim, "lli", check_ll);
499537
numbers_list_val_width(unsigned long long, "%llx", delim, "llx", check_ull);
500538
numbers_list_val_width(unsigned long long, "0x%llx", delim, "llx", check_ull);
501539
numbers_list_val_width(long long, "0x%llx", delim, "lli", check_ll);
540+
}
502541

542+
static void __init numbers_list_field_width_val_l(const char *delim)
543+
{
503544
numbers_list_val_width(unsigned long, "%lu", delim, "lu", check_ulong);
504545
numbers_list_val_width(long, "%ld", delim, "ld", check_long);
505546
numbers_list_val_width(long, "%ld", delim, "li", check_long);
506547
numbers_list_val_width(unsigned long, "%lx", delim, "lx", check_ulong);
507548
numbers_list_val_width(unsigned long, "0x%lx", delim, "lx", check_ulong);
508549
numbers_list_val_width(long, "0x%lx", delim, "li", check_long);
550+
}
509551

552+
static void __init numbers_list_field_width_val_d(const char *delim)
553+
{
510554
numbers_list_val_width(unsigned int, "%u", delim, "u", check_uint);
511555
numbers_list_val_width(int, "%d", delim, "d", check_int);
512556
numbers_list_val_width(int, "%d", delim, "i", check_int);
513557
numbers_list_val_width(unsigned int, "%x", delim, "x", check_uint);
514558
numbers_list_val_width(unsigned int, "0x%x", delim, "x", check_uint);
515559
numbers_list_val_width(int, "0x%x", delim, "i", check_int);
560+
}
516561

562+
static void __init numbers_list_field_width_val_h(const char *delim)
563+
{
517564
numbers_list_val_width(unsigned short, "%hu", delim, "hu", check_ushort);
518565
numbers_list_val_width(short, "%hd", delim, "hd", check_short);
519566
numbers_list_val_width(short, "%hd", delim, "hi", check_short);
520567
numbers_list_val_width(unsigned short, "%hx", delim, "hx", check_ushort);
521568
numbers_list_val_width(unsigned short, "0x%hx", delim, "hx", check_ushort);
522569
numbers_list_val_width(short, "0x%hx", delim, "hi", check_short);
570+
}
523571

572+
static void __init numbers_list_field_width_val_hh(const char *delim)
573+
{
524574
numbers_list_val_width(unsigned char, "%hhu", delim, "hhu", check_uchar);
525575
numbers_list_val_width(signed char, "%hhd", delim, "hhd", check_char);
526576
numbers_list_val_width(signed char, "%hhd", delim, "hhi", check_char);
@@ -529,6 +579,19 @@ static void __init numbers_list_field_width_val_width(const char *delim)
529579
numbers_list_val_width(signed char, "0x%hhx", delim, "hhi", check_char);
530580
}
531581

582+
/*
583+
* List of numbers separated by delim. Each field width specifier is the
584+
* exact length of the corresponding value digits in the string being scanned.
585+
*/
586+
static void __init numbers_list_field_width_val_width(const char *delim)
587+
{
588+
numbers_list_field_width_val_ll(delim);
589+
numbers_list_field_width_val_l(delim);
590+
numbers_list_field_width_val_d(delim);
591+
numbers_list_field_width_val_h(delim);
592+
numbers_list_field_width_val_hh(delim);
593+
}
594+
532595
/*
533596
* Slice a continuous string of digits without field delimiters, containing
534597
* numbers of varying length, using the field width to extract each group

0 commit comments

Comments
 (0)