[PATCH v1 RFC liburing 2/6] Add no libc support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Create `src/no_libc.c` to substitute libc functions like `memset()`,
`malloc()` and `free()`. Only build this file when we build liburing
without libc.

Wrap libc functions with `static inline` functions, defined in
`src/lib.h`, currently we have:
 1) `get_page_size`
 2) `uring_memset`
 3) `uring_malloc`
 4) `uring_free`

Extra notes for tests:
 1) Functions in `src/syscall.c` require libc to work.
 2) Tests require functions in `src/syscall.c`.

So we build `src/syscall.c` manually from test's Makefile.

The Makefile in `src/` dir still builds `src/syscall.c` when we
compile liburing with libc.

Cc: Bedirhan KURT <windowz414@xxxxxxxxxxx>
Cc: Louvian Lyndal <louvianlyndal@xxxxxxxxx>
Link: https://github.com/axboe/liburing/issues/443
Signed-off-by: Ammar Faizi <ammar.faizi@xxxxxxxxxxxxxxxxxxxxx>
---
 src/Makefile   | 13 +++++++++-
 src/lib.h      | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/no_libc.c  | 48 +++++++++++++++++++++++++++++++++++
 src/queue.c    |  1 +
 src/register.c |  1 +
 src/setup.c    | 16 +++++-------
 src/syscall.c  | 11 +++++++-
 test/Makefile  | 23 ++++++++++++++---
 8 files changed, 167 insertions(+), 15 deletions(-)
 create mode 100644 src/lib.h
 create mode 100644 src/no_libc.c

diff --git a/src/Makefile b/src/Makefile
index 5e46a9d..3ca2ac7 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -32,11 +32,22 @@ endif
 
 all: $(all_targets)
 
-liburing_srcs := setup.c queue.c syscall.c register.c
+liburing_srcs := setup.c queue.c register.c
+
+ifeq ($(LIBURING_NOLIBC),y)
+	liburing_srcs += no_libc.c
+	override CFLAGS += -nostdlib -nolibc -nodefaultlibs -ffreestanding -fno-stack-protector -fpic
+	override CPPFLAGS += -nostdlib -nolibc -nodefaultlibs -ffreestanding -fno-stack-protector -fpic
+	override LINK_FLAGS += -nostdlib -nolibc -nodefaultlibs -fpic
+else
+	liburing_srcs += syscall.c
+endif
 
 liburing_objs := $(patsubst %.c,%.ol,$(liburing_srcs))
 liburing_sobjs := $(patsubst %.c,%.os,$(liburing_srcs))
 
+$(liburing_srcs): syscall.h lib.h
+
 $(liburing_objs) $(liburing_sobjs): include/liburing/io_uring.h
 
 %.os: %.c
