Browse Source

Simplify assert() to reduce memory usage

The behaviour of assert() now depends on the value of the new optional
platform define `PLAT_LOG_LEVEL_ASSERT`. This defaults to `LOG_LEVEL` if
not defined by the platform.

- If `PLAT_LOG_LEVEL_ASSERT` >= `LOG_LEVEL_VERBOSE`, it prints the file
  name, line and asserted expression.
- If `PLAT_LOG_LEVEL_ASSERT` >= `LOG_LEVEL_INFO`, it prints the file
  name and line.
- If not, it doesn't print anything.

Note the old behaviour was to print the function name whereas now it
prints the file name. This reduces memory usage because the file name is
shared between all assert calls in a given file. Also, the default
behaviour in debug builds is to no longer print the asserted expression,
greatly reducing the string usage.

For FVP debug builds this change saves approximately:

              No TBBR    TBBR
        BL1    1.6 KB   2.2 KB
        BL2    1.7 KB   2.1 KB
        BL31   2.6 KB   3.3 KB

Change-Id: I2947569d593df0b25611dc3c7a6096f42155c115
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
pull/936/head
Antonio Nino Diaz 8 years ago
parent
commit
0da2fe7e29
  1. 11
      docs/porting-guide.md
  2. 23
      include/lib/stdlib/assert.h
  3. 33
      lib/stdlib/assert.c

11
docs/porting-guide.md

@ -535,6 +535,17 @@ optionally be defined:
PLAT_PARTITION_MAX_ENTRIES := 12 PLAT_PARTITION_MAX_ENTRIES := 12
$(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) $(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES))
The following constant is optional. It should be defined to override the default
behaviour of the `assert()` function (for example, to save memory).
* **PLAT_LOG_LEVEL_ASSERT**
If `PLAT_LOG_LEVEL_ASSERT` is higher or equal than `LOG_LEVEL_VERBOSE`,
`assert()` prints the name of the file, the line number and the asserted
expression. Else if it is higher than `LOG_LEVEL_INFO`, it prints the file
name and the line number. Else if it is lower than `LOG_LEVEL_INFO`, it
doesn't print anything to the console. If `PLAT_LOG_LEVEL_ASSERT` isn't
defined, it defaults to `LOG_LEVEL`.
### File : plat_macros.S [mandatory] ### File : plat_macros.S [mandatory]

23
include/lib/stdlib/assert.h

@ -42,19 +42,36 @@
#ifndef _ASSERT_H_ #ifndef _ASSERT_H_
#define _ASSERT_H_ #define _ASSERT_H_
#include <debug.h>
#include <platform_def.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>
#ifndef PLAT_LOG_LEVEL_ASSERT
#define PLAT_LOG_LEVEL_ASSERT LOG_LEVEL
#endif
#if ENABLE_ASSERTIONS #if ENABLE_ASSERTIONS
#define _assert(e) assert(e) #define _assert(e) assert(e)
#define assert(e) ((e) ? (void)0 : __assert(__func__, __FILE__, \ # if PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_VERBOSE
__LINE__, #e)) # define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__, #e))
# elif PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_INFO
# define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__))
# else
# define assert(e) ((e) ? (void)0 : __assert())
# endif
#else #else
#define assert(e) ((void)0) #define assert(e) ((void)0)
#define _assert(e) ((void)0) #define _assert(e) ((void)0)
#endif /* ENABLE_ASSERTIONS */ #endif /* ENABLE_ASSERTIONS */
__BEGIN_DECLS __BEGIN_DECLS
void __assert(const char *, const char *, int, const char *) __dead2; #if PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_VERBOSE
void __assert(const char *, unsigned int, const char *) __dead2;
#elif PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_INFO
void __assert(const char *, unsigned int) __dead2;
#else
void __assert(void) __dead2;
#endif
__END_DECLS __END_DECLS
#endif /* !_ASSERT_H_ */ #endif /* !_ASSERT_H_ */

33
lib/stdlib/assert.c

@ -4,22 +4,33 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
#include <assert.h>
#include <console.h> #include <console.h>
#include <debug.h> #include <debug.h>
#include <platform.h> #include <platform.h>
void __assert(const char *function, const char *file, unsigned int line, /*
const char *assertion) * Only print the output if PLAT_LOG_LEVEL_ASSERT is higher or equal to
{ * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1.
#if LOG_LEVEL >= LOG_LEVEL_INFO */
/*
* Only print the output if LOG_LEVEL is higher or equal to
* LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1.
*/
tf_printf("ASSERT: %s <%d> : %s\n", function, line, assertion);
#if PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_VERBOSE
void __assert(const char *file, unsigned int line, const char *assertion)
{
tf_printf("ASSERT: %s <%d> : %s\n", file, line, assertion);
console_flush(); console_flush();
#endif
plat_panic_handler(); plat_panic_handler();
} }
#elif PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_INFO
void __assert(const char *file, unsigned int line)
{
tf_printf("ASSERT: %s <%d>\n", file, line);
console_flush();
plat_panic_handler();
}
#else
void __assert(void)
{
plat_panic_handler();
}
#endif

Loading…
Cancel
Save