mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v3 00/16] common: introduce bthreads, co-operative
@ 2021-03-10  8:47 Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 01/16] common: introduce HAS_ARCH_SJLJ Ahmad Fatoum
                   ` (16 more replies)
  0 siblings, 17 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer

Current state of CONFIG_HAS_ARCH_SJLJ

    [x] arm 32-bit (Ahmad)
    [x] arm 64-bit (Sascha)
    [x] mips (Sascha)
    [x] powerpc (Sascha)
    [x] riscv (Sascha)
    [x] sandbox (Ahmad)
    [-] nios2 (Removed; Sascha)
    [x] x86 32-bit (Ahmad)
    [x] x86 64-bit (Ahmad)
    [x] openrisc (Stafford)
    [x] kvx (Jules)

Legend: [-] arch removed, [x] implemented

Changes since v2:
  - Reworked bthread_reschedule(): Threads now always schedule the next
    thread in the runqueue. Simplifies code and saves context switch back
    to scheduler
  - Removed assert_command_context yield. Will need further rework until
    it's usable, so just warn for now like with pollers
  - Added resched() to collect the reschedule bits in one place
  - Migrate LED poller as an example
  - Rework bthread command to use API better
  - Split up commits for shorter, reworked, commit messages
  - Fixed poor English and copy-paste errors (Peter Korsgaard)
  - Marked RISC-V and MIPS CONFIG_HAS_ARCH_SJLJ explicitly 32-bit only
    (Peter Mamonov)
  - Added x86 implementations (tested on EFI x86_64 and i386 sandbox)

Cheers,
Ahmad Fatoum (10):
  common: introduce HAS_ARCH_SJLJ
  ARM: asm: setjmp: annotate setjmp/longjmp for GCC
  ARM: asm: setjmp: implement coroutine dependency initjmp()
  sandbox: asm: implement setjmp/longjmp/initjmp
  x86: implement setjmp/longjmp/initjmp
  common: poller: replace explicit calls to poller_call() with resched()
  console: unconditionally run resched() in ctrlc()
  common: introduce bthreads, co-operative barebox threads
  commands: add new bthread test command
  RFC: led: migrate from poller to bthread

Sascha Hauer (6):
  riscv: Add asm/asm.h
  riscv: Add asm/linkage.h
  riscv: Implement setjmp/longjmp/initjmp for RV32I
  mips: Add linkage.h
  mips: Implement setjmp/longjmp/initjmp for 32BIT
  powerpc: Implement initjmp/setjmp/longjmp

 Documentation/devel/background-execution.rst |  37 +++-
 arch/arm/Kconfig                             |   1 +
 arch/arm/include/asm/setjmp.h                |   6 +-
 arch/arm/lib32/setjmp.S                      |   8 +
 arch/arm/lib64/setjmp.S                      |   9 +
 arch/mips/Kconfig                            |   1 +
 arch/mips/include/asm/linkage.h              |   9 +
 arch/mips/include/asm/setjmp.h               |  32 +++
 arch/mips/lib/Makefile                       |   1 +
 arch/mips/lib/setjmp.S                       |  50 +++++
 arch/powerpc/Kconfig                         |   1 +
 arch/powerpc/include/asm/setjmp.h            |  21 ++
 arch/powerpc/lib/Makefile                    |   2 +-
 arch/powerpc/lib/setjmp.S                    |  86 ++++++++
 arch/riscv/Kconfig                           |   1 +
 arch/riscv/include/asm/asm.h                 |  69 ++++++
 arch/riscv/include/asm/linkage.h             |  12 ++
 arch/riscv/include/asm/setjmp.h              |  27 +++
 arch/riscv/lib/Makefile                      |   1 +
 arch/riscv/lib/longjmp.S                     |  28 +++
 arch/riscv/lib/setjmp.S                      |  35 +++
 arch/sandbox/Kconfig                         |   1 +
 arch/sandbox/Makefile                        |   5 +-
 arch/sandbox/include/asm/setjmp.h            |  17 ++
 arch/sandbox/os/Makefile                     |   5 +-
 arch/sandbox/os/setjmp.c                     | 180 ++++++++++++++++
 arch/x86/Kconfig                             |   2 +
 arch/x86/include/asm/setjmp.h                |  44 ++++
 arch/x86/lib/Makefile                        |   3 +
 arch/x86/lib/setjmp_32.S                     |  60 ++++++
 arch/x86/lib/setjmp_64.S                     |  60 ++++++
 commands/Kconfig                             |   9 +
 commands/Makefile                            |   1 +
 commands/bthread.c                           | 195 +++++++++++++++++
 common/Kconfig                               |  13 ++
 common/Makefile                              |   1 +
 common/bthread.c                             | 214 +++++++++++++++++++
 common/clock.c                               |   4 +-
 common/console.c                             |   6 +-
 drivers/led/core.c                           |  52 ++---
 include/bthread.h                            |  53 +++++
 include/poller.h                             |   2 +
 include/sched.h                              |  15 ++
 include/slice.h                              |  17 +-
 lib/readline.c                               |   4 +-
 45 files changed, 1349 insertions(+), 51 deletions(-)
 create mode 100644 arch/mips/include/asm/linkage.h
 create mode 100644 arch/mips/include/asm/setjmp.h
 create mode 100644 arch/mips/lib/setjmp.S
 create mode 100644 arch/powerpc/include/asm/setjmp.h
 create mode 100644 arch/powerpc/lib/setjmp.S
 create mode 100644 arch/riscv/include/asm/asm.h
 create mode 100644 arch/riscv/include/asm/linkage.h
 create mode 100644 arch/riscv/include/asm/setjmp.h
 create mode 100644 arch/riscv/lib/longjmp.S
 create mode 100644 arch/riscv/lib/setjmp.S
 create mode 100644 arch/sandbox/include/asm/setjmp.h
 create mode 100644 arch/sandbox/os/setjmp.c
 create mode 100644 arch/x86/include/asm/setjmp.h
 create mode 100644 arch/x86/lib/setjmp_32.S
 create mode 100644 arch/x86/lib/setjmp_64.S
 create mode 100644 commands/bthread.c
 create mode 100644 common/bthread.c
 create mode 100644 include/bthread.h
 create mode 100644 include/sched.h

-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 01/16] common: introduce HAS_ARCH_SJLJ
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 02/16] ARM: asm: setjmp: annotate setjmp/longjmp for GCC Ahmad Fatoum
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer

From: Ahmad Fatoum <ahmad@a3f.at>

setjmp stores the registers comprising the execution context into a
jmp_buf and longjmp switches to that context and continues execution just
after the setjmp that allocated that jmp_buf.

setjmp/longjmp can have multiple uses:

  - Handle return from firmware that clobbers registers. This is why we
    already have a setjmp/longjmp ARM

  - Do exception handling[1]

  - Port over scripting language VMs that use sjlj for context switching

  - Implement stackless coroutines in C.

These coroutines would be stackless, because jumping to a setjmp down the
call stack means that the code there will clobber the stack below it.
On resuming the coroutine, it will run with a stack changed in the
interim leading to undefined behavior.

There are ways around that without resorting to custom Assembly:

  - Allocate a buffer on the scheduler's stack, so coroutine can
    grow into them
     -> Problem: exploits Undefined behavior

  - Yield first time on scheduler stack, then patch jmp_buf to point at
    another stack
     -> Problem: Code switching stacks should not itself use the stack

  - Construct a new jmp_buf with user-supplied return address and stack top:
    int initjmp(jmp_buf jmp, void __noreturn (*func)(void), void *stack_top);

The latter could also be reused as a portable way of setting up a stack
in early init code.

We are going to implement green threads in later commits, so add a
symbol that can be selected to indicate architecture support for setjmp,
longjmp and the new initjmp.

[1]: https://www.spinics.net/lists/u-boot-v2/msg41322.html

Signed-off-by: Ahmad Fatoum <ahmad@a3f.at>
---
 common/Kconfig | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/common/Kconfig b/common/Kconfig
index edadcc9f4979..c0ff57bcdba4 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -28,6 +28,11 @@ config HAS_DMA
 	  Drivers that depend on a DMA implementation can depend on this
 	  config, so that you don't get a compilation error.
 
+config HAS_ARCH_SJLJ
+	bool
+	help
+	  Architecture has support implemented for setjmp()/longjmp()/initjmp()
+
 config GENERIC_GPIO
 	bool
 
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 02/16] ARM: asm: setjmp: annotate setjmp/longjmp for GCC
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 01/16] common: introduce HAS_ARCH_SJLJ Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 03/16] ARM: asm: setjmp: implement coroutine dependency initjmp() Ahmad Fatoum
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer, Ahmad Fatoum

To avoid invalid optimizations and to enable warnings, GCC must be told
that setjmp and longjmp are to be handled specially. Add the missing
attributes.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/include/asm/setjmp.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/setjmp.h b/arch/arm/include/asm/setjmp.h
index 62bac613d6e1..538d9cd50651 100644
--- a/arch/arm/include/asm/setjmp.h
+++ b/arch/arm/include/asm/setjmp.h
@@ -23,7 +23,7 @@ struct jmp_buf_data {
 
 typedef struct jmp_buf_data jmp_buf[1];
 
-int setjmp(jmp_buf jmp);
-void longjmp(jmp_buf jmp, int ret);
+int setjmp(jmp_buf jmp) __attribute__((returns_twice));
+void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
 
 #endif /* _SETJMP_H_ */
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 03/16] ARM: asm: setjmp: implement coroutine dependency initjmp()
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 01/16] common: introduce HAS_ARCH_SJLJ Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 02/16] ARM: asm: setjmp: annotate setjmp/longjmp for GCC Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 04/16] sandbox: asm: implement setjmp/longjmp/initjmp Ahmad Fatoum
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer, Ahmad Fatoum

Implement initjmp() for use with the incoming bthread support.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/Kconfig              | 1 +
 arch/arm/include/asm/setjmp.h | 2 ++
 arch/arm/lib32/setjmp.S       | 8 ++++++++
 arch/arm/lib64/setjmp.S       | 9 +++++++++
 4 files changed, 20 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ab0bf030131c..cdb934136e34 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -5,6 +5,7 @@ config ARM
 	select HAVE_CONFIGURABLE_TEXT_BASE if !RELOCATABLE
 	select HAVE_IMAGE_COMPRESSION
 	select HAVE_ARCH_KASAN
+	select HAS_ARCH_SJLJ
 	select ARM_OPTIMZED_STRING_FUNCTIONS if KASAN
 	default y
 
diff --git a/arch/arm/include/asm/setjmp.h b/arch/arm/include/asm/setjmp.h
index 538d9cd50651..4877e4312411 100644
--- a/arch/arm/include/asm/setjmp.h
+++ b/arch/arm/include/asm/setjmp.h
@@ -26,4 +26,6 @@ typedef struct jmp_buf_data jmp_buf[1];
 int setjmp(jmp_buf jmp) __attribute__((returns_twice));
 void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
 
+int initjmp(jmp_buf jmp, void __noreturn (*func)(void), void *stack_top);
+
 #endif /* _SETJMP_H_ */
diff --git a/arch/arm/lib32/setjmp.S b/arch/arm/lib32/setjmp.S
index f0606a7f6659..626d915da183 100644
--- a/arch/arm/lib32/setjmp.S
+++ b/arch/arm/lib32/setjmp.S
@@ -33,4 +33,12 @@ ENTRY(longjmp)
 1:
 	bx   lr
 ENDPROC(longjmp)
+
+.pushsection .text.initjmp, "ax"
+ENTRY(initjmp)
+	str  a3, [a1, #32] /* stack pointer */
+	str  a2, [a1, #36] /* return address */
+	mov  a1, #0
+	bx   lr
+ENDPROC(initjmp)
 .popsection
diff --git a/arch/arm/lib64/setjmp.S b/arch/arm/lib64/setjmp.S
index 0910e2f5a6c3..80be8cb0f201 100644
--- a/arch/arm/lib64/setjmp.S
+++ b/arch/arm/lib64/setjmp.S
@@ -36,3 +36,12 @@ ENTRY(longjmp)
 	ret
 ENDPROC(longjmp)
 .popsection
+
+.pushsection .text.initjmp, "ax"
+ENTRY(initjmp)
+	str  x2, [x0, #96] /* stack pointer */
+	str  x1, [x0, #88] /* return address */
+	mov  x0, #0
+	ret
+ENDPROC(initjmp)
+.popsection
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 04/16] sandbox: asm: implement setjmp/longjmp/initjmp
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (2 preceding siblings ...)
  2021-03-10  8:47 ` [PATCH v3 03/16] ARM: asm: setjmp: implement coroutine dependency initjmp() Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 05/16] riscv: Add asm/asm.h Ahmad Fatoum
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer, Ahmad Fatoum

