Simplify assert() to reduce memory usage
authorAntonio Nino Diaz <antonio.ninodiaz@arm.com>
Tue, 16 May 2017 08:52:02 +0000 (09:52 +0100)
committerAntonio Nino Diaz <antonio.ninodiaz@arm.com>
Tue, 16 May 2017 08:58:08 +0000 (09:58 +0100)
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>
docs/porting-guide.md
include/lib/stdlib/assert.h
lib/stdlib/assert.c

index 0189ec407a41c84985cc4bccf8d48b84f55a0fe9..4d7a5eadc84bcc00d557ba66b73564a254877848 100644 (file)
@@ -535,6 +535,17 @@ optionally be defined:
     PLAT_PARTITION_MAX_ENTRIES :=      12
     $(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]
 
index 1bcd1ead5e6be22045c91a387221e345d54e8103..db567dbb2ad65a9fa12d186ed43b6ac81b728940 100644 (file)
 #ifndef _ASSERT_H_
 #define _ASSERT_H_
 
+#include <debug.h>
+#include <platform_def.h>
 #include <sys/cdefs.h>
 
+#ifndef PLAT_LOG_LEVEL_ASSERT
+#define PLAT_LOG_LEVEL_ASSERT  LOG_LEVEL
+#endif
+
 #if ENABLE_ASSERTIONS
 #define        _assert(e)      assert(e)
-#define        assert(e)       ((e) ? (void)0 : __assert(__func__, __FILE__, \
-                           __LINE__, #e))
+# if PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_VERBOSE
+#  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
 #define        assert(e)       ((void)0)
 #define        _assert(e)      ((void)0)
 #endif /* ENABLE_ASSERTIONS */
 
 __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
 
 #endif /* !_ASSERT_H_ */
index 5220ad8f44f91440efb16a34228173608f797c82..41f70703e25f3f4651c41e08109f6958821513f4 100644 (file)
@@ -4,22 +4,33 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
 #include <console.h>
 #include <debug.h>
 #include <platform.h>
 
-void __assert(const char *function, const char *file, unsigned int line,
-               const char *assertion)
-{
-#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);
+/*
+* 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 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();
-#endif
-
        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