summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Kconfig5
-rw-r--r--common/Makefile1
-rw-r--r--common/bthread.c59
-rw-r--r--common/poller.c23
-rw-r--r--common/sched.c26
-rw-r--r--common/usbgadget.c36
6 files changed, 107 insertions, 43 deletions
diff --git a/common/Kconfig b/common/Kconfig
index 9c9e0525e2..a9feae2ae8 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -997,11 +997,16 @@ config BAREBOXCRC32_TARGET
'bareboxcrc32' is a userspacetool to generate the crc32 checksums the same way
barebox does. Say yes here to build it for the target.
+config HAS_SCHED
+ bool
+
config POLLER
bool "generic polling infrastructure"
+ select HAS_SCHED
config BTHREAD
bool "barebox co-operative (green) thread infrastructure"
+ select HAS_SCHED
depends on HAS_ARCH_SJLJ
help
barebox threads are lightweight cooperative (green) threads that are
diff --git a/common/Makefile b/common/Makefile
index daa022ff54..4b45f678c7 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -51,6 +51,7 @@ extra-$(CONFIG_MODULES) += module.lds
obj-$(CONFIG_OFTREE) += oftree.o
obj-$(CONFIG_PARTITION_DISK) += partitions.o partitions/
obj-$(CONFIG_PASSWORD) += password.o
+obj-$(CONFIG_HAS_SCHED) += sched.o
obj-$(CONFIG_POLLER) += poller.o
obj-$(CONFIG_BTHREAD) += bthread.o
obj-$(CONFIG_RESET_SOURCE) += reset_source.o
diff --git a/common/bthread.c b/common/bthread.c
index c811797130..46e6987149 100644
--- a/common/bthread.c
+++ b/common/bthread.c
@@ -20,11 +20,8 @@
#endif
static struct bthread {
- int (*threadfn)(void *);
- union {
- void *data;
- int ret;
- };
+ void (*threadfn)(void *);
+ void *data;
char *name;
jmp_buf jmp_buf;
void *stack;
@@ -35,10 +32,12 @@ static struct bthread {
#endif
u8 awake :1;
u8 should_stop :1;
+ u8 should_clean :1;
u8 has_stopped :1;
} main_thread = {
.list = LIST_HEAD_INIT(main_thread.list),
.name = "main",
+ .awake = true,
};
struct bthread *current = &main_thread;
@@ -54,7 +53,7 @@ static void __noreturn bthread_trampoline(void)
finish_switch_fiber(current);
bthread_reschedule();
- current->ret = current->threadfn(current->data);
+ current->threadfn(current->data);
bthread_suspend(current);
current->has_stopped = true;
@@ -69,7 +68,7 @@ bool bthread_is_main(struct bthread *bthread)
return bthread == &main_thread;
}
-void bthread_free(struct bthread *bthread)
+static void bthread_free(struct bthread *bthread)
{
free(bthread->stack);
free(bthread->name);
@@ -81,7 +80,7 @@ const char *bthread_name(struct bthread *bthread)
return bthread->name;
}
-struct bthread *bthread_create(int (*threadfn)(void *), void *data,
+struct bthread *bthread_create(void (*threadfn)(void *), void *data,
const char *namefmt, ...)
{
struct bthread *bthread;
@@ -107,6 +106,8 @@ struct bthread *bthread_create(int (*threadfn)(void *), void *data,
if (len < 0)
goto err;
+ list_add_tail(&bthread->list, &current->list);
+
/* set up bthread context with the new stack */
initjmp(bthread->jmp_buf, bthread_trampoline,
bthread->stack + CONFIG_STACK_SIZE);
@@ -117,30 +118,38 @@ err:
return NULL;
}
+void *bthread_data(struct bthread *bthread)
+{
+ return bthread->data;
+}
+
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)
+void bthread_cancel(struct bthread *bthread)
+{
+ bthread->should_stop = true;
+ bthread->should_clean = true;
+}
+
+void __bthread_stop(struct bthread *bthread)
{
bthread->should_stop = true;
+ pr_debug("waiting for %s to stop\n", bthread->name);
+
while (!bthread->has_stopped)
bthread_reschedule();
- return bthread->ret;
+ list_del(&bthread->list);
+ bthread_free(bthread);
}
int bthread_should_stop(void)
@@ -163,7 +172,23 @@ void bthread_info(void)
void bthread_reschedule(void)
{
- bthread_schedule(list_next_entry(current, list));
+ struct bthread *next, *tmp;
+
+ if (current == list_next_entry(current, list))
+ return;
+
+ list_for_each_entry_safe(next, tmp, &current->list, list) {
+ if (next->awake) {
+ pr_debug("switch %s -> %s\n", current->name, next->name);
+ bthread_schedule(next);
+ return;
+ }
+ if (next->has_stopped && next->should_clean) {
+ pr_debug("deleting %s\n", next->name);
+ list_del(&next->list);
+ bthread_free(next);
+ }
+ }
}
void bthread_schedule(struct bthread *to)
diff --git a/common/poller.c b/common/poller.c
index 61da5698d2..0409d3cf81 100644
--- a/common/poller.c
+++ b/common/poller.c
@@ -10,11 +10,14 @@
#include <param.h>
#include <poller.h>
#include <clock.h>
-#include <work.h>
-#include <slice.h>
static LIST_HEAD(poller_list);
-int poller_active;
+static int __poller_active;
+
+bool poller_active(void)
+{
+ return __poller_active;
+}
int poller_register(struct poller_struct *poller, const char *name)
{
@@ -110,23 +113,13 @@ int poller_async_unregister(struct poller_async *pa)
void poller_call(void)
{
struct poller_struct *poller, *tmp;
- bool run_workqueues = !slice_acquired(&command_slice);
-
- if (poller_active)
- return;
-
- command_slice_acquire();
-
- if (run_workqueues)
- wq_do_all_works();
- poller_active = 1;
+ __poller_active = 1;
list_for_each_entry_safe(poller, tmp, &poller_list, list)
poller->func(poller);
- command_slice_release();
- poller_active = 0;
+ __poller_active = 0;
}
#if defined CONFIG_CMD_POLLER
diff --git a/common/sched.c b/common/sched.c
new file mode 100644
index 0000000000..02582b2c5e
--- /dev/null
+++ b/common/sched.c
@@ -0,0 +1,26 @@
+/* SPDX License Identifier: GPL-2.0 */
+
+#include <bthread.h>
+#include <poller.h>
+#include <work.h>
+#include <slice.h>
+#include <sched.h>
+
+void resched(void)
+{
+ bool run_workqueues = !slice_acquired(&command_slice);
+
+ if (poller_active())
+ return;
+
+ command_slice_acquire();
+
+ if (run_workqueues) {
+ wq_do_all_works();
+ bthread_reschedule();
+ }
+
+ poller_call();
+
+ command_slice_release();
+}
diff --git a/common/usbgadget.c b/common/usbgadget.c
index d4437b5169..34a685234b 100644
--- a/common/usbgadget.c
+++ b/common/usbgadget.c
@@ -48,36 +48,43 @@ static inline struct file_list *get_dfu_function(void)
return NULL;
}
-int usbgadget_register(bool dfu, const char *dfu_opts,
- bool fastboot, const char *fastboot_opts,
- bool acm, bool export_bbu)
+int usbgadget_register(const struct usbgadget_funcs *funcs)
{
int ret;
+ int flags = funcs->flags;
struct device_d *dev;
struct f_multi_opts *opts;
opts = xzalloc(sizeof(*opts));
opts->release = usb_multi_opts_release;
- if (dfu) {
- opts->dfu_opts.files = parse(dfu_opts);
+ if (flags & USBGADGET_DFU) {
+ opts->dfu_opts.files = parse(funcs->dfu_opts);
if (IS_ENABLED(CONFIG_USB_GADGET_DFU) && file_list_empty(opts->dfu_opts.files)) {
file_list_free(opts->dfu_opts.files);
opts->dfu_opts.files = get_dfu_function();
}
}
- if (fastboot) {
- opts->fastboot_opts.files = parse(fastboot_opts);
+ if (flags & USBGADGET_MASS_STORAGE) {
+ opts->ums_opts.files = parse(funcs->ums_opts);
+ if (IS_ENABLED(CONFIG_USB_GADGET_MASS_STORAGE) && file_list_empty(opts->ums_opts.files)) {
+ file_list_free(opts->ums_opts.files);
+ opts->ums_opts.files = system_partitions_get();
+ }
+ }
+
+ if (flags & USBGADGET_FASTBOOT) {
+ opts->fastboot_opts.files = parse(funcs->fastboot_opts);
if (IS_ENABLED(CONFIG_FASTBOOT_BASE) && file_list_empty(opts->fastboot_opts.files)) {
file_list_free(opts->fastboot_opts.files);
opts->fastboot_opts.files = get_fastboot_partitions();
}
- opts->fastboot_opts.export_bbu = export_bbu;
+ opts->fastboot_opts.export_bbu = flags & USBGADGET_EXPORT_BBU;
}
- opts->create_acm = acm;
+ opts->create_acm = flags & USBGADGET_ACM;
if (usb_multi_count_functions(opts) == 0) {
pr_warn("No functions to register\n");
@@ -111,14 +118,21 @@ err:
static int usbgadget_autostart_set(struct param_d *param, void *ctx)
{
+ struct usbgadget_funcs funcs = {};
static bool started;
- bool fastboot_bbu = get_fastboot_bbu();
int err;
if (!autostart || started)
return 0;
- err = usbgadget_register(true, NULL, true, NULL, acm, fastboot_bbu);
+ if (get_fastboot_bbu())
+ funcs.flags |= USBGADGET_EXPORT_BBU;
+ if (acm)
+ funcs.flags |= USBGADGET_ACM;
+
+ funcs.flags |= USBGADGET_DFU | USBGADGET_FASTBOOT | USBGADGET_MASS_STORAGE;
+
+ err = usbgadget_register(&funcs);
if (!err)
started = true;