To extend incoming bthread support to sandbox, implement setjmp, longjmp
and initjmp. Unlike bare metal platforms, setjmp() and longjmp() are
readily provided on standard-conforming hosted platforms.  initjmp() on
the other hand requires us to be able to invoke a function with a
user-supplied stack pointer, which isn't possible in standard C.

For POSIX systems, there are two methods to portably achieve this though:

  - Use makecontext(2) to set up a new context. makecontext(2) was however
    removed in POSIX.1-2008 and at least GCC 10.2.1 ASan complains that it
    "doesn't fully support makecontext/swapcontext functions and may
    produce false positives in some cases!"

  - Use sigaltstack to set a new signal stack, raise the signal call,
    setjmp in the signal handler to store the new stack pointer, return
    regularly from signal handler and then longjmp back

Both methods are implemented in QEMU. While QEMU uses the makecontext
method by default, for the reasons described, import the second implementation
and use it implement initjmp.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/sandbox/Kconfig              |   1 +
 arch/sandbox/Makefile             |   5 +-
 arch/sandbox/include/asm/setjmp.h |  17 +++
 arch/sandbox/os/Makefile          |   5 +-
 arch/sandbox/os/setjmp.c          | 180 ++++++++++++++++++++++++++++++
 5 files changed, 204 insertions(+), 4 deletions(-)
 create mode 100644 arch/sandbox/include/asm/setjmp.h
 create mode 100644 arch/sandbox/os/setjmp.c

diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 1a4e3bacf66d..cef8e9fb7ab4 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -13,6 +13,7 @@ config SANDBOX
 	select PARTITION_DISK
 	select ARCH_HAS_STACK_DUMP if ASAN
 	select GENERIC_FIND_NEXT_BIT
+	select HAS_ARCH_SJLJ
 	default y
 
 config ARCH_TEXT_BASE
diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile
index ea594944e4eb..5fc7e227be67 100644
--- a/arch/sandbox/Makefile
+++ b/arch/sandbox/Makefile
@@ -27,7 +27,8 @@ KBUILD_CFLAGS += -Dmalloc=barebox_malloc -Dcalloc=barebox_calloc \
 		-Dftruncate=barebox_ftruncate -Dasprintf=barebox_asprintf \
 		-Dopendir=barebox_opendir -Dreaddir=barebox_readdir \
 		-Dclosedir=barebox_closedir -Dreadlink=barebox_readlink \
-		-Doptarg=barebox_optarg -Doptind=barebox_optind
+		-Doptarg=barebox_optarg -Doptind=barebox_optind \
+		-Dsetjmp=barebox_setjmp -Dlongjmp=barebox_longjmp
 
 machdirs := $(patsubst %,arch/sandbox/mach-%/,$(machine-y))
 
@@ -64,7 +65,7 @@ endif
 BAREBOX_LDFLAGS += \
 	-Wl,-T,$(BAREBOX_LDS) \
 	-Wl,--whole-archive $(BAREBOX_OBJS) -Wl,--no-whole-archive \
-	-lrt $(SDL_LIBS) $(FTDI1_LIBS) \
+	-lrt -pthread $(SDL_LIBS) $(FTDI1_LIBS) \
 	$(SANITIZER_LIBS)
 
 cmd_barebox__ = $(CC) -o $@ $(BAREBOX_LDFLAGS)
diff --git a/arch/sandbox/include/asm/setjmp.h b/arch/sandbox/include/asm/setjmp.h
new file mode 100644
index 000000000000..f085a9079dd7
--- /dev/null
+++ b/arch/sandbox/include/asm/setjmp.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __SETJMP_H_
+#define __SETJMP_H_
+
+struct jmp_buf_data {
+	unsigned char opaque[512] __aligned(16);
+};
+
+typedef struct jmp_buf_data jmp_buf[1];
+
+int setjmp(jmp_buf jmp) __attribute__((returns_twice));
+void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
+
+int initjmp(jmp_buf jmp, void __noreturn (*func)(void), void *stack_top);
+
+#endif
diff --git a/arch/sandbox/os/Makefile b/arch/sandbox/os/Makefile
index fb2c3cfd8632..5d0c938ce68c 100644
--- a/arch/sandbox/os/Makefile
+++ b/arch/sandbox/os/Makefile
@@ -4,7 +4,8 @@ machdirs := $(patsubst %,arch/sandbox/mach-%/,$(machine-y))
 
 KBUILD_CPPFLAGS = $(patsubst %,-I$(srctree)/%include,$(machdirs))
 
-KBUILD_CPPFLAGS += -DCONFIG_MALLOC_SIZE=$(CONFIG_MALLOC_SIZE) -D_FILE_OFFSET_BITS=64
+KBUILD_CPPFLAGS += -DCONFIG_MALLOC_SIZE=$(CONFIG_MALLOC_SIZE) -D_FILE_OFFSET_BITS=64 \
+		   -DCONFIG_STACK_SIZE=$(CONFIG_STACK_SIZE)
 
 KBUILD_CFLAGS := -Wall
 
@@ -14,7 +15,7 @@ ifeq ($(CONFIG_SANDBOX_LINUX_I386),y)
 KBUILD_CFLAGS += -m32
 endif
 
-obj-y = common.o tap.o
+obj-y = common.o tap.o setjmp.o
 obj-$(CONFIG_MALLOC_LIBC) += libc_malloc.o
 
 CFLAGS_sdl.o = $(shell pkg-config sdl2 --cflags)
