summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2021-03-10 09:47:58 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2021-03-22 10:46:47 +0100
commit64242776de86d46d914aa8f3ab6cfee68420ca6a (patch)
tree33b339b551b65557d3f15c2af6e4beaae17da631 /include
parent7ce21703892fac7084d417d296fc2723a85e7c10 (diff)
downloadbarebox-64242776de86d46d914aa8f3ab6cfee68420ca6a.tar.gz
barebox-64242776de86d46d914aa8f3ab6cfee68420ca6a.tar.xz
common: introduce bthreads, co-operative barebox threads
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> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'include')
-rw-r--r--include/bthread.h53
-rw-r--r--include/poller.h2
-rw-r--r--include/sched.h3
-rw-r--r--include/slice.h17
4 files changed, 67 insertions, 8 deletions
diff --git a/include/bthread.h b/include/bthread.h
new file mode 100644
index 0000000000..e3871fb115
--- /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 db773265b2..371dafc6f8 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 43d239c3ef..57be1678fd 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 b2d65b80cd..cf684300a8 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