[libc-commits] [libc] [libc] add snmalloc as an alternative allocator to libc (PR #122284)
Schrodinger ZHU Yifan via libc-commits
libc-commits at lists.llvm.org
Sun Jan 26 17:19:56 PST 2025
https://github.com/SchrodingerZhu updated https://github.com/llvm/llvm-project/pull/122284
>From 503caadaec4f001918bfe08141bbb96ff2e42a1e Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <i at zhuyi.fan>
Date: Thu, 9 Jan 2025 22:57:57 +0800
Subject: [PATCH 01/10] POC: add snmalloc as an alternative allocator to libc
---
libc/src/stdlib/CMakeLists.txt | 41 +++++++++++-
libc/src/stdlib/snmalloc/CMakeLists.txt | 75 ++++++++++++++++++++++
libc/src/stdlib/snmalloc/aligned_alloc.cpp | 0
libc/src/stdlib/snmalloc/calloc.cpp | 0
libc/src/stdlib/snmalloc/free.cpp | 0
libc/src/stdlib/snmalloc/malloc.cpp | 9 +++
libc/src/stdlib/snmalloc/mallopt.cpp | 0
libc/src/stdlib/snmalloc/realloc.cpp | 0
libc/src/stdlib/snmalloc/support.h | 14 ++++
9 files changed, 138 insertions(+), 1 deletion(-)
create mode 100644 libc/src/stdlib/snmalloc/CMakeLists.txt
create mode 100644 libc/src/stdlib/snmalloc/aligned_alloc.cpp
create mode 100644 libc/src/stdlib/snmalloc/calloc.cpp
create mode 100644 libc/src/stdlib/snmalloc/free.cpp
create mode 100644 libc/src/stdlib/snmalloc/malloc.cpp
create mode 100644 libc/src/stdlib/snmalloc/mallopt.cpp
create mode 100644 libc/src/stdlib/snmalloc/realloc.cpp
create mode 100644 libc/src/stdlib/snmalloc/support.h
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index 73a9fbf1e2ddc3..dabbb655867ab8 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -324,7 +324,46 @@ add_entrypoint_object(
)
if(NOT LIBC_TARGET_OS_IS_BAREMETAL AND NOT LIBC_TARGET_OS_IS_GPU)
- if(LLVM_LIBC_INCLUDE_SCUDO)
+ if (NOT "${LLVM_LIBC_INCLUDE_SNMALLOC}" STREQUAL "")
+ message(STATUS "Including snmalloc as the allocator, source directory: ${LLVM_LIBC_INCLUDE_SNMALLOC}")
+ add_subdirectory(snmalloc)
+ add_entrypoint_object(
+ malloc
+ ALIAS
+ DEPENDS
+ .snmalloc.malloc
+ )
+ add_entrypoint_object(
+ calloc
+ ALIAS
+ DEPENDS
+ .snmalloc.calloc
+ )
+ add_entrypoint_object(
+ realloc
+ ALIAS
+ DEPENDS
+ .snmalloc.realloc
+ )
+ add_entrypoint_object(
+ aligned_alloc
+ ALIAS
+ DEPENDS
+ .snmalloc.aligned_alloc
+ )
+ add_entrypoint_object(
+ free
+ ALIAS
+ DEPENDS
+ .snmalloc.free
+ )
+ add_entrypoint_object(
+ mallopt
+ ALIAS
+ DEPENDS
+ .snmalloc.mallopt
+ )
+ elseif(LLVM_LIBC_INCLUDE_SCUDO)
set(SCUDO_DEPS "")
include(${LIBC_SOURCE_DIR}/../compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake)
diff --git a/libc/src/stdlib/snmalloc/CMakeLists.txt b/libc/src/stdlib/snmalloc/CMakeLists.txt
new file mode 100644
index 00000000000000..3971ea42db1744
--- /dev/null
+++ b/libc/src/stdlib/snmalloc/CMakeLists.txt
@@ -0,0 +1,75 @@
+set(SNMALLOC_USE_SELF_VENDORED_STL ON CACHE BOOL "use freestanding snmalloc setup" FORCE)
+set(SNMALLOC_BUILD_TESTING OFF CACHE BOOL "disable snmalloc tests" FORCE)
+set(SNMALLOC_HEADER_ONLY_LIBRARY ON CACHE BOOL "use snmalloc as header only library" FORCE)
+
+# Disable installation
+macro (install)
+endmacro ()
+
+add_subdirectory(${LLVM_LIBC_INCLUDE_SNMALLOC} ${CMAKE_CURRENT_BINARY_DIR}/snmalloc EXCLUDE_FROM_ALL)
+
+target_compile_options(
+ snmalloc
+ INTERFACE
+ -ffreestanding
+ -nostdinc
+ -Wno-newline-eof
+ -Wno-extra-semi
+ -Wno-unused-command-line-argument
+ -Wno-ctad-maybe-unsupported
+ # TODO: define this
+ -DSTDERR_FILENO=2
+ -include ${CMAKE_CURRENT_SOURCE_DIR}/support.h
+ # include_directories does not propagate, use options instead
+ -isystem ${COMPILER_RESOURCE_DIR}/include
+ -isystem ${LIBC_INCLUDE_DIR}
+)
+add_dependencies(snmalloc libc-headers)
+
+add_entrypoint_object(
+ malloc
+ SRCS
+ malloc.cpp
+ DEPENDS
+ snmalloc
+)
+
+add_entrypoint_object(
+ calloc
+ SRCS
+ calloc.cpp
+ DEPENDS
+ snmalloc
+)
+
+add_entrypoint_object(
+ realloc
+ SRCS
+ realloc.cpp
+ DEPENDS
+ snmalloc
+)
+
+add_entrypoint_object(
+ aligned_alloc
+ SRCS
+ aligned_alloc.cpp
+ DEPENDS
+ snmalloc
+)
+
+add_entrypoint_object(
+ free
+ SRCS
+ free.cpp
+ DEPENDS
+ snmalloc
+)
+
+add_entrypoint_object(
+ mallopt
+ SRCS
+ mallopt.cpp
+ DEPENDS
+ snmalloc
+)
diff --git a/libc/src/stdlib/snmalloc/aligned_alloc.cpp b/libc/src/stdlib/snmalloc/aligned_alloc.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdlib/snmalloc/calloc.cpp b/libc/src/stdlib/snmalloc/calloc.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdlib/snmalloc/free.cpp b/libc/src/stdlib/snmalloc/free.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdlib/snmalloc/malloc.cpp b/libc/src/stdlib/snmalloc/malloc.cpp
new file mode 100644
index 00000000000000..644f2eef0ed2bf
--- /dev/null
+++ b/libc/src/stdlib/snmalloc/malloc.cpp
@@ -0,0 +1,9 @@
+#include "src/stdlib/malloc.h"
+#include "snmalloc/snmalloc.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE_DECL {
+LLVM_LIBC_FUNCTION(void *, malloc, (size_t size)) {
+ return snmalloc::libc::malloc(size);
+}
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdlib/snmalloc/mallopt.cpp b/libc/src/stdlib/snmalloc/mallopt.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdlib/snmalloc/realloc.cpp b/libc/src/stdlib/snmalloc/realloc.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdlib/snmalloc/support.h b/libc/src/stdlib/snmalloc/support.h
new file mode 100644
index 00000000000000..4909667c1a50d8
--- /dev/null
+++ b/libc/src/stdlib/snmalloc/support.h
@@ -0,0 +1,14 @@
+#include "src/sys/random/getrandom.h"
+
+// TODO: define this
+inline int getentropy(void *buf, size_t size) {
+ while (size > 0) {
+ ssize_t ret = LIBC_NAMESPACE::getrandom(buf, size, 0);
+ if (ret < 0) {
+ return -1;
+ }
+ buf = (char *)buf + ret;
+ size -= ret;
+ }
+ return 0;
+}
>From 7b6d35630883bdd60dcfb04cd662bd49e3a6baed Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <i at zhuyi.fan>
Date: Thu, 16 Jan 2025 04:08:22 +0000
Subject: [PATCH 02/10] adjust build
---
libc/src/stdlib/snmalloc/CMakeLists.txt | 2 +-
libc/src/stdlib/snmalloc/free.cpp | 17 +++++++++++++++++
libc/src/stdlib/snmalloc/malloc.cpp | 8 ++++++++
libc/src/stdlib/snmalloc/support.h | 14 --------------
4 files changed, 26 insertions(+), 15 deletions(-)
delete mode 100644 libc/src/stdlib/snmalloc/support.h
diff --git a/libc/src/stdlib/snmalloc/CMakeLists.txt b/libc/src/stdlib/snmalloc/CMakeLists.txt
index 3971ea42db1744..516505c09a13d1 100644
--- a/libc/src/stdlib/snmalloc/CMakeLists.txt
+++ b/libc/src/stdlib/snmalloc/CMakeLists.txt
@@ -19,7 +19,7 @@ target_compile_options(
-Wno-ctad-maybe-unsupported
# TODO: define this
-DSTDERR_FILENO=2
- -include ${CMAKE_CURRENT_SOURCE_DIR}/support.h
+ -DSNMALLOC_USE_PTHREAD_DESTRUCTORS
# include_directories does not propagate, use options instead
-isystem ${COMPILER_RESOURCE_DIR}/include
-isystem ${LIBC_INCLUDE_DIR}
diff --git a/libc/src/stdlib/snmalloc/free.cpp b/libc/src/stdlib/snmalloc/free.cpp
index e69de29bb2d1d6..a3160c15d0df38 100644
--- a/libc/src/stdlib/snmalloc/free.cpp
+++ b/libc/src/stdlib/snmalloc/free.cpp
@@ -0,0 +1,17 @@
+//===-- Implementation of free --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/free.h"
+#include "snmalloc/snmalloc.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE_DECL {
+LLVM_LIBC_FUNCTION(void, free, (void * ptr)) {
+ return snmalloc::libc::free(ptr);
+}
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdlib/snmalloc/malloc.cpp b/libc/src/stdlib/snmalloc/malloc.cpp
index 644f2eef0ed2bf..ab58e63743016a 100644
--- a/libc/src/stdlib/snmalloc/malloc.cpp
+++ b/libc/src/stdlib/snmalloc/malloc.cpp
@@ -1,3 +1,11 @@
+//===-- Implementation of malloc ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
#include "src/stdlib/malloc.h"
#include "snmalloc/snmalloc.h"
#include "src/__support/common.h"
diff --git a/libc/src/stdlib/snmalloc/support.h b/libc/src/stdlib/snmalloc/support.h
deleted file mode 100644
index 4909667c1a50d8..00000000000000
--- a/libc/src/stdlib/snmalloc/support.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "src/sys/random/getrandom.h"
-
-// TODO: define this
-inline int getentropy(void *buf, size_t size) {
- while (size > 0) {
- ssize_t ret = LIBC_NAMESPACE::getrandom(buf, size, 0);
- if (ret < 0) {
- return -1;
- }
- buf = (char *)buf + ret;
- size -= ret;
- }
- return 0;
-}
>From 490c4f2834b84591fd0cb5e96f195fb7e2a9fc68 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <i at zhuyi.fan>
Date: Thu, 16 Jan 2025 04:26:12 +0000
Subject: [PATCH 03/10] implement all symbols
---
libc/src/stdlib/snmalloc/aligned_alloc.cpp | 17 +++++++++++++++++
libc/src/stdlib/snmalloc/calloc.cpp | 17 +++++++++++++++++
libc/src/stdlib/snmalloc/free.cpp | 2 +-
libc/src/stdlib/snmalloc/mallopt.cpp | 13 +++++++++++++
libc/src/stdlib/snmalloc/realloc.cpp | 17 +++++++++++++++++
5 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/libc/src/stdlib/snmalloc/aligned_alloc.cpp b/libc/src/stdlib/snmalloc/aligned_alloc.cpp
index e69de29bb2d1d6..ee1d74ca9c778c 100644
--- a/libc/src/stdlib/snmalloc/aligned_alloc.cpp
+++ b/libc/src/stdlib/snmalloc/aligned_alloc.cpp
@@ -0,0 +1,17 @@
+//===-- Implementation of aligned_alloc -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/aligned_alloc.h"
+#include "snmalloc/snmalloc.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE_DECL {
+LLVM_LIBC_FUNCTION(void *, aligned_alloc, (size_t alignment, size_t size)) {
+ return snmalloc::libc::aligned_alloc(alignment, size);
+}
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdlib/snmalloc/calloc.cpp b/libc/src/stdlib/snmalloc/calloc.cpp
index e69de29bb2d1d6..39af67607bf709 100644
--- a/libc/src/stdlib/snmalloc/calloc.cpp
+++ b/libc/src/stdlib/snmalloc/calloc.cpp
@@ -0,0 +1,17 @@
+//===-- Implementation of calloc ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/calloc.h"
+#include "snmalloc/snmalloc.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE_DECL {
+LLVM_LIBC_FUNCTION(void *, calloc, (size_t num, size_t size)) {
+ return snmalloc::libc::calloc(num, size);
+}
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdlib/snmalloc/free.cpp b/libc/src/stdlib/snmalloc/free.cpp
index a3160c15d0df38..eb403710fffada 100644
--- a/libc/src/stdlib/snmalloc/free.cpp
+++ b/libc/src/stdlib/snmalloc/free.cpp
@@ -11,7 +11,7 @@
#include "src/__support/common.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(void, free, (void * ptr)) {
+LLVM_LIBC_FUNCTION(void, free, (void *ptr)) {
return snmalloc::libc::free(ptr);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdlib/snmalloc/mallopt.cpp b/libc/src/stdlib/snmalloc/mallopt.cpp
index e69de29bb2d1d6..c52d68e3d52230 100644
--- a/libc/src/stdlib/snmalloc/mallopt.cpp
+++ b/libc/src/stdlib/snmalloc/mallopt.cpp
@@ -0,0 +1,13 @@
+//===-- Implementation of mallopt stub ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE_DECL {
+LLVM_LIBC_FUNCTION(int, mallopt, (int, int)) { return 0; }
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdlib/snmalloc/realloc.cpp b/libc/src/stdlib/snmalloc/realloc.cpp
index e69de29bb2d1d6..36972e0a2232ec 100644
--- a/libc/src/stdlib/snmalloc/realloc.cpp
+++ b/libc/src/stdlib/snmalloc/realloc.cpp
@@ -0,0 +1,17 @@
+//===-- Implementation of realloc -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/realloc.h"
+#include "snmalloc/snmalloc.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE_DECL {
+LLVM_LIBC_FUNCTION(void *, realloc, (void *ptr, size_t size)) {
+ return snmalloc::libc::realloc(ptr, size);
+}
+} // namespace LIBC_NAMESPACE_DECL
>From 64e639e53f3ef8cdd8f70f3e1b4a53a203f6817e Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <i at zhuyi.fan>
Date: Thu, 16 Jan 2025 05:09:37 +0000
Subject: [PATCH 04/10] setup dependencies
---
libc/src/stdlib/snmalloc/CMakeLists.txt | 43 +++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/libc/src/stdlib/snmalloc/CMakeLists.txt b/libc/src/stdlib/snmalloc/CMakeLists.txt
index 516505c09a13d1..cc7172c947c4c2 100644
--- a/libc/src/stdlib/snmalloc/CMakeLists.txt
+++ b/libc/src/stdlib/snmalloc/CMakeLists.txt
@@ -24,8 +24,46 @@ target_compile_options(
-isystem ${COMPILER_RESOURCE_DIR}/include
-isystem ${LIBC_INCLUDE_DIR}
)
+
add_dependencies(snmalloc libc-headers)
+set(SNMALLOC_DEPS
+ # includes
+ libc.include.errno
+ libc.include.fcntl
+ libc.include.limits
+ libc.include.pthread
+ libc.include.stdio
+ libc.include.stdint
+ libc.include.stdlib
+ libc.include.string
+ libc.include.strings
+ libc.include.sys_mman
+ libc.include.sys_prctl
+ libc.include.sys_random
+ libc.include.sys_syscall
+ libc.include.sys_uio
+ libc.include.unistd
+ # symbols
+ libc.src.errno.errno
+ libc.src.fcntl.open
+ libc.src.pthread.pthread_key_create
+ libc.src.pthread.pthread_setspecific
+ libc.src.stdlib.abort
+ libc.src.stdlib.atexit
+ libc.src.string.memset
+ libc.src.string.strlen
+ libc.src.sys.mman.madvise
+ libc.src.sys.mman.mmap
+ libc.src.sys.uio.writev
+ libc.src.time.clock_gettime
+ libc.src.unistd.__llvm_libc_syscall
+ libc.src.unistd.close
+ libc.src.unistd.fsync
+ libc.src.unistd.getentropy
+ libc.src.unistd.read
+)
+
add_entrypoint_object(
malloc
SRCS
@@ -40,6 +78,7 @@ add_entrypoint_object(
calloc.cpp
DEPENDS
snmalloc
+ ${SNMALLOC_DEPS}
)
add_entrypoint_object(
@@ -48,6 +87,7 @@ add_entrypoint_object(
realloc.cpp
DEPENDS
snmalloc
+ ${SNMALLOC_DEPS}
)
add_entrypoint_object(
@@ -56,6 +96,7 @@ add_entrypoint_object(
aligned_alloc.cpp
DEPENDS
snmalloc
+ ${SNMALLOC_DEPS}
)
add_entrypoint_object(
@@ -64,6 +105,7 @@ add_entrypoint_object(
free.cpp
DEPENDS
snmalloc
+ ${SNMALLOC_DEPS}
)
add_entrypoint_object(
@@ -72,4 +114,5 @@ add_entrypoint_object(
mallopt.cpp
DEPENDS
snmalloc
+ ${SNMALLOC_DEPS}
)
>From 1e287f0cd144c7289c7cf5a955add80853f5b256 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <i at zhuyi.fan>
Date: Thu, 16 Jan 2025 06:12:42 +0000
Subject: [PATCH 05/10] make hermetic build pass with snmalloc
---
libc/src/stdlib/snmalloc/CMakeLists.txt | 1 +
libc/src/stdlib/snmalloc/override.h | 32 +++++++++++++++++++++++++
libc/test/src/stdlib/CMakeLists.txt | 8 ++++---
3 files changed, 38 insertions(+), 3 deletions(-)
create mode 100644 libc/src/stdlib/snmalloc/override.h
diff --git a/libc/src/stdlib/snmalloc/CMakeLists.txt b/libc/src/stdlib/snmalloc/CMakeLists.txt
index cc7172c947c4c2..e360b36f5fb3ad 100644
--- a/libc/src/stdlib/snmalloc/CMakeLists.txt
+++ b/libc/src/stdlib/snmalloc/CMakeLists.txt
@@ -21,6 +21,7 @@ target_compile_options(
-DSTDERR_FILENO=2
-DSNMALLOC_USE_PTHREAD_DESTRUCTORS
# include_directories does not propagate, use options instead
+ -include ${CMAKE_CURRENT_SOURCE_DIR}/override.h
-isystem ${COMPILER_RESOURCE_DIR}/include
-isystem ${LIBC_INCLUDE_DIR}
)
diff --git a/libc/src/stdlib/snmalloc/override.h b/libc/src/stdlib/snmalloc/override.h
new file mode 100644
index 00000000000000..a36a6316790fbd
--- /dev/null
+++ b/libc/src/stdlib/snmalloc/override.h
@@ -0,0 +1,32 @@
+//===-- Macro Override for SnMalloc ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// skip special headers
+#define LLVM_LIBC_COMMON_H
+#define LLVM_LIBC_ERRNO_H
+
+// define common macros
+#define __BEGIN_C_DECLS namespace LIBC_NAMESPACE {
+#define __END_C_DECLS \
+ } \
+ using namespace LIBC_NAMESPACE;
+
+#define _Noreturn [[noreturn]]
+#define _Alignas alignas
+#define _Static_assert static_assert
+#define _Alignof alignof
+#define _Thread_local thread_local
+
+// Use empty definition to avoid spec mismatching
+// We are building internally anyway, hence noexcept does not matter here
+#define __NOEXCEPT
+
+// Enforce internal errno implementation
+#include "hdr/errno_macros.h"
+#include "src/errno/libc_errno.h"
+#define errno libc_errno
diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt
index aba76833be9d41..ce050b0286641a 100644
--- a/libc/test/src/stdlib/CMakeLists.txt
+++ b/libc/test/src/stdlib/CMakeLists.txt
@@ -419,9 +419,11 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.stdlib.quick_exit
)
- # Only baremetal and GPU has an in-tree 'malloc' implementation.
- if((LIBC_TARGET_OS_IS_BAREMETAL OR LIBC_TARGET_OS_IS_GPU) AND
- NOT LIBC_TARGET_ARCHITECTURE_IS_NVPTX)
+ # Only baremetal, snmalloc and GPU has an in-tree 'malloc'
+ # implementation.
+ if(LIBC_TARGET_OS_IS_BAREMETAL
+ OR (LIBC_TARGET_OS_IS_GPU AND NOT LIBC_TARGET_ARCHITECTURE_IS_NVPTX)
+ OR NOT "${LLVM_LIBC_INCLUDE_SNMALLOC}")
add_libc_test(
malloc_test
HERMETIC_TEST_ONLY
>From 8e46a124956b562826b84953c56e0fdb03fdef9a Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <i at zhuyi.fan>
Date: Sun, 19 Jan 2025 09:04:54 +0000
Subject: [PATCH 06/10] use _malloc_thread_cleanup hook in fullbuild mode
---
libc/src/__support/threads/linux/CMakeLists.txt | 5 +++++
libc/src/__support/threads/linux/thread.cpp | 10 ++++++++++
libc/src/stdlib/CMakeLists.txt | 9 +++++++++
libc/src/stdlib/atexit.cpp | 9 +++++++++
libc/src/stdlib/snmalloc/CMakeLists.txt | 5 -----
libc/src/stdlib/snmalloc/aligned_alloc.cpp | 4 +++-
libc/src/stdlib/snmalloc/calloc.cpp | 4 +++-
libc/src/stdlib/snmalloc/free.cpp | 4 +++-
libc/src/stdlib/snmalloc/malloc.cpp | 4 +++-
libc/src/stdlib/snmalloc/override.h | 4 ++++
libc/src/stdlib/snmalloc/realloc.cpp | 4 +++-
11 files changed, 52 insertions(+), 10 deletions(-)
diff --git a/libc/src/__support/threads/linux/CMakeLists.txt b/libc/src/__support/threads/linux/CMakeLists.txt
index 364e7e2b905854..74dfef3d150736 100644
--- a/libc/src/__support/threads/linux/CMakeLists.txt
+++ b/libc/src/__support/threads/linux/CMakeLists.txt
@@ -71,6 +71,10 @@ add_header_library(
libc.src.__support.threads.mutex_common
)
+if (NOT "${LLVM_LIBC_INCLUDE_SNMALLOC}" STREQUAL "")
+ set (libc_malloc_thread_cleanup_flag "-DLIBC_USE_MALLOC_THREAD_CLEANUP")
+endif()
+
add_object_library(
thread
SRCS
@@ -89,6 +93,7 @@ add_object_library(
libc.src.__support.threads.thread_common
COMPILE_OPTIONS
${libc_opt_high_flag}
+ ${libc_malloc_thread_cleanup_flag}
-fno-omit-frame-pointer # This allows us to sniff out the thread args from
# the new thread's stack reliably.
-Wno-frame-address # Yes, calling __builtin_return_address with a
diff --git a/libc/src/__support/threads/linux/thread.cpp b/libc/src/__support/threads/linux/thread.cpp
index c531d74c533550..a80c04a24fdba8 100644
--- a/libc/src/__support/threads/linux/thread.cpp
+++ b/libc/src/__support/threads/linux/thread.cpp
@@ -482,6 +482,11 @@ int Thread::get_name(cpp::StringStream &name) const {
return 0;
}
+#ifdef LIBC_USE_MALLOC_THREAD_CLEANUP
+// This symbol may not be defined if libc is not built with allocator
+extern "C" [[gnu::weak]] void _malloc_thread_cleanup();
+#endif
+
void thread_exit(ThreadReturnValue retval, ThreadStyle style) {
auto attrib = self.attrib;
@@ -494,6 +499,11 @@ void thread_exit(ThreadReturnValue retval, ThreadStyle style) {
// different thread. The destructors of thread local and TSS objects should
// be called by the thread which owns them.
internal::call_atexit_callbacks(attrib);
+#ifdef LIBC_USE_MALLOC_THREAD_CLEANUP
+ // teardown TLS heap
+ if (_malloc_thread_cleanup)
+ _malloc_thread_cleanup();
+#endif
uint32_t joinable_state = uint32_t(DetachState::JOINABLE);
if (!attrib->detach_state.compare_exchange_strong(
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index dabbb655867ab8..db7873a537a99a 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -326,6 +326,9 @@ add_entrypoint_object(
if(NOT LIBC_TARGET_OS_IS_BAREMETAL AND NOT LIBC_TARGET_OS_IS_GPU)
if (NOT "${LLVM_LIBC_INCLUDE_SNMALLOC}" STREQUAL "")
message(STATUS "Including snmalloc as the allocator, source directory: ${LLVM_LIBC_INCLUDE_SNMALLOC}")
+ if (NOT LLVM_LIBC_FULL_BUILD)
+ message(FATAL_ERROR "Snmalloc can only be included when fullbuild mode is enabled")
+ endif()
add_subdirectory(snmalloc)
add_entrypoint_object(
malloc
@@ -595,6 +598,10 @@ add_header_library(
)
endif()
+if (NOT "${LLVM_LIBC_INCLUDE_SNMALLOC}" STREQUAL "")
+ set (libc_malloc_thread_cleanup_flag "-DLIBC_USE_MALLOC_THREAD_CLEANUP")
+endif()
+
add_entrypoint_object(
atexit
SRCS
@@ -605,6 +612,8 @@ add_entrypoint_object(
20 # For constinit
DEPENDS
.exit_handler
+ COMPILE_OPTIONS
+ ${libc_malloc_thread_cleanup_flag}
)
add_entrypoint_object(
diff --git a/libc/src/stdlib/atexit.cpp b/libc/src/stdlib/atexit.cpp
index 799aad136bda5c..e5baca946c85b0 100644
--- a/libc/src/stdlib/atexit.cpp
+++ b/libc/src/stdlib/atexit.cpp
@@ -18,6 +18,11 @@ constinit ExitCallbackList atexit_callbacks;
Mutex handler_list_mtx(false, false, false, false);
[[gnu::weak]] extern void teardown_main_tls();
+#ifdef LIBC_USE_MALLOC_THREAD_CLEANUP
+// This symbol may not be defined if libc is not built with allocator
+extern "C" [[gnu::weak]] void _malloc_thread_cleanup();
+#endif
+
extern "C" {
int __cxa_atexit(AtExitCallback *callback, void *payload, void *) {
@@ -27,6 +32,10 @@ int __cxa_atexit(AtExitCallback *callback, void *payload, void *) {
void __cxa_finalize(void *dso) {
if (!dso) {
call_exit_callbacks(atexit_callbacks);
+#ifdef LIBC_USE_MALLOC_THREAD_CLEANUP
+ if (_malloc_thread_cleanup)
+ _malloc_thread_cleanup();
+#endif
if (teardown_main_tls)
teardown_main_tls();
}
diff --git a/libc/src/stdlib/snmalloc/CMakeLists.txt b/libc/src/stdlib/snmalloc/CMakeLists.txt
index e360b36f5fb3ad..b980738abb750f 100644
--- a/libc/src/stdlib/snmalloc/CMakeLists.txt
+++ b/libc/src/stdlib/snmalloc/CMakeLists.txt
@@ -17,11 +17,6 @@ target_compile_options(
-Wno-extra-semi
-Wno-unused-command-line-argument
-Wno-ctad-maybe-unsupported
- # TODO: define this
- -DSTDERR_FILENO=2
- -DSNMALLOC_USE_PTHREAD_DESTRUCTORS
- # include_directories does not propagate, use options instead
- -include ${CMAKE_CURRENT_SOURCE_DIR}/override.h
-isystem ${COMPILER_RESOURCE_DIR}/include
-isystem ${LIBC_INCLUDE_DIR}
)
diff --git a/libc/src/stdlib/snmalloc/aligned_alloc.cpp b/libc/src/stdlib/snmalloc/aligned_alloc.cpp
index ee1d74ca9c778c..7e209c170d6133 100644
--- a/libc/src/stdlib/snmalloc/aligned_alloc.cpp
+++ b/libc/src/stdlib/snmalloc/aligned_alloc.cpp
@@ -6,9 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#include "src/stdlib/aligned_alloc.h"
+#include "src/stdlib/snmalloc/override.h"
+
#include "snmalloc/snmalloc.h"
#include "src/__support/common.h"
+#include "src/stdlib/aligned_alloc.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(void *, aligned_alloc, (size_t alignment, size_t size)) {
diff --git a/libc/src/stdlib/snmalloc/calloc.cpp b/libc/src/stdlib/snmalloc/calloc.cpp
index 39af67607bf709..7bac3f6b1b0e6c 100644
--- a/libc/src/stdlib/snmalloc/calloc.cpp
+++ b/libc/src/stdlib/snmalloc/calloc.cpp
@@ -6,9 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#include "src/stdlib/calloc.h"
+#include "src/stdlib/snmalloc/override.h"
+
#include "snmalloc/snmalloc.h"
#include "src/__support/common.h"
+#include "src/stdlib/calloc.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(void *, calloc, (size_t num, size_t size)) {
diff --git a/libc/src/stdlib/snmalloc/free.cpp b/libc/src/stdlib/snmalloc/free.cpp
index eb403710fffada..fa8f94f73a563f 100644
--- a/libc/src/stdlib/snmalloc/free.cpp
+++ b/libc/src/stdlib/snmalloc/free.cpp
@@ -6,9 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#include "src/stdlib/free.h"
+#include "src/stdlib/snmalloc/override.h"
+
#include "snmalloc/snmalloc.h"
#include "src/__support/common.h"
+#include "src/stdlib/free.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(void, free, (void *ptr)) {
diff --git a/libc/src/stdlib/snmalloc/malloc.cpp b/libc/src/stdlib/snmalloc/malloc.cpp
index ab58e63743016a..ff4352687ed0d1 100644
--- a/libc/src/stdlib/snmalloc/malloc.cpp
+++ b/libc/src/stdlib/snmalloc/malloc.cpp
@@ -6,9 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#include "src/stdlib/malloc.h"
+#include "src/stdlib/snmalloc/override.h"
+
#include "snmalloc/snmalloc.h"
#include "src/__support/common.h"
+#include "src/stdlib/malloc.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(void *, malloc, (size_t size)) {
diff --git a/libc/src/stdlib/snmalloc/override.h b/libc/src/stdlib/snmalloc/override.h
index a36a6316790fbd..50f26f8b203866 100644
--- a/libc/src/stdlib/snmalloc/override.h
+++ b/libc/src/stdlib/snmalloc/override.h
@@ -26,6 +26,10 @@
// We are building internally anyway, hence noexcept does not matter here
#define __NOEXCEPT
+// TODO: define this in stdio.h
+#define STDERR_FILENO 2
+#define SNMALLOC_USE_THREAD_CLEANUP
+
// Enforce internal errno implementation
#include "hdr/errno_macros.h"
#include "src/errno/libc_errno.h"
diff --git a/libc/src/stdlib/snmalloc/realloc.cpp b/libc/src/stdlib/snmalloc/realloc.cpp
index 36972e0a2232ec..bdafc2d0cc7590 100644
--- a/libc/src/stdlib/snmalloc/realloc.cpp
+++ b/libc/src/stdlib/snmalloc/realloc.cpp
@@ -6,9 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#include "src/stdlib/realloc.h"
+#include "src/stdlib/snmalloc/override.h"
+
#include "snmalloc/snmalloc.h"
#include "src/__support/common.h"
+#include "src/stdlib/realloc.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(void *, realloc, (void *ptr, size_t size)) {
>From 040503e2a27bd3ca6a7c7f5fc8b5f3f0e454563a Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <i at zhuyi.fan>
Date: Sun, 19 Jan 2025 10:00:12 +0000
Subject: [PATCH 07/10] minor cleanup
---
libc/src/stdlib/snmalloc/CMakeLists.txt | 4 ----
1 file changed, 4 deletions(-)
diff --git a/libc/src/stdlib/snmalloc/CMakeLists.txt b/libc/src/stdlib/snmalloc/CMakeLists.txt
index b980738abb750f..08616267bb2b96 100644
--- a/libc/src/stdlib/snmalloc/CMakeLists.txt
+++ b/libc/src/stdlib/snmalloc/CMakeLists.txt
@@ -28,7 +28,6 @@ set(SNMALLOC_DEPS
libc.include.errno
libc.include.fcntl
libc.include.limits
- libc.include.pthread
libc.include.stdio
libc.include.stdint
libc.include.stdlib
@@ -43,10 +42,7 @@ set(SNMALLOC_DEPS
# symbols
libc.src.errno.errno
libc.src.fcntl.open
- libc.src.pthread.pthread_key_create
- libc.src.pthread.pthread_setspecific
libc.src.stdlib.abort
- libc.src.stdlib.atexit
libc.src.string.memset
libc.src.string.strlen
libc.src.sys.mman.madvise
>From d505a358b7e8f092abdb94d06b85927075c31359 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <i at zhuyi.fan>
Date: Sun, 26 Jan 2025 12:40:08 +0000
Subject: [PATCH 08/10] address code related reviews
---
libc/src/__support/threads/linux/CMakeLists.txt | 2 +-
libc/src/stdlib/CMakeLists.txt | 6 +++---
libc/src/stdlib/snmalloc/CMakeLists.txt | 2 +-
libc/test/src/stdlib/CMakeLists.txt | 2 +-
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/libc/src/__support/threads/linux/CMakeLists.txt b/libc/src/__support/threads/linux/CMakeLists.txt
index 74dfef3d150736..80a060428d86b2 100644
--- a/libc/src/__support/threads/linux/CMakeLists.txt
+++ b/libc/src/__support/threads/linux/CMakeLists.txt
@@ -71,7 +71,7 @@ add_header_library(
libc.src.__support.threads.mutex_common
)
-if (NOT "${LLVM_LIBC_INCLUDE_SNMALLOC}" STREQUAL "")
+if (NOT "${LIBC_INCLUDE_SNMALLOC}" STREQUAL "")
set (libc_malloc_thread_cleanup_flag "-DLIBC_USE_MALLOC_THREAD_CLEANUP")
endif()
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index db7873a537a99a..7012d1b5ab4ac3 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -324,8 +324,8 @@ add_entrypoint_object(
)
if(NOT LIBC_TARGET_OS_IS_BAREMETAL AND NOT LIBC_TARGET_OS_IS_GPU)
- if (NOT "${LLVM_LIBC_INCLUDE_SNMALLOC}" STREQUAL "")
- message(STATUS "Including snmalloc as the allocator, source directory: ${LLVM_LIBC_INCLUDE_SNMALLOC}")
+ if (NOT "${LIBC_INCLUDE_SNMALLOC}" STREQUAL "")
+ message(STATUS "Including snmalloc as the allocator, source directory: ${LIBC_INCLUDE_SNMALLOC}")
if (NOT LLVM_LIBC_FULL_BUILD)
message(FATAL_ERROR "Snmalloc can only be included when fullbuild mode is enabled")
endif()
@@ -598,7 +598,7 @@ add_header_library(
)
endif()
-if (NOT "${LLVM_LIBC_INCLUDE_SNMALLOC}" STREQUAL "")
+if (NOT "${LIBC_INCLUDE_SNMALLOC}" STREQUAL "")
set (libc_malloc_thread_cleanup_flag "-DLIBC_USE_MALLOC_THREAD_CLEANUP")
endif()
diff --git a/libc/src/stdlib/snmalloc/CMakeLists.txt b/libc/src/stdlib/snmalloc/CMakeLists.txt
index 08616267bb2b96..7632ffa17036da 100644
--- a/libc/src/stdlib/snmalloc/CMakeLists.txt
+++ b/libc/src/stdlib/snmalloc/CMakeLists.txt
@@ -6,7 +6,7 @@ set(SNMALLOC_HEADER_ONLY_LIBRARY ON CACHE BOOL "use snmalloc as header only libr
macro (install)
endmacro ()
-add_subdirectory(${LLVM_LIBC_INCLUDE_SNMALLOC} ${CMAKE_CURRENT_BINARY_DIR}/snmalloc EXCLUDE_FROM_ALL)
+add_subdirectory(${LIBC_INCLUDE_SNMALLOC} ${CMAKE_CURRENT_BINARY_DIR}/snmalloc EXCLUDE_FROM_ALL)
target_compile_options(
snmalloc
diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt
index ce050b0286641a..ca43228e89ea72 100644
--- a/libc/test/src/stdlib/CMakeLists.txt
+++ b/libc/test/src/stdlib/CMakeLists.txt
@@ -423,7 +423,7 @@ if(LLVM_LIBC_FULL_BUILD)
# implementation.
if(LIBC_TARGET_OS_IS_BAREMETAL
OR (LIBC_TARGET_OS_IS_GPU AND NOT LIBC_TARGET_ARCHITECTURE_IS_NVPTX)
- OR NOT "${LLVM_LIBC_INCLUDE_SNMALLOC}")
+ OR NOT "${LIBC_INCLUDE_SNMALLOC}" STREQUAL "")
add_libc_test(
malloc_test
HERMETIC_TEST_ONLY
>From 655d5b14ab91a0fcc4ebc69a1d0888dc88387b99 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <i at zhuyi.fan>
Date: Sun, 26 Jan 2025 12:56:05 +0000
Subject: [PATCH 09/10] add doc
---
libc/docs/full_host_build.rst | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/libc/docs/full_host_build.rst b/libc/docs/full_host_build.rst
index 12aacf181695a9..298c520631956a 100644
--- a/libc/docs/full_host_build.rst
+++ b/libc/docs/full_host_build.rst
@@ -140,6 +140,30 @@ allocator for LLVM-libc.
-DCLANG_DEFAULT_RTLIB=compiler-rt \
-DCMAKE_INSTALL_PREFIX=$SYSROOT
+Libc can optionally use `SnMalloc <https://github.com/microsoft/snmalloc>`_ as its
+allocator implementation. ``SnMalloc`` is a modern allocator implementation with excellent
+multicore performance. Please refer to ``SnMalloc``'s repositories for more information.
+
+To setup ``SnMalloc``, use the following ``cmake`` configuration instead:
+
+.. code-block:: sh
+ $> git clone https://github.com/microsoft/snmalloc
+ $> export SNMALLOC_DIR=$(realpath snmalloc)
+ $> cd /path/to/llvm-project
+ $> cmake -S runtimes \
+ -B build \
+ -G Ninja \
+ -DCMAKE_C_COMPILER=clang \
+ -DCMAKE_CXX_COMPILER=clang++ \
+ -DLLVM_ENABLE_RUNTIMES="libc" \
+ -DLLVM_LIBC_FULL_BUILD=ON \
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo \
+ -DLLVM_LIBC_INCLUDE_SNMALLOC="$SNMALLOC_DIR"
+
+.. note::
+ LLVM's libc does not vendor ``SnMalloc``. The commit known to work is
+ ``e3e558472de805b2408e2ee24a055ef0b7c38423``.
+
Build and install
=================
>From 4a7f3070322423b94b8f9ed82d8f5b4c872d420d Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <i at zhuyi.fan>
Date: Mon, 27 Jan 2025 01:19:22 +0000
Subject: [PATCH 10/10] fix doc build
---
libc/docs/full_host_build.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/libc/docs/full_host_build.rst b/libc/docs/full_host_build.rst
index 298c520631956a..923f5fbae31880 100644
--- a/libc/docs/full_host_build.rst
+++ b/libc/docs/full_host_build.rst
@@ -147,6 +147,7 @@ multicore performance. Please refer to ``SnMalloc``'s repositories for more info
To setup ``SnMalloc``, use the following ``cmake`` configuration instead:
.. code-block:: sh
+
$> git clone https://github.com/microsoft/snmalloc
$> export SNMALLOC_DIR=$(realpath snmalloc)
$> cd /path/to/llvm-project
More information about the libc-commits
mailing list