diff --git a/arch/sandbox/os/setjmp.c b/arch/sandbox/os/setjmp.c
new file mode 100644
index 000000000000..7f686b0fc6e9
--- /dev/null
+++ b/arch/sandbox/os/setjmp.c
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * sigaltstack coroutine initialization code
+ *
+ * Copyright (C) 2006  Anthony Liguori <anthony@codemonkey.ws>
+ * Copyright (C) 2011  Kevin Wolf <kwolf@redhat.com>
+ * Copyright (C) 2012  Alex Barcelo <abarcelo@ac.upc.edu>
+ * Copyright (C) 2021  Ahmad Fatoum, Pengutronix
+ * This file is partly based on pth_mctx.c, from the GNU Portable Threads
+ *  Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com>
+ */
+
+/* XXX Is there a nicer way to disable glibc's stack check for longjmp? */
+#ifdef _FORTIFY_SOURCE
+#undef _FORTIFY_SOURCE
+#endif
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <signal.h>
+
+typedef sigjmp_buf _jmp_buf __attribute__((aligned((16))));
+_Static_assert(sizeof(_jmp_buf) <= 512, "sigjmp_buf size exceeds expectation");
+
+/*
+ * Information for the signal handler (trampoline)
+ */
+static struct {
+	_jmp_buf *reenter;
+	void (*entry)(void);
+	volatile sig_atomic_t called;
+} tr_state;
+
+/*
+ * "boot" function
+ * This is what starts the coroutine, is called from the trampoline
+ * (from the signal handler when it is not signal handling, read ahead
+ * for more information).
+ */
+static void __attribute__((noinline, noreturn))
+coroutine_bootstrap(void (*entry)(void))
+{
+	for (;;)
+		entry();
+}
+
+/*
+ * This is used as the signal handler. This is called with the brand new stack
+ * (thanks to sigaltstack). We have to return, given that this is a signal
+ * handler and the sigmask and some other things are changed.
+ */
+static void coroutine_trampoline(int signal)
+{
+	/* Get the thread specific information */
+	tr_state.called = 1;
+
+	/*
+	 * Here we have to do a bit of a ping pong between the caller, given that
+	 * this is a signal handler and we have to do a return "soon". Then the
+	 * caller can reestablish everything and do a siglongjmp here again.
+	 */
+	if (!sigsetjmp(*tr_state.reenter, 0)) {
+		return;
+	}
+
+	/*
+	 * Ok, the caller has siglongjmp'ed back to us, so now prepare
+	 * us for the real machine state switching. We have to jump
+	 * into another function here to get a new stack context for
+	 * the auto variables (which have to be auto-variables
+	 * because the start of the thread happens later). Else with
+	 * PIC (i.e. Position Independent Code which is used when PTH
+	 * is built as a shared library) most platforms would
+	 * horrible core dump as experience showed.
+	 */
+	coroutine_bootstrap(tr_state.entry);
+}
+
+int initjmp(_jmp_buf jmp, void (*func)(void), void *stack_top)
+{
+	struct sigaction sa;
+	struct sigaction osa;
+	stack_t ss;
+	stack_t oss;
+	sigset_t sigs;
+	sigset_t osigs;
+
+	/* The way to manipulate stack is with the sigaltstack function. We
+	 * prepare a stack, with it delivering a signal to ourselves and then
+	 * put sigsetjmp/siglongjmp where needed.
+	 * This has been done keeping coroutine-ucontext (from the QEMU project)
+	 * as a model and with the pth ideas (GNU Portable Threads).
+	 * See coroutine-ucontext for the basics of the coroutines and see
+	 * pth_mctx.c (from the pth project) for the
+	 * sigaltstack way of manipulating stacks.
+	 */
+
+	tr_state.entry = func;
+	tr_state.reenter = (void *)jmp;
+
+	/*
+	 * Preserve the SIGUSR2 signal state, block SIGUSR2,
+	 * and establish our signal handler. The signal will
+	 * later transfer control onto the signal stack.
+	 */
+	sigemptyset(&sigs);
+	sigaddset(&sigs, SIGUSR2);
+	pthread_sigmask(SIG_BLOCK, &sigs, &osigs);
+	sa.sa_handler = coroutine_trampoline;
+	sigfillset(&sa.sa_mask);
+	sa.sa_flags = SA_ONSTACK;
+	if (sigaction(SIGUSR2, &sa, &osa) != 0) {
+		return -1;
+	}
+
+	/*
+	 * Set the new stack.
+	 */
+	ss.ss_sp = stack_top - CONFIG_STACK_SIZE;
+	ss.ss_size = CONFIG_STACK_SIZE;
+	ss.ss_flags = 0;
+	if (sigaltstack(&ss, &oss) < 0) {
+		return -1;
+	}
+
+	/*
+	 * Now transfer control onto the signal stack and set it up.
+	 * It will return immediately via "return" after the sigsetjmp()
+	 * was performed. Be careful here with race conditions.  The
+	 * signal can be delivered the first time sigsuspend() is
+	 * called.
+	 */
+	tr_state.called = 0;
+	pthread_kill(pthread_self(), SIGUSR2);
+	sigfillset(&sigs);
+	sigdelset(&sigs, SIGUSR2);
+	while (!tr_state.called) {
+		sigsuspend(&sigs);
+	}
+
+	/*
+	 * Inform the system that we are back off the signal stack by
+	 * removing the alternative signal stack. Be careful here: It
+	 * first has to be disabled, before it can be removed.
+	 */
+	sigaltstack(NULL, &ss);
+	ss.ss_flags = SS_DISABLE;
+	if (sigaltstack(&ss, NULL) < 0) {
+		return -1;
+	}
+	sigaltstack(NULL, &ss);
+	if (!(oss.ss_flags & SS_DISABLE)) {
+		sigaltstack(&oss, NULL);
+	}
+
+	/*
+	 * Restore the old SIGUSR2 signal handler and mask
+	 */
+	sigaction(SIGUSR2, &osa, NULL);
+	pthread_sigmask(SIG_SETMASK, &osigs, NULL);
+
+	/*
+	 * jmp can now be used to enter the trampoline again, but not as a
+	 * signal handler. Instead it's longjmp'd to directly.
+	 */
+
+	return 0;
+}
+
+int  __attribute__((returns_twice)) barebox_setjmp(_jmp_buf jmp)
+{
+	return sigsetjmp(jmp, 0);
+}
+
+void __attribute((noreturn)) barebox_longjmp(_jmp_buf jmp, int ret)
+{
+	siglongjmp(jmp, ret);
+}
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 05/16] riscv: Add asm/asm.h
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (3 preceding siblings ...)
  2021-03-10  8:47 ` [PATCH v3 04/16] sandbox: asm: implement setjmp/longjmp/initjmp Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 06/16] riscv: Add asm/linkage.h Ahmad Fatoum
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer, Ahmad Fatoum

From: Sascha Hauer <s.hauer@pengutronix.de>

Various definitions for assembly code, taken as-is from Linux.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/riscv/include/asm/asm.h | 69 ++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 arch/riscv/include/asm/asm.h

diff --git a/arch/riscv/include/asm/asm.h b/arch/riscv/include/asm/asm.h
new file mode 100644
index 000000000000..9c992a88d858
--- /dev/null
+++ b/arch/riscv/include/asm/asm.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2015 Regents of the University of California
+ */
+
+#ifndef _ASM_RISCV_ASM_H
+#define _ASM_RISCV_ASM_H
+
+#ifdef __ASSEMBLY__
+#define __ASM_STR(x)	x
+#else
+#define __ASM_STR(x)	#x
+#endif
+
+#if __riscv_xlen == 64
+#define __REG_SEL(a, b)	__ASM_STR(a)
+#elif __riscv_xlen == 32
+#define __REG_SEL(a, b)	__ASM_STR(b)
+#else
+#error "Unexpected __riscv_xlen"
+#endif
+
+#define REG_L		__REG_SEL(ld, lw)
+#define REG_S		__REG_SEL(sd, sw)
+#define REG_SC		__REG_SEL(sc.d, sc.w)
+#define SZREG		__REG_SEL(8, 4)
+#define LGREG		__REG_SEL(3, 2)
+
+#if __SIZEOF_POINTER__ == 8
+#ifdef __ASSEMBLY__
+#define RISCV_PTR		.dword
+#define RISCV_SZPTR		8
+#define RISCV_LGPTR		3
+#else
+#define RISCV_PTR		".dword"
+#define RISCV_SZPTR		"8"
+#define RISCV_LGPTR		"3"
+#endif
+#elif __SIZEOF_POINTER__ == 4
+#ifdef __ASSEMBLY__
+#define RISCV_PTR		.word
+#define RISCV_SZPTR		4
+#define RISCV_LGPTR		2
+#else
+#define RISCV_PTR		".word"
+#define RISCV_SZPTR		"4"
+#define RISCV_LGPTR		"2"
+#endif
+#else
+#error "Unexpected __SIZEOF_POINTER__"
+#endif
+
+#if (__SIZEOF_INT__ == 4)
+#define RISCV_INT		__ASM_STR(.word)
+#define RISCV_SZINT		__ASM_STR(4)
+#define RISCV_LGINT		__ASM_STR(2)
+#else
+#error "Unexpected __SIZEOF_INT__"
+#endif
+
+#if (__SIZEOF_SHORT__ == 2)
+#define RISCV_SHORT		__ASM_STR(.half)
+#define RISCV_SZSHORT		__ASM_STR(2)
+#define RISCV_LGSHORT		__ASM_STR(1)
+#else
+#error "Unexpected __SIZEOF_SHORT__"
+#endif
+
+#endif /* _ASM_RISCV_ASM_H */
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 06/16] riscv: Add asm/linkage.h
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (4 preceding siblings ...)
  2021-03-10  8:47 ` [PATCH v3 05/16] riscv: Add asm/asm.h Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 07/16] riscv: Implement setjmp/longjmp/initjmp for RV32I Ahmad Fatoum
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer, Ahmad Fatoum

From: Sascha Hauer <s.hauer@pengutronix.de>

Needed to include linux/linkage.h on riscv

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/riscv/include/asm/linkage.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 arch/riscv/include/asm/linkage.h

diff --git a/arch/riscv/include/asm/linkage.h b/arch/riscv/include/asm/linkage.h
new file mode 100644
index 000000000000..9e88ba23cd2b
--- /dev/null
+++ b/arch/riscv/include/asm/linkage.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2015 Regents of the University of California
+ */
+
+#ifndef _ASM_RISCV_LINKAGE_H
+#define _ASM_RISCV_LINKAGE_H
+
+#define __ALIGN		.balign 4
+#define __ALIGN_STR	".balign 4"
+
+#endif /* _ASM_RISCV_LINKAGE_H */
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 07/16] riscv: Implement setjmp/longjmp/initjmp for RV32I
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (5 preceding siblings ...)
  2021-03-10  8:47 ` [PATCH v3 06/16] riscv: Add asm/linkage.h Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 08/16] mips: Add linkage.h Ahmad Fatoum
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer, Ahmad Fatoum

From: Sascha Hauer <s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/riscv/Kconfig              |  1 +
 arch/riscv/include/asm/setjmp.h | 27 +++++++++++++++++++++++++
 arch/riscv/lib/Makefile         |  1 +
 arch/riscv/lib/longjmp.S        | 28 ++++++++++++++++++++++++++
 arch/riscv/lib/setjmp.S         | 35 +++++++++++++++++++++++++++++++++
 5 files changed, 92 insertions(+)
 create mode 100644 arch/riscv/include/asm/setjmp.h
 create mode 100644 arch/riscv/lib/longjmp.S
 create mode 100644 arch/riscv/lib/setjmp.S

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 16c3eecce6f8..c8d63f99bb28 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -36,6 +36,7 @@ config ARCH_RV32I
 	select GENERIC_LIB_ASHLDI3
 	select GENERIC_LIB_ASHRDI3
 	select GENERIC_LIB_LSHRDI3
+	select HAS_ARCH_SJLJ
 
 endchoice
 
diff --git a/arch/riscv/include/asm/setjmp.h b/arch/riscv/include/asm/setjmp.h
new file mode 100644
index 000000000000..7516f6825841
--- /dev/null
+++ b/arch/riscv/include/asm/setjmp.h
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ * (C) Copyright 2016 Alexander Graf <agraf@suse.de>
+ */
+
+#ifndef _SETJMP_H_
+#define _SETJMP_H_	1
+
+#include <asm/types.h>
+
+typedef struct __jmp_buf_internal_tag
+  {
+	/* Program counter.  */
+	long int __pc;
+	/* Callee-saved registers.  */
+	long int __regs[12];
+	/* Stack pointer.  */
+	long int __sp;
+} jmp_buf[1];
+
+int setjmp(jmp_buf jmp) __attribute__((returns_twice));
+void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
+
+int initjmp(jmp_buf jmp, void __noreturn (*func)(void), void *stack_top);
+
+#endif /* _SETJMP_H_ */
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index a1df0b7dc78c..7fe57b0b554c 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -1,3 +1,4 @@
 extra-y += barebox.lds
 
 obj-y += riscv_timer.o
+obj-$(CONFIG_HAS_ARCH_SJLJ) += setjmp.o longjmp.o
diff --git a/arch/riscv/lib/longjmp.S b/arch/riscv/lib/longjmp.S
new file mode 100644
index 000000000000..7bcb5b30495d
--- /dev/null
+++ b/arch/riscv/lib/longjmp.S
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+/* longjmp, RISC-V version. */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+
+ENTRY (longjmp)
+	REG_L ra,  0*SZREG(a0)
+	REG_L s0,  1*SZREG(a0)
+	REG_L s1,  2*SZREG(a0)
+	REG_L s2,  3*SZREG(a0)
+	REG_L s3,  4*SZREG(a0)
+	REG_L s4,  5*SZREG(a0)
+	REG_L s5,  6*SZREG(a0)
+	REG_L s6,  7*SZREG(a0)
+	REG_L s7,  8*SZREG(a0)
+	REG_L s8,  9*SZREG(a0)
+	REG_L s9, 10*SZREG(a0)
+	REG_L s10,11*SZREG(a0)
+	REG_L s11,12*SZREG(a0)
+	REG_L sp, 13*SZREG(a0)
+
+	seqz a0, a1
+	add  a0, a0, a1   # a0 = (a1 == 0) ? 1 : a1
+	ret
+
+END (longjmp)
diff --git a/arch/riscv/lib/setjmp.S b/arch/riscv/lib/setjmp.S
new file mode 100644
index 000000000000..e8ad01635dd3
--- /dev/null
+++ b/arch/riscv/lib/setjmp.S
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+/* setjmp for RISC-V. */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+
+ENTRY (setjmp)
+	REG_S ra,  0*SZREG(a0)
+	REG_S s0,  1*SZREG(a0)
+	REG_S s1,  2*SZREG(a0)
+	REG_S s2,  3*SZREG(a0)
+	REG_S s3,  4*SZREG(a0)
+	REG_S s4,  5*SZREG(a0)
+	REG_S s5,  6*SZREG(a0)
+	REG_S s6,  7*SZREG(a0)
+	REG_S s7,  8*SZREG(a0)
+	REG_S s8,  9*SZREG(a0)
+	REG_S s9, 10*SZREG(a0)
+	REG_S s10,11*SZREG(a0)
+	REG_S s11,12*SZREG(a0)
+	REG_S sp, 13*SZREG(a0)
+
+	li a0, 0
+	ret
+
+END (setjmp)
+
+ENTRY (initjmp)
+	REG_S a1,  0*SZREG(a0)
+	REG_S a2, 13*SZREG(a0)
+	li a0, 0
+	ret
+
+END (initjmp)
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 08/16] mips: Add linkage.h
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (6 preceding siblings ...)
  2021-03-10  8:47 ` [PATCH v3 07/16] riscv: Implement setjmp/longjmp/initjmp for RV32I Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 09/16] mips: Implement setjmp/longjmp/initjmp for 32BIT Ahmad Fatoum
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer, Ahmad Fatoum

From: Sascha Hauer <s.hauer@pengutronix.de>

Taken from Linux Kernel with unnecessary bits removed.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/mips/include/asm/linkage.h | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 arch/mips/include/asm/linkage.h

diff --git a/arch/mips/include/asm/linkage.h b/arch/mips/include/asm/linkage.h
new file mode 100644
index 000000000000..14835f513961
--- /dev/null
+++ b/arch/mips/include/asm/linkage.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+#ifdef __ASSEMBLY__
+#include <asm/asm.h>
+#endif
+
+#endif
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 09/16] mips: Implement setjmp/longjmp/initjmp for 32BIT
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (7 preceding siblings ...)
  2021-03-10  8:47 ` [PATCH v3 08/16] mips: Add linkage.h Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 10/16] powerpc: Implement initjmp/setjmp/longjmp Ahmad Fatoum
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer, Ahmad Fatoum

From: Sascha Hauer <s.hauer@pengutronix.de>

The header has been taken from glibc, the implementation itself is based
on the newlib implementation.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/mips/Kconfig              |  1 +
 arch/mips/include/asm/setjmp.h | 32 ++++++++++++++++++++++
 arch/mips/lib/Makefile         |  1 +
 arch/mips/lib/setjmp.S         | 50 ++++++++++++++++++++++++++++++++++
 4 files changed, 84 insertions(+)
 create mode 100644 arch/mips/include/asm/setjmp.h
 create mode 100644 arch/mips/lib/setjmp.S

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 48f97c4bbf30..7774abe94827 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -303,6 +303,7 @@ choice
 config 32BIT
 	bool "32-bit barebox"
 	depends on CPU_SUPPORTS_32BIT_KERNEL && SYS_SUPPORTS_32BIT_KERNEL
+	select HAS_ARCH_SJLJ
 	help
 	  Select this option if you want to build a 32-bit barebox.
 
diff --git a/arch/mips/include/asm/setjmp.h b/arch/mips/include/asm/setjmp.h
new file mode 100644
index 000000000000..5a9af7773a5f
--- /dev/null
+++ b/arch/mips/include/asm/setjmp.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+/*
+ * Define the machine-dependent type `jmp_buf'.  MIPS version.
+ * Copyright (C) 1992-2021 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ */
+
+#ifndef _MIPS_BITS_SETJMP_H
+#define _MIPS_BITS_SETJMP_H 1
+
+#include <asm/sgidefs.h>
+
+typedef struct __jmp_buf_internal_tag {
+	/* Program counter.  */
+	void *__pc;
+
+	/* Stack pointer.  */
+	void *__sp;
+
+	/* Callee-saved registers s0 through s7.  */
+	int __regs[8];
+
+	/* The frame pointer.  */
+	void *__fp;
+} jmp_buf[1];
+
+int setjmp(jmp_buf jmp) __attribute__((returns_twice));
+void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
+int initjmp(jmp_buf jmp, void __noreturn (*func)(void), void *stack_top);
+
+#endif /* _MIPS_BITS_SETJMP_H */
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 0761588ae865..88a2bdbd282b 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -8,6 +8,7 @@ obj-y += reloc.o
 obj-y += sections.o
 obj-y += shutdown.o
 obj-y += dma-default.o
+obj-$(CONFIG_HAS_ARCH_SJLJ) += setjmp.o
 
 obj-$(CONFIG_MIPS_OPTIMIZED_STRING_FUNCTIONS) += memcpy.o
 obj-$(CONFIG_MIPS_OPTIMIZED_STRING_FUNCTIONS) += memset.o
diff --git a/arch/mips/lib/setjmp.S b/arch/mips/lib/setjmp.S
new file mode 100644
index 000000000000..b09a7c55293c
--- /dev/null
+++ b/arch/mips/lib/setjmp.S
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <asm/regdef.h>
+#include <asm/asm.h>
+#include <linux/linkage.h>
+
+/* int setjmp (jmp_buf);  */
+LEAF(setjmp)
+	sw	ra, (0 * 4)(a0)
+	sw	sp, (1 * 4)(a0)
+	sw	s0, (2 * 4)(a0)
+	sw	s1, (3 * 4)(a0)
+	sw	s2, (4 * 4)(a0)
+	sw	s3, (5 * 4)(a0)
+	sw	s4, (6 * 4)(a0)
+	sw	s5, (7 * 4)(a0)
+	sw	s6, (8 * 4)(a0)
+	sw	s7, (9 * 4)(a0)
+	sw	fp, (10 * 4)(a0)
+	move	v0, zero
+	j	ra
+END(setjmp)
+
+/* volatile void longjmp (jmp_buf, int);  */
+LEAF(longjmp)
+	lw	ra, (0 * 4)(a0)
+	lw	sp, (1 * 4)(a0)
+	lw	s0, (2 * 4)(a0)
+	lw	s1, (3 * 4)(a0)
+	lw	s2, (4 * 4)(a0)
+	lw	s3, (5 * 4)(a0)
+	lw	s4, (6 * 4)(a0)
+	lw	s5, (7 * 4)(a0)
+	lw	s6, (8 * 4)(a0)
+	lw	s7, (9 * 4)(a0)
+	lw	fp, (10 * 4)(a0)
+	bne	a1, zero, 1f
+	li	a1, 1
+1:
+	move	v0, a1
+	j	ra
+END(longjmp)
+
+/* int initjmp(jmp_buf jmp, void __noreturn (*func)(void), void *stack_top); */
+LEAF(initjmp)
+	sw	a1, (0 * 4)(a0)
+	sw	a2, (1 * 4)(a0)
+	move	v0, zero
+	j	ra
+END(initjmp)
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 10/16] powerpc: Implement initjmp/setjmp/longjmp
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (8 preceding siblings ...)
  2021-03-10  8:47 ` [PATCH v3 09/16] mips: Implement setjmp/longjmp/initjmp for 32BIT Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 11/16] x86: implement setjmp/longjmp/initjmp Ahmad Fatoum
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer, Ahmad Fatoum

From: Sascha Hauer <s.hauer@pengutronix.de>

Implementation has been taken from newlib as this is much simpler than
the glibc version.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/powerpc/Kconfig              |  1 +
 arch/powerpc/include/asm/setjmp.h | 21 ++++++++
 arch/powerpc/lib/Makefile         |  2 +-
 arch/powerpc/lib/setjmp.S         | 86 +++++++++++++++++++++++++++++++
 4 files changed, 109 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/include/asm/setjmp.h
 create mode 100644 arch/powerpc/lib/setjmp.S

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 90ec7b1702e9..376c1bf42b5e 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -6,6 +6,7 @@ config PPC
 	select HAS_CACHE
 	select GENERIC_FIND_NEXT_BIT
 	select OFTREE
+	select HAS_ARCH_SJLJ
 	default y
 
 choice
diff --git a/arch/powerpc/include/asm/setjmp.h b/arch/powerpc/include/asm/setjmp.h
new file mode 100644
index 000000000000..c558415c99d9
--- /dev/null
+++ b/arch/powerpc/include/asm/setjmp.h
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ * (C) Copyright 2016 Alexander Graf <agraf@suse.de>
+ */
+
+#ifndef _SETJMP_H_
+#define _SETJMP_H_	1
+
+#include <asm/types.h>
+
+typedef struct __jmp_buf_internal_tag {
+	long int __regs[24];
+} jmp_buf[1];
+
+int setjmp(jmp_buf jmp) __attribute__((returns_twice));
+void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
+
+int initjmp(jmp_buf jmp, void __noreturn (*func)(void), void *stack_top);
+
+#endif /* _SETJMP_H_ */
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index ba2f078b6277..405351c19929 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -9,4 +9,4 @@ obj-$(CONFIG_CMD_BOOTM) += ppclinux.o
 obj-$(CONFIG_MODULES) += module.o
 obj-y += crtsavres.o
 obj-y += reloc.o
-
+obj-y += setjmp.o
diff --git a/arch/powerpc/lib/setjmp.S b/arch/powerpc/lib/setjmp.S
new file mode 100644
index 000000000000..021a57eebc3c
--- /dev/null
+++ b/arch/powerpc/lib/setjmp.S
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * This is a simple version of setjmp and longjmp for the PowerPC.
+ * Ian Lance Taylor, Cygnus Support, 9 Feb 1994.
+ */
+
+#include <linux/linkage.h>
+#include <asm/ppc_asm.tmpl>
+
+ENTRY(setjmp)
+	addi	r3,r3,7		# align to 8 byte boundary
+	rlwinm	r3,r3,0,0,28
+	stw	r1,0(r3)	# offset 0
+	stwu	r2,4(r3)	# offset 4
+	stwu	r13,4(r3)	# offset 8
+	stwu	r14,4(r3)	# offset 12
+	stwu	r15,4(r3)	# offset 16
+	stwu	r16,4(r3)	# offset 20
+	stwu	r17,4(r3)	# offset 24
+	stwu	r18,4(r3)	# offset 28
+	stwu	r19,4(r3)	# offset 32
+	stwu	r20,4(r3)	# offset 36
+	stwu	r21,4(r3)	# offset 40
+	stwu	r22,4(r3)	# offset 44
+	stwu	r23,4(r3)	# offset 48
+	stwu	r24,4(r3)	# offset 52
+	stwu	r25,4(r3)	# offset 56
+	stwu	r26,4(r3)	# offset 60
+	stwu	r27,4(r3)	# offset 64
+	stwu	r28,4(r3)	# offset 68
+	stwu	r29,4(r3)	# offset 72
+	stwu	r30,4(r3)	# offset 76
+	stwu	r31,4(r3)	# offset 80
+	mflr	r4
+	stwu	r4,4(r3)	# offset 84
+	mfcr	r4
+	stwu	r4,4(r3)	# offset 88
+
+	li	r3,0
+	blr
+END(setjmp)
+
+ENTRY(longjmp)
+	addi	r3,r3,7		# align to 8 byte boundary
+	rlwinm	r3,r3,0,0,28
+	lwz	r1,0(r3)	# offset 0
+	lwzu	r2,4(r3)	# offset 4
+	lwzu	r13,4(r3)	# offset 8
+	lwzu	r14,4(r3)	# offset 12
+	lwzu	r15,4(r3)	# offset 16
+	lwzu	r16,4(r3)	# offset 20
+	lwzu	r17,4(r3)	# offset 24
+	lwzu	r18,4(r3)	# offset 28
+	lwzu	r19,4(r3)	# offset 32
+	lwzu	r20,4(r3)	# offset 36
+	lwzu	r21,4(r3)	# offset 40
+	lwzu	r22,4(r3)	# offset 44
+	lwzu	r23,4(r3)	# offset 48
+	lwzu	r24,4(r3)	# offset 52
+	lwzu	r25,4(r3)	# offset 56
+	lwzu	r26,4(r3)	# offset 60
+	lwzu	r27,4(r3)	# offset 64
+	lwzu	r28,4(r3)	# offset 68
+	lwzu	r29,4(r3)	# offset 72
+	lwzu	r30,4(r3)	# offset 76
+	lwzu	r31,4(r3)	# offset 80
+	lwzu	r5,4(r3)	# offset 84
+	mtlr	r5
+	lwzu	r5,4(r3)	# offset 88
+	mtcrf	255,r5
+
+	mr.	r3,r4
+	bclr+	4,2
+	li	r3,1
+	blr
+END(longjmp)
+
+ENTRY(initjmp)
+	addi	r3,r3,7		# align to 8 byte boundary
+	rlwinm	r3,r3,0,0,28
+	stw	r5,0(r3)	# offset 0
+	stwu	r4,88(r3)	# offset 88
+	li	r3,0
+	blr
+END(initjmp)
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 11/16] x86: implement setjmp/longjmp/initjmp
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (9 preceding siblings ...)
  2021-03-10  8:47 ` [PATCH v3 10/16] powerpc: Implement initjmp/setjmp/longjmp Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 12/16] common: poller: replace explicit calls to poller_call() with resched() Ahmad Fatoum
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer

From: Ahmad Fatoum <ahmad@a3f.at>

For use with bthreads, implement CONFIG_HAS_ARCH_SJLJ.
Code is taken from U-Boot, itself based on the Linux ARCH=um.

Signed-off-by: Ahmad Fatoum <ahmad@a3f.at>
---
 arch/x86/Kconfig              |  2 ++
 arch/x86/include/asm/setjmp.h | 44 +++++++++++++++++++++++++
 arch/x86/lib/Makefile         |  3 ++
 arch/x86/lib/setjmp_32.S      | 60 +++++++++++++++++++++++++++++++++++
 arch/x86/lib/setjmp_64.S      | 60 +++++++++++++++++++++++++++++++++++
 5 files changed, 169 insertions(+)
 create mode 100644 arch/x86/include/asm/setjmp.h
 create mode 100644 arch/x86/lib/setjmp_32.S
 create mode 100644 arch/x86/lib/setjmp_64.S

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0e3e5d61872a..e942c79cbd49 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -36,10 +36,12 @@ config 64BIT
 config X86_32
 	def_bool y
 	depends on !64BIT
+	select HAS_ARCH_SJLJ
 
 config X86_64
 	def_bool y
 	depends on 64BIT
+	select HAS_ARCH_SJLJ
 
 endmenu
 
diff --git a/arch/x86/include/asm/setjmp.h b/arch/x86/include/asm/setjmp.h
new file mode 100644
index 000000000000..88c198cfaeb9
--- /dev/null
+++ b/arch/x86/include/asm/setjmp.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Written by H. Peter Anvin <hpa@zytor.com>
+ * Brought in from Linux v4.4 and modified for U-Boot
+ * From Linux arch/um/sys-i386/setjmp.S
+ */
+
+#ifndef __setjmp_h
+#define __setjmp_h
+
+#include <linux/compiler.h>
+
+struct jmp_buf_data {
+#if defined CONFIG_X86_64
+#define __sjlj_attr
+	unsigned long __rip;
+	unsigned long __rsp;
+	unsigned long __rbp;
+	unsigned long __rbx;
+	unsigned long __r12;
+	unsigned long __r13;
+	unsigned long __r14;
+	unsigned long __r15;
+#elif defined CONFIG_X86_32
+#define __sjlj_attr	__attribute__((regparm(3)))
+	unsigned int __ebx;
+	unsigned int __esp;
+	unsigned int __ebp;
+	unsigned int __esi;
+	unsigned int __edi;
+	unsigned int __eip;
+#else
+#error "Unsupported configuration"
+#endif
+};
+
+typedef struct jmp_buf_data jmp_buf[1];
+
+int setjmp(jmp_buf jmp) __attribute__((returns_twice)) __sjlj_attr;
+void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn)) __sjlj_attr;
+
+int initjmp(jmp_buf jmp, void __noreturn (*func)(void), void *stack_top) __sjlj_attr;
+
+#endif
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 05e43f0f2b34..6a8fa7c0ff3e 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -4,5 +4,8 @@ obj-y += memory.o
 obj-y += gdt.o
 endif
 
+obj-$(CONFIG_X86_32) += setjmp_32.o
+obj-$(CONFIG_X86_64) += setjmp_64.o
+
 # needed, when running via a 16 bit BIOS
 obj-$(CONFIG_CMD_LINUX16) += linux_start.o
diff --git a/arch/x86/lib/setjmp_32.S b/arch/x86/lib/setjmp_32.S
new file mode 100644
index 000000000000..38dcb68c1b59
--- /dev/null
+++ b/arch/x86/lib/setjmp_32.S
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Written by H. Peter Anvin <hpa@zytor.com>
+ * Brought in from Linux v4.4 and modified for U-Boot
+ * From Linux arch/um/sys-i386/setjmp.S
+ */
+
+#define _REGPARM
+
+#include <linux/linkage.h>
+
+.text
+.align 8
+
+/*
+ * The jmp_buf is assumed to contain the following, in order:
+ *	%ebx
+ *	%esp
+ *	%ebp
+ *	%esi
+ *	%edi
+ *	<return address>
+ */
+
+ENTRY(setjmp)
+
+	movl %eax, %edx
+	popl %ecx		/* Return address, and adjust the stack */
+	xorl %eax, %eax		/* Return value */
+	movl %ebx, (%edx)
+	movl %esp, 4(%edx)	/* Post-return %esp! */
+	pushl %ecx		/* Make the call/return stack happy */
+	movl %ebp, 8(%edx)
+	movl %esi, 12(%edx)
+	movl %edi, 16(%edx)
+	movl %ecx, 20(%edx)	/* Return address */
+	ret
+
+ENDPROC(setjmp)
+
+ENTRY(longjmp)
+
+	xchgl %eax, %edx
+	movl (%edx), %ebx
+	movl 4(%edx), %esp
+	movl 8(%edx), %ebp
+	movl 12(%edx), %esi
+	movl 16(%edx), %edi
+	jmp *20(%edx)
+
+ENDPROC(longjmp)
+
+ENTRY(initjmp)
+
+	movl %edx, 20(%eax)	/* Return address */
+	movl %ecx, 4(%eax)	/* Post-return %esp! */
+	xorl %eax, %eax		/* Return value */
+	ret
+
+ENDPROC(initjmp)
diff --git a/arch/x86/lib/setjmp_64.S b/arch/x86/lib/setjmp_64.S
new file mode 100644
index 000000000000..28ea576cd22e
--- /dev/null
+++ b/arch/x86/lib/setjmp_64.S
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Intel Corporation
+ *
+ * See arch/x86/include/asm/setjmp.h for jmp_buf format
+ */
+
+#include <linux/linkage.h>
+
+.text
+.align 8
+
+ENTRY(setjmp)
+
+	pop	%rcx
+	movq	%rcx, (%rdi)	/* Return address */
+	movq	%rsp, 8(%rdi)
+	movq	%rbp, 16(%rdi)
+	movq	%rbx, 24(%rdi)
+	movq	%r12, 32(%rdi)
+	movq	%r13, 40(%rdi)
+	movq	%r14, 48(%rdi)
+	movq	%r15, 56(%rdi)
+	xorq	%rax, %rax	/* Direct invocation returns 0 */
+	jmpq	*%rcx
+
+ENDPROC(setjmp)
+
+.align 8
+
+ENTRY(longjmp)
+
+	movq	(%rdi), %rcx	/* Return address */
+	movq	8(%rdi), %rsp
+	movq	16(%rdi), %rbp
+	movq	24(%rdi), %rbx
+	movq	32(%rdi), %r12
+	movq	40(%rdi), %r13
+	movq	48(%rdi), %r14
+	movq	56(%rdi), %r15
+
+	movq	%rsi, %rax	/* Value to be returned by setjmp() */
+	testq	%rax, %rax	/* cannot be 0 in this case */
+	jnz	1f
+	incq	%rax		/* Return 1 instead */
+1:
+	jmpq	*%rcx
+
+ENDPROC(longjmp)
+
+.align 8
+
+ENTRY(initjmp)
+
+	movq	%rsi, (%rdi)	/* Return address */
+	movq	%rdx, 8(%rdi)	/* Stack top */
+	xorq	%rax, %rax
+	ret
+
+ENDPROC(initjmp)
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 12/16] common: poller: replace explicit calls to poller_call() with resched()
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (10 preceding siblings ...)
  2021-03-10  8:47 ` [PATCH v3 11/16] x86: implement setjmp/longjmp/initjmp Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 13/16] console: unconditionally run resched() in ctrlc() Ahmad Fatoum
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer

From: Ahmad Fatoum <ahmad@a3f.at>

We won't replace pollers with bthreads completely over night. To make
migration easier, replace explicit calls to poller_call with a new
resched() function. This can be made to call bthread_reschedule() in
future and eventually replaced with bthread_reschedule() once pollers
are removed.

Signed-off-by: Ahmad Fatoum <ahmad@a3f.at>
---
 common/clock.c   |  4 ++--
 common/console.c |  4 ++--
 include/sched.h  | 12 ++++++++++++
 lib/readline.c   |  4 ++--
 4 files changed, 18 insertions(+), 6 deletions(-)
 create mode 100644 include/sched.h

diff --git a/common/clock.c b/common/clock.c
index 7eeba88317ac..fa90d1a4576f 100644
--- a/common/clock.c
+++ b/common/clock.c
@@ -13,7 +13,7 @@
 #include <init.h>
 #include <linux/math64.h>
 #include <clock.h>
-#include <poller.h>
+#include <sched.h>
 
 static uint64_t time_ns;
 
@@ -172,7 +172,7 @@ int is_timeout(uint64_t start_ns, uint64_t time_offset_ns)
 	int ret = is_timeout_non_interruptible(start_ns, time_offset_ns);
 
 	if (time_offset_ns >= 100 * USECOND)
-		poller_call();
+		resched();
 
 	return ret;
 }
diff --git a/common/console.c b/common/console.c
index 306149c99ea1..a436c37aa3e8 100644
--- a/common/console.c
+++ b/common/console.c
@@ -17,7 +17,7 @@
 #include <clock.h>
 #include <kfifo.h>
 #include <module.h>
-#include <poller.h>
+#include <sched.h>
 #include <ratp_bb.h>
 #include <magicvar.h>
 #include <globalvar.h>
@@ -585,7 +585,7 @@ int ctrlc(void)
 	if (ctrlc_abort)
 		return 1;
 
-	poller_call();
+	resched();
 
 #ifdef ARCH_HAS_CTRLC
 	ret = arch_ctrlc();
diff --git a/include/sched.h b/include/sched.h
new file mode 100644
index 000000000000..43d239c3ef63
--- /dev/null
+++ b/include/sched.h
@@ -0,0 +1,12 @@
+/* SPDX License Identifier: GPL-2.0 */
+#ifndef __BAREBOX_SCHED_H_
+#define __BAREBOX_SCHED_H_
+
+#include <poller.h>
+
+static inline void resched(void)
+{
+	poller_call();
+}
+
+#endif
diff --git a/lib/readline.c b/lib/readline.c
index e5370f9c7b6e..25aa99b95e46 100644
--- a/lib/readline.c
+++ b/lib/readline.c
@@ -2,7 +2,7 @@
 #include <readkey.h>
 #include <init.h>
 #include <libbb.h>
-#include <poller.h>
+#include <sched.h>
 #include <xfuncs.h>
 #include <complete.h>
 #include <linux/ctype.h>
@@ -200,7 +200,7 @@ int readline(const char *prompt, char *buf, int len)
 
 	while (1) {
 		while (!tstc())
-			poller_call();
+			resched();
 
 		ichar = read_key();
 
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 13/16] console: unconditionally run resched() in ctrlc()
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (11 preceding siblings ...)
  2021-03-10  8:47 ` [PATCH v3 12/16] common: poller: replace explicit calls to poller_call() with resched() Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 14/16] common: introduce bthreads, co-operative barebox threads Ahmad Fatoum
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer

From: Ahmad Fatoum <ahmad@a3f.at>

ctrlc is allowed only after init and reboot mode scripts have run, so
these scripts run uninterruptible. A side effect of this is that all
calls to ctrlc() will immediately return with false without running the
pollers. While init scripts shouldn't run too long, it's still
surprising behavior. Thus call resched() first thing in ctrlc().

Signed-off-by: Ahmad Fatoum <ahmad@a3f.at>
---
 common/console.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/console.c b/common/console.c
index a436c37aa3e8..8a0af75a1ff4 100644
--- a/common/console.c
+++ b/common/console.c
@@ -579,14 +579,14 @@ int ctrlc(void)
 {
 	int ret = 0;
 
+	resched();
+
 	if (!ctrlc_allowed)
 		return 0;
 
 	if (ctrlc_abort)
 		return 1;
 
-	resched();
-
 #ifdef ARCH_HAS_CTRLC
 	ret = arch_ctrlc();
 #else
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 14/16] common: introduce bthreads, co-operative barebox threads
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (12 preceding siblings ...)
  2021-03-10  8:47 ` [PATCH v3 13/16] console: unconditionally run resched() in ctrlc() Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:47 ` [PATCH v3 15/16] commands: add new bthread test command Ahmad Fatoum
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer, Ahmad Fatoum

With the new setjmp/longjmp/initjmp support, we have all the
architecture support in place to have suspendable green
threads in barebox. These are expected to replace pollers and
workqueues. For now we still have a differentiation between
the main and secondary threads. The main thread is allowed
I/O access unconditionally. If it's in a delay loop, a secondary
thread running needs to be wary of not entering the same driver
and doing hardware manipulation. We already have slices as
mechanism to guard against this, but they aren't used as widely
as needed.

Preferably, in the end, threads will automatically yield until
they can claim a resource (i.e. lock a mutex). Until we are there,
take the same care when using bthreads as with pollers.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 Documentation/devel/background-execution.rst |  37 +++-
 common/Kconfig                               |   8 +
 common/Makefile                              |   1 +
 common/bthread.c                             | 214 +++++++++++++++++++
 include/bthread.h                            |  53 +++++
 include/poller.h                             |   2 +
 include/sched.h                              |   3 +
 include/slice.h                              |  17 +-
 8 files changed, 323 insertions(+), 12 deletions(-)
 create mode 100644 common/bthread.c
 create mode 100644 include/bthread.h

diff --git a/Documentation/devel/background-execution.rst b/Documentation/devel/background-execution.rst
index eadad9d898d0..fa4d23e6d271 100644
--- a/Documentation/devel/background-execution.rst
+++ b/Documentation/devel/background-execution.rst
@@ -1,10 +1,10 @@
 Background execution in barebox
 ===============================
 
-barebox is single-threaded and doesn't support interrupts. Nevertheless it is
-sometimes desired to execute code "in the background", like for example polling
-for completion of transfers or to regularly blink a heartbeat LED.  For these
-scenarios barebox offers the techniques described below.
+barebox does not use interrupts to avoid the associated increase in complexity.
+Nevertheless it is sometimes desired to execute code "in the background",
+like for example polling for completion of transfers or to regularly blink a
+heartbeat LED. For these scenarios barebox offers the techniques described below.
 
 Pollers
 -------
@@ -71,6 +71,35 @@ actually queueing a work item on a work queue. This can be called from poller
 code. Usually a work item is allocated by the poller and then freed either in
 ``work_queue.fn()`` or in ``work_queue.cancel()``.
 
+bthreads
+--------
+
+barebox threads are co-operative green threads, which are scheduled whenever
+``is_timeout()`` is called.  This has a few implications. First of all,
+bthreads are not scheduled when ``is_timeout()`` is not called.
+For this and other reasons, loops polling for hardware events should always
+use a timeout, which is best implemented with ``is_timeout()``.
+Another thing to remember is that bthreads can be scheduled anywhere
+in the middle of other device accesses whenever ``is_timeout()`` is
+called. Care must be taken that a green thread doesn't access the very same device
+again itself. See "slices" below on how devices can safely be accessed from
+bthreads.
+
+The bthread interface is declared in ``include/bthread.h``.
+``bthread_create()`` is used to allocate a bthread control block along with
+its stack. ``bthread_wake()`` can be used to add it into the run queue.
+From this moment on and until the thread terminates, the thread will be
+switched to regularly as long as someone calls ``is_timeout()``.
+bthreads are allowed to call ``is_timeout()``, which will arrange for
+other threads to execute.
+
+barebox threads are planned to replace previous infrastructure, pollers
+and workqueues. Poller like behavior can be easily achieved by looping
+and yielding on every iteration. There's ``bthread_should_stop()``, which
+can be used as condition for continuing the loop. Workqueues could be
+replaced along the same line, but with mutexes protecting underlying device
+access.
+
 Slices
 ------
 
diff --git a/common/Kconfig b/common/Kconfig
index c0ff57bcdba4..b1f4543e03cd 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -960,6 +960,14 @@ config BAREBOXCRC32_TARGET
 config POLLER
 	bool "generic polling infrastructure"
 
+config BTHREAD
+	bool "barebox co-operative (green) thread infrastructure"
+	depends on HAS_ARCH_SJLJ
+	help
+	 barebox threads are lightweight cooperative (green) threads that are
+	 scheduled within delay loops and the console idle to asynchronously
+	 execute actions, like checking for link up or feeding a watchdog.
+
 config STATE
 	bool "generic state infrastructure"
 	select CRC32
diff --git a/common/Makefile b/common/Makefile
index 0e0ba384c9b5..c0b45d263e5b 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_OFTREE)		+= oftree.o
 obj-$(CONFIG_PARTITION_DISK)	+= partitions.o partitions/
 obj-$(CONFIG_PASSWORD)		+= password.o
 obj-$(CONFIG_POLLER)		+= poller.o
+obj-$(CONFIG_BTHREAD)		+= bthread.o
 obj-$(CONFIG_RESET_SOURCE)	+= reset_source.o
 obj-$(CONFIG_SHELL_HUSH)	+= hush.o
 obj-$(CONFIG_SHELL_SIMPLE)	+= parser.o