diff --git a/src/lib.h b/src/lib.h
new file mode 100644
index 0000000..171eee7
--- /dev/null
+++ b/src/lib.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef LIBURING_LIB_H
+#define LIBURING_LIB_H
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef offsetof
+# define offsetof(TYPE, FIELD) ((size_t) &((TYPE *)0)->FIELD)
+#endif
+
+#ifndef container_of
+# define container_of(PTR, TYPE, FIELD) ({				\
+	__typeof__(((TYPE *)0)->FIELD) *__FIELD_PTR = (PTR);		\
+	(TYPE *)((char *) __FIELD_PTR - offsetof(TYPE, FIELD));		\
+})
+#endif
+
+
+static inline long get_page_size(void)
+{
+#ifdef LIBURING_NOLIBC
+	return __arch_impl_get_page_size();
+#else
+	long page_size;
+
+	page_size = sysconf(_SC_PAGESIZE);
+	if (page_size < 0)
+		page_size = 4096;
+
+	return page_size;
+#endif
+}
+
+void *__uring_memset(void *s, int c, size_t n);
+
+static inline void *uring_memset(void *s, int c, size_t n)
+{
+#ifdef LIBURING_NOLIBC
+	return __uring_memset(s, c, n);
+#else
+	return memset(s, c, n);
+#endif
+}
+
+void *__uring_malloc(size_t len);
+
+static inline void *uring_malloc(size_t len)
+{
+#ifdef LIBURING_NOLIBC
+	return __uring_malloc(len);
+#else
+	return malloc(len);
+#endif
+}
+
+void __uring_free(void *p);
+
+static inline void uring_free(void *p)
+{
+#ifdef LIBURING_NOLIBC
+	__uring_free(p);
+#else
+	free(p);
+#endif
+}
+
+#endif /* #ifndef LIBURING_LIB_H */
diff --git a/src/no_libc.c b/src/no_libc.c
new file mode 100644
index 0000000..149426c
--- /dev/null
+++ b/src/no_libc.c
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: MIT */
+
+#ifndef LIBURING_NOLIBC
+# error "This file should only be compiled for no libc build"
+#endif
+
+#include "lib.h"
+#include "syscall.h"
+
+void *__uring_memset(void *s, int c, size_t n)
+{
+	size_t i;
+	unsigned char *p = s;
+
+	for (i = 0; i < n; i++)
+		p[i] = (unsigned char) c;
+
+	return s;
+}
+
+struct uring_heap {
+	size_t		len;
+	char		user_p[];
+};
+
+void *__uring_malloc(size_t len)
+{
+	struct uring_heap *heap;
+
+	heap = uring_mmap(NULL, sizeof(*heap) + len, PROT_READ | PROT_WRITE,
+			  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+	if (IS_ERR(heap))
+		return NULL;
+
+	heap->len = sizeof(*heap) + len;
+	return heap->user_p;
+}
+
+void __uring_free(void *p)
+{
+	struct uring_heap *heap;
+
+	if (uring_unlikely(!p))
+		return;
+
+	heap = container_of(p, struct uring_heap, user_p);
+	uring_munmap(heap, heap->len);
+}
diff --git a/src/queue.c b/src/queue.c
index 9af29d5..cd76048 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -13,6 +13,7 @@
 #include "liburing.h"
 #include "liburing/barrier.h"
 
+#include "lib.h"
 #include "syscall.h"
 
 /*
diff --git a/src/register.c b/src/register.c
index 074223f..f8e88cf 100644
--- a/src/register.c
+++ b/src/register.c
@@ -12,6 +12,7 @@
 #include "liburing/io_uring.h"
 #include "liburing.h"
 
+#include "lib.h"
 #include "syscall.h"
 
 int io_uring_register_buffers_update_tag(struct io_uring *ring, unsigned off,
diff --git a/src/setup.c b/src/setup.c
index 4f006de..0f64a35 100644
--- a/src/setup.c
+++ b/src/setup.c
@@ -12,6 +12,7 @@
 #include "liburing/io_uring.h"
 #include "liburing.h"
 
+#include "lib.h"
 #include "syscall.h"
 
 static void io_uring_unmap_rings(struct io_uring_sq *sq, struct io_uring_cq *cq)
@@ -161,7 +162,7 @@ int io_uring_queue_init(unsigned entries, struct io_uring *ring, unsigned flags)
 {
 	struct io_uring_params p;
 
-	memset(&p, 0, sizeof(p));
+	uring_memset(&p, 0, sizeof(p));
 	p.flags = flags;
 
 	return io_uring_queue_init_params(entries, ring, &p);
@@ -184,16 +185,16 @@ struct io_uring_probe *io_uring_get_probe_ring(struct io_uring *ring)
 	int r;
 
 	len = sizeof(*probe) + 256 * sizeof(struct io_uring_probe_op);
-	probe = malloc(len);
+	probe = uring_malloc(len);
 	if (!probe)
 		return NULL;
-	memset(probe, 0, len);
+	uring_memset(probe, 0, len);
 
 	r = io_uring_register_probe(ring, probe, 256);
 	if (r >= 0)
 		return probe;
 
-	free(probe);
+	uring_free(probe);
 	return NULL;
 }
 
@@ -214,7 +215,7 @@ struct io_uring_probe *io_uring_get_probe(void)
 
 void io_uring_free_probe(struct io_uring_probe *probe)
 {
-	free(probe);
+	uring_free(probe);
 }
 
 static int __fls(int x)
@@ -336,10 +337,7 @@ ssize_t io_uring_mlock_size_params(unsigned entries, struct io_uring_params *p)
 		cq_entries = 2 * entries;
 	}
 
-	page_size = sysconf(_SC_PAGESIZE);
-	if (page_size < 0)
-		page_size = 4096;
-
+	page_size = get_page_size();
 	return rings_size(entries, cq_entries, page_size);
 }
 
diff --git a/src/syscall.c b/src/syscall.c
index 5923fbb..cfb3ee2 100644
--- a/src/syscall.c
+++ b/src/syscall.c
@@ -1,6 +1,16 @@
 /* SPDX-License-Identifier: MIT */
 #define _DEFAULT_SOURCE
 
+/*
+ * Functions in this file require libc, only build them when we use libc.
+ *
+ * Note:
+ * liburing's tests still need these functions.
+ */
+#if defined(LIBURING_NOLIBC) && !defined(LIBURING_BUILD_TEST)
+# error "This file should only be compiled for libc build"
+#endif
+
 /*
  * Will go away once libc support is there
  */
@@ -11,7 +21,6 @@
 #include "liburing/io_uring.h"
 #include "syscall.h"
 
-
 int __sys_io_uring_register(int fd, unsigned opcode, const void *arg,
 			    unsigned nr_args)
 {
diff --git a/test/Makefile b/test/Makefile
index 2936469..ddb589b 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -21,8 +21,8 @@ ifdef CONFIG_HAVE_ARRAY_BOUNDS
 endif
 
 CXXFLAGS ?= $(CFLAGS)
-override CFLAGS += $(XCFLAGS)
-override CXXFLAGS += $(XCFLAGS) -std=c++11
+override CFLAGS += $(XCFLAGS) -DLIBURING_BUILD_TEST
+override CXXFLAGS += $(XCFLAGS) -std=c++11 -DLIBURING_BUILD_TEST
 LDFLAGS ?=
 override LDFLAGS += -L../src/ -luring
 
@@ -153,11 +153,26 @@ test_targets += sq-full-cpp
 endif
 all_targets += sq-full-cpp
 
-helpers = helpers.o
+#
+# Note:
+#
+# Build ../src/syscall.c manually from test's Makefile to support
+# build liburing without libc.
+#
+# Functions in ../src/syscall.c require libc to work with, if we
+# build liburing.so without libc, we don't have those functions
+# in liburing.so.
+#
+# This makes the tests can run for liburing.so without libc.
+#
+helpers = helpers.o ../src/syscall.o
 
 all: ${helpers} $(test_targets)
 
-helpers.o: helpers.c helpers.c
+../src/syscall.o: ../src/syscall.c
+	$(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
+
+helpers.o: helpers.c
 	$(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
 
 %: %.c ${helpers} helpers.h
-- 
2.30.2




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux