* [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, ¤t->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, ¤t->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