diff --git a/common/bthread.c b/common/bthread.c
new file mode 100644
index 000000000000..df8031266d55
--- /dev/null
+++ b/common/bthread.c
@@ -0,0 +1,214 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2021 Ahmad Fatoum, Pengutronix
+ *
+ * ASAN bookkeeping based on Qemu coroutine-ucontext.c
+ */
+
+/* To avoid future issues; fortify doesn't like longjmp up the call stack */
+#ifndef __NO_FORTIFY
+#define __NO_FORTIFY
+#endif
+
+#include <common.h>
+#include <bthread.h>
+#include <asm/setjmp.h>
+#include <linux/overflow.h>
+
+static struct bthread {
+	int (*threadfn)(void *);
+	union {
+		void *data;
+		int ret;
+	};
+	char *name;
+	jmp_buf jmp_buf;
+	void *stack;
+	u32 stack_size;
+	struct list_head list;
+#ifdef CONFIG_ASAN
+	void *fake_stack_save;
+#endif
+	u16 awake :1;
+	u16 should_stop :1;
+	u16 has_stopped :1;
+	u8 stack_space[] __aligned(16);
+} main_thread = {
+	.list = LIST_HEAD_INIT(main_thread.list),
+	.name = "main",
+};
+
+struct bthread *current = &main_thread;
+
+/*
+ * When using ASAN, it needs to be told when we switch stacks.
+ */
+static void start_switch_fiber(struct bthread *, bool terminate_old);
+static void finish_switch_fiber(struct bthread *);
+
+static void __noreturn bthread_trampoline(void)
+{
+	finish_switch_fiber(current);
+	bthread_reschedule();
+
+	current->ret = current->threadfn(current->data);
+
+	bthread_suspend(current);
+	current->has_stopped = true;
+
+	current = &main_thread;
+	start_switch_fiber(current, true);
+	longjmp(current->jmp_buf, 1);
+}
+
+bool bthread_is_main(struct bthread *bthread)
+{
+	return bthread == &main_thread;
+}
+
+void bthread_free(struct bthread *bthread)
+{
+	free(bthread->name);
+	free(bthread);
+}
+
+const char *bthread_name(struct bthread *bthread)
+{
+	return bthread->name;
+}
+
+struct bthread *bthread_create(int (*threadfn)(void *), void *data,
+			       const char *namefmt, ...)
+{
+	struct bthread *bthread = NULL;
+	va_list ap;
+	int len;
+
+	bthread = malloc(struct_size(bthread, stack_space, CONFIG_STACK_SIZE));
+	if (!bthread)
+		goto err;
+
+	memset(bthread, 0, sizeof(*bthread));
+
+	bthread->stack = bthread->stack_space;
+	bthread->stack_size = CONFIG_STACK_SIZE;
+	bthread->threadfn = threadfn;
+	bthread->data = data;
+
+	va_start(ap, namefmt);
+	len = vasprintf(&bthread->name, namefmt, ap);
+	va_end(ap);
+
+	if (len < 0)
+		goto err;
+
+	/* set up bthread context with the new stack */
+	initjmp(bthread->jmp_buf, bthread_trampoline,
+		bthread->stack + CONFIG_STACK_SIZE);
+
+	return bthread;
+err:
+	free(bthread);
+	return NULL;
+}
+
+void bthread_wake(struct bthread *bthread)
+{
+	if (bthread->awake)
+		return;
+	list_add_tail(&bthread->list, &current->list);
+	bthread->awake = true;
+}
+
+void bthread_suspend(struct bthread *bthread)
+{
+	if (!bthread->awake)
+		return;
+	bthread->awake = false;
+	list_del(&bthread->list);
+}
+
+int bthread_stop(struct bthread *bthread)
+{
+	bthread->should_stop = true;
+
+	while (!bthread->has_stopped)
+		bthread_reschedule();
+
+	return bthread->ret;
+}
+
+int bthread_should_stop(void)
+{
+	if (bthread_is_main(current))
+		return -EINTR;
+	bthread_reschedule();
+	return current->should_stop;
+}
+
+void bthread_info(void)
+{
+	struct bthread *bthread;
+
+	printf("Registered barebox threads:\n%s\n", current->name);
+
+	list_for_each_entry(bthread, &current->list, list)
+		printf("%s\n", bthread->name);
+}
+
+void bthread_reschedule(void)
+{
+	bthread_schedule(list_next_entry(current, list));
+}
+
+void bthread_schedule(struct bthread *to)
+{
+	struct bthread *from = current;
+	int ret;
+
+	start_switch_fiber(to, false);
+
+	ret = setjmp(from->jmp_buf);
+	if (ret == 0) {
+		current = to;
+		longjmp(to->jmp_buf, 1);
+	}
+
+	finish_switch_fiber(from);
+}
+
+#ifdef CONFIG_ASAN
+
+void __sanitizer_start_switch_fiber(void **fake_stack_save, const void *bottom, size_t size);
+void __sanitizer_finish_switch_fiber(void *fake_stack_save, const void **bottom_old, size_t *size_old);
+
+static void finish_switch_fiber(struct bthread *bthread)
+{
+	const void *bottom_old;
+	size_t size_old;
+
+	__sanitizer_finish_switch_fiber(bthread->fake_stack_save, &bottom_old, &size_old);
+
+	if (!main_thread.stack) {
+		main_thread.stack = (void *)bottom_old;
+		main_thread.stack_size = size_old;
+	}
+}
+
+static void start_switch_fiber(struct bthread *to, bool terminate_old)
+{
+	__sanitizer_start_switch_fiber(terminate_old ? &to->fake_stack_save : NULL,
+				       to->stack, to->stack_size);
+}
+
+#else
+
+static void finish_switch_fiber(struct bthread *bthread)
+{
+}
+
+static void start_switch_fiber(struct bthread *to, bool terminate_old)
+{
+}
+
+#endif
diff --git a/include/bthread.h b/include/bthread.h
new file mode 100644
index 000000000000..e3871fb11555
--- /dev/null
+++ b/include/bthread.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#ifndef __BTHREAD_H_
+#define __BTHREAD_H_
+
+#include <linux/stddef.h>
+
+struct bthread;
+
+extern struct bthread *current;
+
+struct bthread *bthread_create(int (*threadfn)(void *), void *data, const char *namefmt, ...);
+void bthread_free(struct bthread *bthread);
+
+void bthread_schedule(struct bthread *);
+void bthread_wake(struct bthread *bthread);
+void bthread_suspend(struct bthread *bthread);
+int bthread_should_stop(void);
+int bthread_stop(struct bthread *bthread);
+void bthread_info(void);
+const char *bthread_name(struct bthread *bthread);
+bool bthread_is_main(struct bthread *bthread);
+
+/**
+ * bthread_run - create and wake a thread.
+ * @threadfn: the function to run for coming reschedule cycles
+ * @data: data ptr for @threadfn.
+ * @namefmt: printf-style name for the thread.
+ *
+ * Description: Convenient wrapper for bthread_create() followed by
+ * bthread_wakeup().  Returns the bthread or NULL
+ */
+#define bthread_run(threadfn, data, namefmt, ...)                          \
+({                                                                         \
+        struct bthread *__b                                                \
+                = bthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
+        if (__b)							   \
+                bthread_wake(__b);                                         \
+        __b;                                                               \
+})
+
+#ifdef CONFIG_BTHREAD
+void bthread_reschedule(void);
+#else
+static inline void bthread_reschedule(void)
+{
+}
+#endif
+
+#endif
diff --git a/include/poller.h b/include/poller.h
index db773265b2f6..371dafc6f8b8 100644
--- a/include/poller.h
+++ b/include/poller.h
@@ -39,6 +39,8 @@ static inline bool poller_async_active(struct poller_async *pa)
 	return pa->active;
 }
 
+extern int poller_active;
+
 #ifdef CONFIG_POLLER
 void poller_call(void);
 #else
diff --git a/include/sched.h b/include/sched.h
index 43d239c3ef63..57be1678fdaa 100644
--- a/include/sched.h
+++ b/include/sched.h
@@ -2,11 +2,14 @@
 #ifndef __BAREBOX_SCHED_H_
 #define __BAREBOX_SCHED_H_
 
+#include <bthread.h>
 #include <poller.h>
 
 static inline void resched(void)
 {
 	poller_call();
+	if (!IS_ENABLED(CONFIG_POLLER) || !poller_active)
+		bthread_reschedule();
 }
 
 #endif
diff --git a/include/slice.h b/include/slice.h
index b2d65b80cd69..cf684300a809 100644
--- a/include/slice.h
+++ b/include/slice.h
@@ -1,6 +1,8 @@
 #ifndef __SLICE_H
 #define __SLICE_H
 
+#include <bthread.h>
+
 enum slice_action {
 	SLICE_ACQUIRE = 1,
 	SLICE_RELEASE = -1,
@@ -35,12 +37,11 @@ void command_slice_release(void);
 
 extern int poller_active;
 
-#ifdef CONFIG_POLLER
-#define assert_command_context() ({    \
-	WARN_ONCE(poller_active, "%s called in poller\n", __func__); \
-})
-#else
-#define assert_command_context() do { } while (0)
-#endif
+#define assert_command_context() do { \
+	WARN_ONCE(IS_ENABLED(CONFIG_POLLER) && poller_active, \
+		  "%s called in poller\n", __func__); \
+	WARN_ONCE(IS_ENABLED(CONFIG_BTHREAD) && !bthread_is_main(current), \
+		  "%s called in secondary bthread\n", __func__); \
+} while (0)
 
-#endif /* __SLICE_H */
+#endif
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 15/16] commands: add new bthread test command
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (13 preceding siblings ...)
  2021-03-10  8:47 ` [PATCH v3 14/16] common: introduce bthreads, co-operative barebox threads Ahmad Fatoum
@ 2021-03-10  8:47 ` Ahmad Fatoum
  2021-03-10  8:48 ` [PATCH v3 16/16] RFC: led: migrate from poller to bthread Ahmad Fatoum
  2021-03-15  8:34 ` [PATCH v3 00/16] common: introduce bthreads, co-operative Sascha Hauer
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:47 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer

From: Ahmad Fatoum <ahmad@a3f.at>

This command is meant to show how to use the bthread API as well as
help with debugging. It's a bit overcomplicated to exercise aspects
of the API, like scheduling from both secondary and primary thread.

Signed-off-by: Ahmad Fatoum <ahmad@a3f.at>
---
 commands/Kconfig   |   9 +++
 commands/Makefile  |   1 +
 commands/bthread.c | 195 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 205 insertions(+)
 create mode 100644 commands/bthread.c

diff --git a/commands/Kconfig b/commands/Kconfig
index 520ad4b1dea3..6d84c956e576 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -253,6 +253,15 @@ config CMD_POLLER
 	  is_timeout() or one of the various delay functions. The poller command prints
 	  informations about registered pollers.
 
+config CMD_BTHREAD
+	tristate
+	prompt "bthread"
+	depends on BTHREAD
+	help
+	  barebox threads are cooperatively-scheduled (green) threads that are running in
+	  the background whenever code executes is_timeout() or one of the various delay
+	  functions. The bthread command prints informations about registered bthreads.
+
 config CMD_SLICE
 	tristate
 	prompt "slice"
diff --git a/commands/Makefile b/commands/Makefile
index 034c0e6383d3..cdf14a5e1d8d 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -129,6 +129,7 @@ obj-$(CONFIG_CMD_MMC_EXTCSD)	+= mmc_extcsd.o
 obj-$(CONFIG_CMD_NAND_BITFLIP)	+= nand-bitflip.o
 obj-$(CONFIG_CMD_SEED)		+= seed.o
 obj-$(CONFIG_CMD_IP_ROUTE_GET)  += ip-route-get.o
+obj-$(CONFIG_CMD_BTHREAD)	+= bthread.o
 obj-$(CONFIG_CMD_UBSAN)		+= ubsan.o
 
 UBSAN_SANITIZE_ubsan.o := y
