From: darcagn <da...@us...> - 2024-04-29 17:47:21
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 9d93eadb528671d3f11fe84114aff0b5874754f5 (commit) via e2df806c4d9074544c1b37782988eb606d6e100c (commit) via d21b171a48930baf68ba5da6fb53d32e7d1a6feb (commit) via 8955282afe6ee15248175cd5acc44869f71a1bdf (commit) from a69d61cdf816bd520b873698ba26832dce49d496 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 9d93eadb528671d3f11fe84114aff0b5874754f5 Author: darcagn <da...@pr...> Date: Mon Apr 29 11:39:23 2024 -0600 Fix 'parameter name omitted' errors on older compilers (#531) commit e2df806c4d9074544c1b37782988eb606d6e100c Author: Donald Haase <qu...@ya...> Date: Mon Apr 29 13:37:37 2024 -0400 Patch newlib headers to expose lstat (#530) * Patch newlib headers to expose lstat, which we already support * Add patches for exposing lstat in Newlib 2.0.0 and 3.3.0 * Fix unexpected end of line error in Newlib 4.4.0 patch --------- Co-authored-by: QuzarDC <qu...@co...> Co-authored-by: darcagn <da...@pr...> commit d21b171a48930baf68ba5da6fb53d32e7d1a6feb Author: darcagn <da...@pr...> Date: Sun Apr 28 02:31:13 2024 -0600 Update GCC configurations and patches for new separate GCC 15 and 14 branches, D support, and building m4-single support (#526) commit 8955282afe6ee15248175cd5acc44869f71a1bdf Author: Paul Cercueil <pa...@cr...> Date: Sat Apr 27 22:10:38 2024 +0200 Worker threads (#505) * thread: Add worker threads Worker threads are threads that are associated to a given work function. When notified (through thd_worker_notify()), the worker thread will call its work function. This is useful for implementing asynchronous function calls. It is especially useful to implement threaded interrupt handlers. Signed-off-by: Paul Cercueil <pa...@cr...> * asic: Use worker thread to implement threaded interrupt handlers Most of the threaded interrupt handler code was duplicated vs. the worker thread code. Update the ASIC code to now use the worker thread API instead. Signed-off-by: Paul Cercueil <pa...@cr...> * thread: Add optional jobs API for use with worker threads Using this API, the program can enqueue specific jobs to the worker threads, and dequeue them in their respective work function, in a FIFO fashion. Signed-off-by: Paul Cercueil <pa...@cr...> * thread: Add explicit constructor for worker threads Add thd_worker_create_ex() which takes an extra parameter that can be used to specify the thread's attributes. Signed-off-by: Paul Cercueil <pa...@cr...> * Update include/kos/worker_thread.h --------- Signed-off-by: Paul Cercueil <pa...@cr...> Co-authored-by: Falco Girgis <gyr...@gm...> Co-authored-by: darcagn <da...@pr...> ----------------------------------------------------------------------- Summary of changes: doc/CHANGELOG | 1 + include/kos/worker_thread.h | 156 +++++++++++++++++++++ kernel/arch/dreamcast/hardware/asic.c | 50 ++----- kernel/arch/dreamcast/hardware/maple/controller.c | 4 +- kernel/arch/dreamcast/hardware/maple/dreameye.c | 16 ++- kernel/arch/dreamcast/hardware/maple/keyboard.c | 4 +- kernel/arch/dreamcast/hardware/maple/mouse.c | 4 +- kernel/arch/dreamcast/hardware/maple/purupuru.c | 4 +- kernel/arch/dreamcast/hardware/maple/sip.c | 12 +- kernel/arch/dreamcast/hardware/maple/vmu.c | 20 ++- kernel/thread/Makefile | 1 + kernel/thread/worker.c | 123 ++++++++++++++++ utils/dc-chain/config/README.md | 1 + utils/dc-chain/config/config.mk.10.5.0.sample | 28 ++-- utils/dc-chain/config/config.mk.11.4.0.sample | 28 ++-- utils/dc-chain/config/config.mk.12.3.0.sample | 28 ++-- utils/dc-chain/config/config.mk.13.2.1-dev.sample | 3 +- utils/dc-chain/config/config.mk.14.0.1-dev.sample | 36 ++--- ....2.1-dev.sample => config.mk.15.0.0-dev.sample} | 12 +- .../dc-chain/config/config.mk.4.7.4-legacy.sample | 28 ++-- .../dc-chain/config/config.mk.9.3.0-legacy.sample | 28 ++-- utils/dc-chain/config/config.mk.9.5.0-winxp.sample | 28 ++-- utils/dc-chain/config/config.mk.stable.sample | 28 ++-- utils/dc-chain/patches/gcc-13.2.1-kos.diff | 4 +- utils/dc-chain/patches/gcc-14.0.1-kos.diff | 59 +------- .../{gcc-13.1.0-kos.diff => gcc-15.0.0-kos.diff} | 56 ++++---- utils/dc-chain/patches/newlib-2.0.0-kos.diff | 13 ++ utils/dc-chain/patches/newlib-3.3.0-kos.diff | 13 ++ .../patches/newlib-4.3.0.20230120-kos.diff | 13 ++ .../patches/newlib-4.4.0.20231231-kos.diff | 15 ++ 30 files changed, 560 insertions(+), 256 deletions(-) create mode 100644 include/kos/worker_thread.h create mode 100644 kernel/thread/worker.c copy utils/dc-chain/config/{config.mk.13.2.1-dev.sample => config.mk.15.0.0-dev.sample} (96%) copy utils/dc-chain/patches/{gcc-13.1.0-kos.diff => gcc-15.0.0-kos.diff} (68%) diff --git a/doc/CHANGELOG b/doc/CHANGELOG index 7a1706e0..cb37cfe0 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -222,6 +222,7 @@ KallistiOS version 2.1.0 ----------------------------------------------- - DC Add support for French AZERTY keyboards [PC] - DC Increased the resolution of pvr_stats_t from milli to nanoseconds [FG] - *** Added support for modifying scheduler frequency at runtime [FG] +- *** Add support for worker threads [PC] KallistiOS version 2.0.0 ----------------------------------------------- - DC Broadband Adapter driver fixes [Megan Potter == MP] diff --git a/include/kos/worker_thread.h b/include/kos/worker_thread.h new file mode 100644 index 00000000..2ec940e8 --- /dev/null +++ b/include/kos/worker_thread.h @@ -0,0 +1,156 @@ +/* KallistiOS ##version## + + include/kos/worker_thread.h + Copyright (C) 2024 Paul Cercueil +*/ + +/** \file kos/worker_thread.h + \brief Threaded worker support. + \ingroup kthreads + + This file contains the threaded worker API. Threaded workers are threads + that are idle most of the time, until they are notified that there is work + pending; in which case they will call their associated work function. + + The work function can then process any number of tasks, until it clears out + all of its tasks or decides that it worked enough; in which case the + function can return, and will re-start the next time it is notified, or if + it was notified while it was running. + + An optional API is also present, which provides a FIFO for jobs to be + processed by the threaded worker. This is useful when jobs have to be + processed in sequence. + + \author Paul Cercueil + + \see kos/thread.h +*/ + +#ifndef __KOS_WORKER_THREAD_H +#define __KOS_WORKER_THREAD_H + +#include <sys/cdefs.h> +__BEGIN_DECLS + +#include <kos/thread.h> +#include <sys/queue.h> + +struct kthread_worker; + +/** \brief Structure describing one worker thread. + + \headerfile kos/thread.h +*/ +typedef struct kthread_worker kthread_worker_t; + +/** \brief Structure describing one job for the worker. */ +typedef struct kthread_job { + /** \brief List handle. */ + STAILQ_ENTRY(kthread_job) entry; + + /** \brief User pointer to the work data. */ + void *data; +} kthread_job_t; + +/** \brief Create a new worker thread with the specific set of attributes. + \relatesalso kthread_worker_t + + This function will create a thread with the specified attributes that will + call the given routine with the given param pointer when notified. + The thread will only stop when thd_worker_destroy() is called. + + \param attr A set of thread attributes for the created thread. + Passing NULL will initialize all attributes to their + default values. + \param routine The function to call in the worker thread. + \param data A parameter to pass to the function called. + + \return The new worker thread on success, NULL on failure. + + \sa thd_worker_destroy, thd_worker_wakeup +*/ +kthread_worker_t *thd_worker_create_ex(const kthread_attr_t *attr, + void (*routine)(void *), void *data); + +/** \brief Create a new worker thread. + \relatesalso kthread_worker_t + + This function will create a thread with the default attributes that will + call the given routine with the given param pointer when notified. + The thread will only stop when thd_worker_destroy() is called. + + \param routine The function to call in the worker thread. + \param data A parameter to pass to the function called. + + \return The new worker thread on success, NULL on failure. + + \sa thd_worker_destroy, thd_worker_wakeup +*/ +static inline kthread_worker_t * +thd_worker_create(void (*routine)(void *), void *data) { + return thd_worker_create_ex(NULL, routine, data); +} + +/** \brief Stop and destroy a worker thread. + \relatesalso kthread_worker_t + + This function will stop the worker thread and free its memory. + + \param thd The worker thread to destroy. + + \sa thd_worker_create, thd_worker_wakeup +*/ +void thd_worker_destroy(kthread_worker_t *thd); + +/** \brief Wake up a worker thread. + \relatesalso kthread_worker_t + + This function will wake up the worker thread, causing it to call its + corresponding work function. Usually, this should be called after a new + job has been added with thd_worker_add_job(). + + \param thd The worker thread to wake up. + + \sa thd_worker_create, thd_worker_destroy, thd_worker_add_job +*/ +void thd_worker_wakeup(kthread_worker_t *thd); + +/** \brief Get a handle to the underlying thread. + \relatesalso kthread_worker_t + + \param thd The worker thread whose handle should be returned. + + \return A handle to the underlying thread. +*/ +kthread_t *thd_worker_get_thread(kthread_worker_t *thd); + +/** \brief Add a new job to the worker thread. + \relatesalso kthread_worker_t + + This function will append the job to the worker thread's to-do queue. + Note that it is the responsability of the work function (the one passed to + thd_worker_create()) to dequeue and process the jobs with + thd_worker_dequeue_job(). Also, this function won't automatically notify the + worker thread - you still need to call thd_worker_wakeup(). + + \param thd The worker thread to add a job to. + \param job The new job to give to the worker thread. +*/ +void thd_worker_add_job(kthread_worker_t *thd, kthread_job_t *job); + +/** \brief Dequeue one job from the worker thread's to-do queue. + \relatesalso kthread_worker_t + + Use this function to dequeue one job from the worker thread, that has been + previously queued using thd_worker_add_job(). This function is typically + used inside the work function registered with thd_worker_create(). + + \param thd The worker thread to add a job to. + + \return A new job to process, or NULL if there is none. +*/ +kthread_job_t *thd_worker_dequeue_job(kthread_worker_t *worker); + +__END_DECLS + +#endif /* __KOS_WORKER_THREAD_H */ diff --git a/kernel/arch/dreamcast/hardware/asic.c b/kernel/arch/dreamcast/hardware/asic.c index 3bc486c6..529ec77a 100644 --- a/kernel/arch/dreamcast/hardware/asic.c +++ b/kernel/arch/dreamcast/hardware/asic.c @@ -102,6 +102,7 @@ #include <dc/asic.h> #include <arch/spinlock.h> #include <kos/genwait.h> +#include <kos/worker_thread.h> /* XXX These based on g1ata.c and pvr.h and should be replaced by a standardized method */ #define IN32(addr) (* ( (volatile uint32_t *)(addr) ) ) @@ -121,11 +122,8 @@ typedef struct { struct asic_thdata { asic_evt_handler hdl; uint32_t source; - kthread_t *thd; - int genwait_obj; + kthread_worker_t *worker; void *data; - volatile bool quit; - volatile bool pending; void (*ack_and_mask)(uint16_t); void (*unmask)(uint16_t); }; @@ -253,29 +251,13 @@ void asic_shutdown(void) { asic_evt_shutdown(); } -static void * asic_threaded_irq(void *data) { +static void asic_threaded_irq(void *data) { struct asic_thdata *thdata = data; - int flags; - - for (;;) { - flags = irq_disable(); - - if (!thdata->pending) - genwait_wait(&thdata->genwait_obj, thdata->thd->label, 0, NULL); - - irq_restore(flags); - if (thdata->quit) - break; + thdata->hdl(thdata->source, thdata->data); - thdata->pending = false; - thdata->hdl(thdata->source, thdata->data); - - if (thdata->unmask) - thdata->unmask(thdata->source); - } - - return NULL; + if (thdata->unmask) + thdata->unmask(thdata->source); } static void asic_thirq_dispatch(uint32_t source, void *data) { @@ -286,8 +268,7 @@ static void asic_thirq_dispatch(uint32_t source, void *data) { thdata->source = source; - thdata->pending = true; - genwait_wake_one(&thdata->genwait_obj); + thd_worker_wakeup(thdata->worker); } int asic_evt_request_threaded_handler(uint16_t code, asic_evt_handler hnd, @@ -297,6 +278,7 @@ int asic_evt_request_threaded_handler(uint16_t code, asic_evt_handler hnd, { struct asic_thdata *thdata; uint32_t flags; + kthread_t *thd; thdata = malloc(sizeof(*thdata)); if (!thdata) @@ -304,27 +286,26 @@ int asic_evt_request_threaded_handler(uint16_t code, asic_evt_handler hnd, thdata->hdl = hnd; thdata->data = data; - thdata->quit = false; - thdata->pending = false; thdata->ack_and_mask = ack_and_mask; thdata->unmask = unmask; flags = irq_disable(); - thdata->thd = thd_create(0, asic_threaded_irq, thdata); - if (!thdata->thd) { + thdata->worker = thd_worker_create(asic_threaded_irq, thdata); + if (!thdata->worker) { irq_restore(flags); free(thdata); return -1; /* TODO: What return code? */ } /* Set a reasonable name to ID the thread */ - snprintf(thdata->thd->label, KTHREAD_LABEL_SIZE, + thd = thd_worker_get_thread(thdata->worker); + snprintf(thd->label, KTHREAD_LABEL_SIZE, "Threaded IRQ code: 0x%x evt: 0x%.4x", ((code >> 16) & 0xf), (code & 0xffff)); /* Highest priority */ - //thd_set_prio(thdata->thd, 0); + //thd_set_prio(thd, 0); asic_evt_set_handler(code, asic_thirq_dispatch, thdata); @@ -347,11 +328,8 @@ void asic_evt_remove_handler(uint16_t code) if (entry.hdl == asic_thirq_dispatch) { thdata = entry.data; - thdata->quit = true; - - genwait_wake_one(&thdata->genwait_obj); - thd_join(thdata->thd, NULL); + thd_worker_destroy(thdata->worker); free(thdata); } } diff --git a/kernel/arch/dreamcast/hardware/maple/controller.c b/kernel/arch/dreamcast/hardware/maple/controller.c index f6678c1f..1db9bfa0 100644 --- a/kernel/arch/dreamcast/hardware/maple/controller.c +++ b/kernel/arch/dreamcast/hardware/maple/controller.c @@ -49,7 +49,9 @@ void cont_btn_callback(uint8_t addr, uint32_t btns, cont_btn_callback_t cb) { } /* Response callback for the GETCOND Maple command. */ -static void cont_reply(maple_state_t *, maple_frame_t *frm) { +static void cont_reply(maple_state_t *st, maple_frame_t *frm) { + (void)st; + maple_response_t *resp; uint32_t *respbuf; cont_cond_t *raw; diff --git a/kernel/arch/dreamcast/hardware/maple/dreameye.c b/kernel/arch/dreamcast/hardware/maple/dreameye.c index fad5d40e..94c9cde8 100644 --- a/kernel/arch/dreamcast/hardware/maple/dreameye.c +++ b/kernel/arch/dreamcast/hardware/maple/dreameye.c @@ -19,7 +19,9 @@ static int dreameye_send_get_image(maple_device_t *dev, static dreameye_state_t *first_state = NULL; -static void dreameye_get_image_count_cb(maple_state_t *, maple_frame_t *frame) { +static void dreameye_get_image_count_cb(maple_state_t *st, maple_frame_t *frame) { + (void)st; + dreameye_state_t *de; maple_response_t *resp; uint32 *respbuf32; @@ -59,7 +61,9 @@ static void dreameye_get_image_count_cb(maple_state_t *, maple_frame_t *frame) { genwait_wake_all(frame); } -static void dreameye_get_transfer_count_cb(maple_state_t *, maple_frame_t *frame) { +static void dreameye_get_transfer_count_cb(maple_state_t *st, maple_frame_t *frame) { + (void)st; + dreameye_state_t *de; maple_response_t *resp; uint32 *respbuf32; @@ -139,7 +143,9 @@ int dreameye_get_image_count(maple_device_t *dev, int block) { return MAPLE_EOK; } -static void dreameye_get_image_cb(maple_state_t *, maple_frame_t *frame) { +static void dreameye_get_image_cb(maple_state_t *st, maple_frame_t *frame) { + (void)st; + maple_device_t *dev; maple_response_t *resp; uint32 *respbuf32; @@ -327,7 +333,9 @@ fail: return MAPLE_EFAIL; } -static void dreameye_erase_cb(maple_state_t *, maple_frame_t *frame) { +static void dreameye_erase_cb(maple_state_t *st, maple_frame_t *frame) { + (void)st; + maple_response_t *resp; uint8 *respbuf; diff --git a/kernel/arch/dreamcast/hardware/maple/keyboard.c b/kernel/arch/dreamcast/hardware/maple/keyboard.c index 1162c6db..9fdb04aa 100644 --- a/kernel/arch/dreamcast/hardware/maple/keyboard.c +++ b/kernel/arch/dreamcast/hardware/maple/keyboard.c @@ -580,7 +580,9 @@ static void kbd_check_poll(maple_frame_t *frm) { } } -static void kbd_reply(maple_state_t *, maple_frame_t *frm) { +static void kbd_reply(maple_state_t *st, maple_frame_t *frm) { + (void)st; + maple_response_t *resp; uint32 *respbuf; kbd_state_t *state; diff --git a/kernel/arch/dreamcast/hardware/maple/mouse.c b/kernel/arch/dreamcast/hardware/maple/mouse.c index 662fbe96..94a13c35 100644 --- a/kernel/arch/dreamcast/hardware/maple/mouse.c +++ b/kernel/arch/dreamcast/hardware/maple/mouse.c @@ -9,7 +9,9 @@ #include <string.h> #include <assert.h> -static void mouse_reply(maple_state_t *, maple_frame_t *frm) { +static void mouse_reply(maple_state_t *st, maple_frame_t *frm) { + (void)st; + maple_response_t *resp; uint32 *respbuf; mouse_cond_t *raw; diff --git a/kernel/arch/dreamcast/hardware/maple/purupuru.c b/kernel/arch/dreamcast/hardware/maple/purupuru.c index a6a93d3a..40e93ef8 100644 --- a/kernel/arch/dreamcast/hardware/maple/purupuru.c +++ b/kernel/arch/dreamcast/hardware/maple/purupuru.c @@ -14,7 +14,9 @@ /* Be warned, not all purus are created equal, in fact, most of them act different for just about everything you feed to them. */ -static void purupuru_rumble_cb(maple_state_t *, maple_frame_t *frame) { +static void purupuru_rumble_cb(maple_state_t *st, maple_frame_t *frame) { + (void)st; + /* Unlock the frame */ maple_frame_unlock(frame); diff --git a/kernel/arch/dreamcast/hardware/maple/sip.c b/kernel/arch/dreamcast/hardware/maple/sip.c index c6a7ad70..7ad55b0f 100644 --- a/kernel/arch/dreamcast/hardware/maple/sip.c +++ b/kernel/arch/dreamcast/hardware/maple/sip.c @@ -15,7 +15,9 @@ #define SIP_START_SAMPLING 0x80 -static void sip_start_sampling_cb(maple_state_t *, maple_frame_t *frame) { +static void sip_start_sampling_cb(maple_state_t *st, maple_frame_t *frame) { + (void)st; + sip_state_t *sip; maple_response_t *resp; @@ -36,7 +38,9 @@ static void sip_start_sampling_cb(maple_state_t *, maple_frame_t *frame) { genwait_wake_all(frame); } -static void sip_stop_sampling_cb(maple_state_t *, maple_frame_t *frame) { +static void sip_stop_sampling_cb(maple_state_t *st, maple_frame_t *frame) { + (void)st; + sip_state_t *sip; maple_response_t *resp; @@ -207,7 +211,9 @@ int sip_stop_sampling(maple_device_t *dev, int block) { return MAPLE_EOK; } -static void sip_reply(maple_state_t *, maple_frame_t *frm) { +static void sip_reply(maple_state_t *st, maple_frame_t *frm) { + (void)st; + maple_response_t *resp; uint32 *respbuf; sip_state_t *sip; diff --git a/kernel/arch/dreamcast/hardware/maple/vmu.c b/kernel/arch/dreamcast/hardware/maple/vmu.c index eb9e8792..d1854fcb 100644 --- a/kernel/arch/dreamcast/hardware/maple/vmu.c +++ b/kernel/arch/dreamcast/hardware/maple/vmu.c @@ -63,7 +63,9 @@ static int vmu_attach(maple_driver_t *drv, maple_device_t *dev) { return 0; } -static void vmu_poll_reply(maple_state_t *, maple_frame_t *frm) { +static void vmu_poll_reply(maple_state_t *st, maple_frame_t *frm) { + (void)st; + maple_response_t *resp; uint32_t *respbuf; vmu_cond_t *raw; @@ -264,7 +266,9 @@ int vmu_set_icon_shape(maple_device_t *dev, uint8_t icon_shape) { can stay the same */ /* Callback that unlocks the frame, general use */ -static void vmu_gen_callback(maple_state_t *, maple_frame_t *frame) { +static void vmu_gen_callback(maple_state_t *st, maple_frame_t *frame) { + (void)st; + /* Unlock the frame for the next usage */ maple_frame_unlock(frame); @@ -412,7 +416,9 @@ void vmu_set_icon(const char *vmu_icon) { /* Read the data in block blocknum into buffer, return a -1 if an error occurs, for now we ignore MAPLE_RESPONSE_FILEERR, which will be changed shortly */ -static void vmu_block_read_callback(maple_state_t *, maple_frame_t *frm) { +static void vmu_block_read_callback(maple_state_t *st, maple_frame_t *frm) { + (void)st; + ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |