[PATCH 3/7] string: implement proper strdup_const/free_const
Ahmad Fatoum
a.fatoum at pengutronix.de
Mon Nov 25 07:29:23 PST 2024
We currently implement strdup_const as strdup, which is correct, but
leaves the benefits of a proper implementation on the table:
Reducing allocations for .rodata strings, which have static storage
duration anyway.
Let's implement it properly using the newly added is_barebox_rodata
and add free_const, dma_free_const and kfree_const that go along with
it.
There will be a slight difference to Linux in our API though: In Linux
devm_kfree can be used with devm_kstrdup_const, but kfree can't be used
with kstrdup_const and instead kfree_const needs to be used.
In barebox, we kfree and kfree_const is identical. This is because Linux
gives kfree a const void * parameter and we have existing code that uses
const pointers to the heap and passes them to kfree and it's not worth
risking memory corruption in this case.
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
include/dma.h | 5 +++++
include/linux/slab.h | 7 ++++---
include/linux/string.h | 5 +++++
lib/string.c | 28 ++++++++++++++++++++++++++++
4 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/include/dma.h b/include/dma.h
index 1f650aecb950..5877f4b13c0d 100644
--- a/include/dma.h
+++ b/include/dma.h
@@ -46,6 +46,11 @@ static inline void dma_free(void *mem)
free(mem);
}
+static inline void dma_free_const(const void *mem)
+{
+ free_const(mem);
+}
+
static inline void dma_free_sensitive(void *mem)
{
free_sensitive(mem);
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 5e08c7697daf..93ce25a58299 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -59,9 +59,11 @@ static inline void kmem_cache_destroy(struct kmem_cache *cache)
static inline void kfree(const void *mem)
{
- dma_free((void *)mem);
+ dma_free_const(mem);
}
+#define kfree_const(ptr) dma_free_const(ptr)
+
static inline void kfree_sensitive(const void *objp)
{
dma_free_sensitive((void *)objp);
@@ -112,7 +114,6 @@ static inline char *kstrdup(const char *str, gfp_t flags)
return strdup(str);
}
-#define kstrdup_const(str, flags) strdup(str)
-#define kfree_const(ptr) kfree((void *)ptr)
+#define kstrdup_const(str, flags) strdup_const(str)
#endif /* _LINUX_SLAB_H */
diff --git a/include/linux/string.h b/include/linux/string.h
index 5d5824b61bf0..0fa84f095e02 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -93,6 +93,11 @@ extern __kernel_size_t strnlen(const char *,__kernel_size_t);
#ifndef __HAVE_ARCH_STRDUP
extern char * strdup(const char *);
#endif
+
+extern void free_const(const void *x);
+extern const char *strdup_const(const char *s);
+const char *xstrdup_const(const char *s);
+
#ifndef __HAVE_ARCH_STRNDUP
extern char *strndup(const char *, size_t);
#endif
diff --git a/lib/string.c b/lib/string.c
index cab543baf38d..f2272be37e76 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -24,6 +24,7 @@
#include <linux/ctype.h>
#include <asm/word-at-a-time.h>
#include <malloc.h>
+#include <asm-generic/sections.h>
#ifndef __HAVE_ARCH_STRCASECMP
int strcasecmp(const char *s1, const char *s2)
@@ -1055,6 +1056,33 @@ char *strjoin(const char *separator, char **arr, size_t arrlen)
}
EXPORT_SYMBOL(strjoin);
+const char *xstrdup_const(const char *str)
+{
+ if (is_barebox_rodata((ulong)str))
+ return str;
+
+ return xstrdup(str);
+}
+EXPORT_SYMBOL(xstrdup_const);
+
+const char *strdup_const(const char *str)
+{
+ if (is_barebox_rodata((ulong)str))
+ return str;
+
+ return strdup(str);
+}
+EXPORT_SYMBOL(strdup_const);
+
+void free_const(const void *str)
+{
+ if (is_barebox_rodata((ulong)str))
+ return;
+
+ free((void *)str);
+}
+EXPORT_SYMBOL(free_const);
+
/**
* strreplace - Replace all occurrences of character in string.
* @str: The string to operate on.
--
2.39.5
More information about the barebox
mailing list