diff --git a/commands/bthread.c b/commands/bthread.c
new file mode 100644
index 000000000000..05dfa68cc597
--- /dev/null
+++ b/commands/bthread.c
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#include <bthread.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <command.h>
+#include <getopt.h>
+#include <clock.h>
+
+static int bthread_time(void)
+{
+	uint64_t start = get_time_ns();
+	int i = 0;
+
+	/*
+	 * How many background tasks can we have in one second?
+	 *
+	 * A low number here may point to problems with bthreads taking too
+	 * much time.
+	 */
+	while (!is_timeout(start, SECOND))
+		i++;
+
+	return i;
+}
+
+static int bthread_infinite(void *data)
+{
+	while (!bthread_should_stop())
+		;
+
+	return 0;
+}
+
+static int bthread_isolated_time(void)
+{
+	uint64_t start = get_time_ns();
+	struct bthread *bthread;
+	int i = 0;
+
+	bthread = bthread_run(bthread_infinite, NULL, "infinite");
+	if (!bthread)
+		return -ENOMEM;
+
+	/* main thread is the first in the run queue. Newly created bthread
+	 * is the last. So if main_thread explicitly schedules new bthread,
+	 * it will schedule back to main_thread afterwards and we won't
+	 * execute any other threads in-between.
+	 */
+
+	while (!is_timeout_non_interruptible(start, SECOND)) {
+		bthread_schedule(bthread);
+		i += 2;
+	}
+
+	bthread_stop(bthread);
+	bthread_free(bthread);
+
+	return i;
+}
+
+static int bthread_printer(void *arg)
+{
+	volatile u64 start;
+	volatile int i = 0;
+	start = get_time_ns();
+
+	while (!bthread_should_stop()) {
+		if (!is_timeout_non_interruptible(start, 225 * MSECOND))
+			continue;
+
+		if ((long)arg == i++)
+			printf("%s yield #%d\n", bthread_name(current), i);
+		start = get_time_ns();
+	}
+
+	return i;
+}
+
+static int yields;
+
+static int bthread_spawner(void *arg)
+{
+	struct bthread *bthread[4];
+	volatile u64 start;
+	volatile int i = 0;
+	int ret = 0;
+	int ecode;
+
+	start = get_time_ns();
+
+	for (i = 0; i < ARRAY_SIZE(bthread); i++) {
+		bthread[i] = bthread_run(bthread_printer, (void *)i,
+					 "%s-bthread%u", bthread_name(current), i+1);
+		if (!bthread[i]) {
+			ret = -ENOMEM;
+			goto cleanup;
+		}
+	}
+
+	while (!bthread_should_stop())
+		;
+
+cleanup:
+	while (i--) {
+		ecode = bthread_stop(bthread[i]);
+		bthread_free(bthread[i]);
+
+		if (!ret && (ecode != 4 || yields < ecode))
+			ret = -EIO;
+	}
+
+	return ret;
+}
+
+struct spawn {
+	struct bthread *bthread;
+	struct list_head list;
+};
+
+static int do_bthread(int argc, char *argv[])
+{
+	LIST_HEAD(spawners);
+	struct spawn *spawner, *tmp;
+	int ret = 0;
+	int ecode, opt, i = 0;
+	bool time = false;
+
+	while ((opt = getopt(argc, argv, "itcv")) > 0) {
+		switch (opt) {
+		case 'i':
+			bthread_info();
+			break;
+		case 'c':
+			yields = bthread_isolated_time();
+			printf("%d bthread context switches possible in 1s\n", yields);
+			break;
+		case 'v':
+			spawner = xzalloc(sizeof(*spawner));
+			spawner->bthread = bthread_run(bthread_spawner, NULL,
+						       "spawner%u", ++i);
+			if (!spawner->bthread) {
+				free(spawner);
+				ret = -ENOMEM;
+				goto cleanup;
+			}
+
+			/* We create intermediate spawning threads to test thread
+			 * creation and scheduling from non-main thread.
+			 */
+			list_add(&spawner->list, &spawners);
+
+			/* fallthrough */
+		case 't':
+			time = true;
+		}
+	}
+
+	if (time) {
+		yields = bthread_time();
+		printf("%d bthread yield calls in 1s\n", yields);
+	}
+
+cleanup:
+	list_for_each_entry_safe(spawner, tmp, &spawners, list) {
+		ecode = bthread_stop(spawner->bthread);
+		bthread_free(spawner->bthread);
+		if (!ret && ecode)
+			ret = ecode;
+		free(spawner);
+	}
+
+	return ret;
+}
+
+BAREBOX_CMD_HELP_START(bthread)
+	BAREBOX_CMD_HELP_TEXT("print info about registered barebox threads")
+	BAREBOX_CMD_HELP_TEXT("")
+	BAREBOX_CMD_HELP_TEXT("Options:")
+	BAREBOX_CMD_HELP_OPT ("-i", "Print information about registered bthreads")
+	BAREBOX_CMD_HELP_OPT ("-t", "measure how many bthreads we currently run in 1s")
+	BAREBOX_CMD_HELP_OPT ("-c", "count maximum context switches in 1s")
+	BAREBOX_CMD_HELP_OPT ("-v", "verify correct bthread operation")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(bthread)
+	.cmd = do_bthread,
+	BAREBOX_CMD_DESC("print info about registered bthreads")
+	BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+	BAREBOX_CMD_HELP(cmd_bthread_help)
+BAREBOX_CMD_END
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 16/16] RFC: led: migrate from poller to bthread
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (14 preceding siblings ...)
  2021-03-10  8:47 ` [PATCH v3 15/16] commands: add new bthread test command Ahmad Fatoum
@ 2021-03-10  8:48 ` Ahmad Fatoum
  2021-03-15  8:34 ` [PATCH v3 00/16] common: introduce bthreads, co-operative Sascha Hauer
  16 siblings, 0 replies; 18+ messages in thread
From: Ahmad Fatoum @ 2021-03-10  8:48 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov, Peter Korsgaard, Sascha Hauer

From: Ahmad Fatoum <ahmad@a3f.at>

Not meant for merge, just to show how a mechanical transformation of
poller to bthread would look like.

Note that this changes behavior slightly: The heartbeat duration was
not affected by the time needed to toggle the LED, but now it is.

Signed-off-by: Ahmad Fatoum <ahmad@a3f.at>
---
 drivers/led/core.c | 52 ++++++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 25 deletions(-)

diff --git a/drivers/led/core.c b/drivers/led/core.c
index ab171c61845b..cfdc6c894f74 100644
--- a/drivers/led/core.c
+++ b/drivers/led/core.c
@@ -21,7 +21,7 @@
 #include <errno.h>
 #include <led.h>
 #include <init.h>
-#include <poller.h>
+#include <bthread.h>
 #include <clock.h>
 #include <linux/ctype.h>
 
@@ -119,35 +119,34 @@ int led_set(struct led *led, unsigned int value)
 	return __led_set(led, value);
 }
 
-static void led_blink_func(struct poller_struct *poller)
+static int led_blink_func(void *data)
 {
 	struct led *led;
 
-	list_for_each_entry(led, &leds, list) {
-		const uint64_t now = get_time_ns();
-		int on;
+	while (!bthread_should_stop()) {
+		list_for_each_entry(led, &leds, list) {
+			int on;
 
-		if (!led->blink && !led->flash)
-			continue;
+			if (!led->blink && !led->flash)
+				continue;
 
-		if (led->blink_next_event > now) {
-			continue;
-		}
+			on = !(led->blink_next_state % 2);
+			if (on)
+				on = led->max_value;
 
-		on = !(led->blink_next_state % 2);
-		if (on)
-			on = led->max_value;
+			if (led->flash && !on)
+				led->flash = 0;
 
-		led->blink_next_event = now +
-			(led->blink_states[led->blink_next_state] * MSECOND);
-		led->blink_next_state = (led->blink_next_state + 1) %
-					led->blink_nr_states;
+			__led_set(led, on);
 
-		if (led->flash && !on)
-			led->flash = 0;
+			led->blink_next_state = (led->blink_next_state + 1) %
+				led->blink_nr_states;
 
-		__led_set(led, on);
+			mdelay(led->blink_states[led->blink_next_state]);
+		}
 	}
+
+	return 0;
 }
 
 /**
@@ -203,13 +202,16 @@ int led_flash(struct led *led, unsigned int duration_ms)
 	return 0;
 }
 
-static struct poller_struct led_poller = {
-	.func = led_blink_func,
-};
-
 static int led_blink_init(void)
 {
-	return poller_register(&led_poller, "led");
+	struct bthread *led_bthread;
+
+	led_bthread = bthread_create(led_blink_func, NULL, "led");
+	if (!led_bthread)
+		return -ENOMEM;
+
+	bthread_wake(led_bthread);
+	return 0;
 }
 late_initcall(led_blink_init);
 
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v3 00/16] common: introduce bthreads, co-operative
  2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
                   ` (15 preceding siblings ...)
  2021-03-10  8:48 ` [PATCH v3 16/16] RFC: led: migrate from poller to bthread Ahmad Fatoum
@ 2021-03-15  8:34 ` Sascha Hauer
  16 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2021-03-15  8:34 UTC (permalink / raw)
  To: Ahmad Fatoum; +Cc: barebox, Peter Mamonov, Peter Korsgaard

On Wed, Mar 10, 2021 at 09:47:44AM +0100, Ahmad Fatoum wrote:
> Current state of CONFIG_HAS_ARCH_SJLJ
> 
>     [x] arm 32-bit (Ahmad)
>     [x] arm 64-bit (Sascha)
>     [x] mips (Sascha)
>     [x] powerpc (Sascha)
>     [x] riscv (Sascha)
>     [x] sandbox (Ahmad)
>     [-] nios2 (Removed; Sascha)
>     [x] x86 32-bit (Ahmad)
>     [x] x86 64-bit (Ahmad)
>     [x] openrisc (Stafford)
>     [x] kvx (Jules)
> 
> Legend: [-] arch removed, [x] implemented
> 
> Changes since v2:
>   - Reworked bthread_reschedule(): Threads now always schedule the next
>     thread in the runqueue. Simplifies code and saves context switch back
>     to scheduler
>   - Removed assert_command_context yield. Will need further rework until
>     it's usable, so just warn for now like with pollers
>   - Added resched() to collect the reschedule bits in one place
>   - Migrate LED poller as an example
>   - Rework bthread command to use API better
>   - Split up commits for shorter, reworked, commit messages
>   - Fixed poor English and copy-paste errors (Peter Korsgaard)
>   - Marked RISC-V and MIPS CONFIG_HAS_ARCH_SJLJ explicitly 32-bit only
>     (Peter Mamonov)
>   - Added x86 implementations (tested on EFI x86_64 and i386 sandbox)

Applied, thanks

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2021-03-15  8:37 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-10  8:47 [PATCH v3 00/16] common: introduce bthreads, co-operative Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 01/16] common: introduce HAS_ARCH_SJLJ Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 02/16] ARM: asm: setjmp: annotate setjmp/longjmp for GCC Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 03/16] ARM: asm: setjmp: implement coroutine dependency initjmp() Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 04/16] sandbox: asm: implement setjmp/longjmp/initjmp Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 05/16] riscv: Add asm/asm.h Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 06/16] riscv: Add asm/linkage.h Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 07/16] riscv: Implement setjmp/longjmp/initjmp for RV32I Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 08/16] mips: Add linkage.h Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 09/16] mips: Implement setjmp/longjmp/initjmp for 32BIT Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 10/16] powerpc: Implement initjmp/setjmp/longjmp Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 11/16] x86: implement setjmp/longjmp/initjmp Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 12/16] common: poller: replace explicit calls to poller_call() with resched() Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 13/16] console: unconditionally run resched() in ctrlc() Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 14/16] common: introduce bthreads, co-operative barebox threads Ahmad Fatoum
2021-03-10  8:47 ` [PATCH v3 15/16] commands: add new bthread test command Ahmad Fatoum
2021-03-10  8:48 ` [PATCH v3 16/16] RFC: led: migrate from poller to bthread Ahmad Fatoum
2021-03-15  8:34 ` [PATCH v3 00/16] common: introduce bthreads, co-operative Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox