From 8588d6943eac18f7f8784fcc438b732ca35cd875 Mon Sep 17 00:00:00 2001 From: sakumisu <1203593632@qq.com> Date: Sat, 29 Jan 2022 23:21:04 +0800 Subject: [PATCH] add workqueue framework --- osal/usb_workq.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ osal/usb_workq.h | 27 ++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 osal/usb_workq.c create mode 100644 osal/usb_workq.h diff --git a/osal/usb_workq.c b/osal/usb_workq.c new file mode 100644 index 00000000..ab4279bd --- /dev/null +++ b/osal/usb_workq.c @@ -0,0 +1,92 @@ +#include "usb_list.h" +#include "usb_osal.h" +#include "usb_workq.h" +#include "usb_config.h" + +void usb_workqueue_submit(struct usb_workqueue *queue, struct usb_work *work, usb_worker_t worker, void *arg, uint32_t ticks) +{ + uint32_t flags; + flags = usb_osal_enter_critical_section(); + usb_dlist_remove(&work->list); + work->worker = worker; + work->arg = arg; + + if (ticks == 0) { + usb_dlist_insert_after(&queue->work_list, &work->list); + usb_osal_sem_give(queue->sem); + } + + usb_osal_leave_critical_section(flags); +} + +struct usb_workqueue g_hpworkq = { NULL }; +struct usb_workqueue g_lpworkq = { NULL }; + +static void usbh_hpwork_thread(void *argument) +{ + struct usb_work *work; + uint32_t flags; + int ret; + struct usb_workqueue *queue = (struct usb_workqueue *)argument; + while (1) { + ret = usb_osal_sem_take(queue->sem); + if (ret < 0) { + continue; + } + flags = usb_osal_enter_critical_section(); + if (usb_dlist_isempty(&queue->work_list)) { + usb_osal_leave_critical_section(flags); + continue; + } + work = usb_dlist_first_entry(&queue->work_list, struct usb_work, list); + usb_dlist_remove(&work->list); + usb_osal_leave_critical_section(flags); + work->worker(work->arg); + } +} + +static void usbh_lpwork_thread(void *argument) +{ + struct usb_work *work; + uint32_t flags; + int ret; + struct usb_workqueue *queue = (struct usb_workqueue *)argument; + while (1) { + ret = usb_osal_sem_take(queue->sem); + if (ret < 0) { + continue; + } + flags = usb_osal_enter_critical_section(); + if (usb_dlist_isempty(&queue->work_list)) { + usb_osal_leave_critical_section(flags); + continue; + } + work = usb_dlist_first_entry(&queue->work_list, struct usb_work, list); + usb_dlist_remove(&work->list); + usb_osal_leave_critical_section(flags); + work->worker(work->arg); + } +} + +int usbh_workq_initialize(void) +{ + g_hpworkq.sem = usb_osal_sem_create(0); + if (g_hpworkq.sem == NULL) { + return -1; + } + g_hpworkq.thread = usb_osal_thread_create("usbh_hpworkq", CONFIG_USBHOST_HPWORKQ_STACKSIZE, CONFIG_USBHOST_HPWORKQ_PRIO, usbh_hpwork_thread, &g_hpworkq); + if (g_hpworkq.thread == NULL) { + return -1; + } + + g_lpworkq.sem = usb_osal_sem_create(0); + if (g_lpworkq.sem == NULL) { + return -1; + } + + g_lpworkq.thread = usb_osal_thread_create("usbh_lpworkq", CONFIG_USBHOST_LPWORKQ_STACKSIZE, CONFIG_USBHOST_LPWORKQ_PRIO, usbh_lpwork_thread, &g_lpworkq); + if (g_lpworkq.thread == NULL) { + return -1; + } + return 0; +} diff --git a/osal/usb_workq.h b/osal/usb_workq.h new file mode 100644 index 00000000..4e20d93f --- /dev/null +++ b/osal/usb_workq.h @@ -0,0 +1,27 @@ +#ifndef _USB_WORKQUEUE_H +#define _USB_WORKQUEUE_H + +/* Defines the work callback */ +typedef void (*usb_worker_t)(void *arg); + +struct usb_work +{ + usb_dlist_t list; + usb_worker_t worker; + void *arg; +}; + +struct usb_workqueue +{ + usb_dlist_t work_list; + usb_dlist_t delay_work_list; + usb_osal_sem_t sem; + usb_osal_thread_t thread; +}; + +extern struct usb_workqueue g_hpworkq; +extern struct usb_workqueue g_lpworkq; + +void usb_workqueue_submit(struct usb_workqueue *queue, struct usb_work *work, usb_worker_t worker, void *arg, uint32_t ticks); +int usbh_workq_initialize(); +#endif \ No newline at end of file