diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Kconfig | 5 | ||||
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/bthread.c | 59 | ||||
-rw-r--r-- | common/poller.c | 23 | ||||
-rw-r--r-- | common/sched.c | 26 | ||||
-rw-r--r-- | common/usbgadget.c | 36 |
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, ¤t->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, ¤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) +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, ¤t->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; |