From: ljsebald <ljs...@us...> - 2023-08-30 21:52:35
|
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 df51ca01ed93f7c291538e1c7097e1eb24c41770 (commit) via 6a7dee98f39d5a4876f625430ad7ad631b5f2287 (commit) from 7094048da2d2c90301611fb963473702f281ef8e (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 df51ca01ed93f7c291538e1c7097e1eb24c41770 Author: darcagn <da...@pr...> Date: Wed Aug 30 16:50:58 2023 -0500 Fix warnings when building examples with -flto (#284) * Fix warning in png example when compiling with -flto * Fix maybe uninitialized warning in dreameye-sd example when compiling with -flto * Fix warning in keytest example when compiling with -flto commit 6a7dee98f39d5a4876f625430ad7ad631b5f2287 Author: Falco Girgis <gyr...@gm...> Date: Wed Aug 30 16:50:20 2023 -0500 Added Spinlock Example/Test (#275) * Added spinlock_test example/test for spinlocks - Created a new example that also flexes the spinlock implementation, demonstrating both gaining control of a lock by "trying" until successful or locking until it becomes available. * Update spinlock_test.c Missing space after { for fib(). * Update spinlock_test.c Logic mistake in checking for issues at the end. * Apply suggestions from code review Co-authored-by: Lawrence Sebald <ljs...@us...> ----------------------------------------------------------------------- Summary of changes: examples/dreamcast/basic/threading/Makefile | 3 + .../threading/spinlock_test}/Makefile | 9 +- .../basic/threading/spinlock_test/spinlock_test.c | 152 +++++++++++++++++++++ examples/dreamcast/dreameye/sd/dreameye-sd.c | 2 +- examples/dreamcast/keyboard/keytest/keytest.c | 24 ++-- examples/dreamcast/png/example.c | 2 +- 6 files changed, 174 insertions(+), 18 deletions(-) copy examples/dreamcast/{video/bfont => basic/threading/spinlock_test}/Makefile (69%) create mode 100644 examples/dreamcast/basic/threading/spinlock_test/spinlock_test.c diff --git a/examples/dreamcast/basic/threading/Makefile b/examples/dreamcast/basic/threading/Makefile index 7e7dd2d..fd7482f 100644 --- a/examples/dreamcast/basic/threading/Makefile +++ b/examples/dreamcast/basic/threading/Makefile @@ -10,6 +10,7 @@ all: $(KOS_MAKE) -C recursive_lock $(KOS_MAKE) -C once $(KOS_MAKE) -C tls + $(KOS_MAKE) -C spinlock_test clean: $(KOS_MAKE) -C general clean @@ -17,6 +18,7 @@ clean: $(KOS_MAKE) -C recursive_lock clean $(KOS_MAKE) -C once clean $(KOS_MAKE) -C tls clean + $(KOS_MAKE) -C spinlock_test clean dist: $(KOS_MAKE) -C general dist @@ -24,4 +26,5 @@ dist: $(KOS_MAKE) -C recursive_lock dist $(KOS_MAKE) -C once dist $(KOS_MAKE) -C tls dist + $(KOS_MAKE) -C spinlock_test dist diff --git a/examples/dreamcast/video/bfont/Makefile b/examples/dreamcast/basic/threading/spinlock_test/Makefile similarity index 69% copy from examples/dreamcast/video/bfont/Makefile copy to examples/dreamcast/basic/threading/spinlock_test/Makefile index 67462af..403f45f 100644 --- a/examples/dreamcast/video/bfont/Makefile +++ b/examples/dreamcast/basic/threading/spinlock_test/Makefile @@ -1,11 +1,12 @@ # KallistiOS ##version## # -# basic/bfont/Makefile -# (c)2002 Megan Potter +# basic/threading/spinlock_test/Makefile +# +# Copyright (C) 2023 Falco Girgis # -TARGET = bfont.elf -OBJS = bfont.o +TARGET = spinlock_test.elf +OBJS = spinlock_test.o all: rm-elf $(TARGET) diff --git a/examples/dreamcast/basic/threading/spinlock_test/spinlock_test.c b/examples/dreamcast/basic/threading/spinlock_test/spinlock_test.c new file mode 100644 index 0000000..372d9ee --- /dev/null +++ b/examples/dreamcast/basic/threading/spinlock_test/spinlock_test.c @@ -0,0 +1,152 @@ +/* KallistiOS ##version## + + spinlock_test.c + + Copyright (C) 2023 Falco Girgis + + This file is a simple example of the different + ways in which to use a spinlock. It serves two + purposes: + + 1) To demonstrate their usage + 2) To serve as a test for KOS's implementation + + Multiple threads are spawned and then take turns + waiting for the spinlock to become available, using + two different methods of waiting. + */ + +#include <kos.h> +#include <stdlib.h> +#include <arch/spinlock.h> + +/* + Simple macro that calls printf and immediately flushes its + buffer so we don't have to wait for it to fill before seeing + a thread's output. +*/ +#define print(...) \ + do { \ + printf(__VA_ARGS__); \ + fflush(stdout); \ + } while(0) + + +/* The counter out threads will be competing for access to */ +static uint32_t lock_counter = 0; +/* The spinlock our threads will use to manage access to the counter */ +static spinlock_t lock = SPINLOCK_INITIALIZER; + +/* + Calculates the Nth Fibonacci number. + Lets give the threads something to do while they wait! +*/ +static int fib(int n) { + if (n <= 1) + return n; + + return fib(n - 1) + fib(n - 2); +} + +/* + Main execution path for each thread, demonstrating the following + with a spinlock: + + 1) Doing something useful while waiting for the lock + 2) Simply locking normally and waiting for it +*/ +void *thd(void *v) { + unsigned tid = (unsigned)v; + unsigned fibres = 0, fibn = 0; + + /* Continue calling spinlock_trylock() until eventually + locking succeeds. */ + while(!spinlock_trylock(&lock)) { + print("Thread[%u] still trying the lock!\n", tid); + /* We can do something else while we wait! */ + fibres = fib(fibn++); + /* Let the other threads have some time too. */ + thd_pass(); + } + + print("Thread[%u] trylock succeeded!\n", tid); + print("Thread[%u] calculated the %uth fibonacci number " + "while waiting: %u\n", tid, fibn - 1, fibres); + + /* Increment our counter once now that we have the lock. */ + ++lock_counter; + sleep(1); + + print("Thread[%u] yielding the lock\n", tid); + + /* Release the lock so the other threads can have it. */ + spinlock_unlock(&lock); + + sleep(1); + + /* Attempt to gain the lock again, this time by + locking it. Program execution will not proceed + until the lock is in the thread's possession. */ + print("Thread[%u] locking the lock\n", tid); + spinlock_lock(&lock); + print("Thread[%u] locked the lock\n", tid); + + /* Increment out counter again to show we got the lock + a second time. */ + ++lock_counter; + sleep(1); + + print("Thread[%u] unlocking the lock\n", tid); + spinlock_unlock(&lock); + + /* Return how far we got into the Fibonacci sequence + while we waited for the lock. */ + return (void *)(fibn - 1); +} + +int main(int argc, char **argv) { + const int thread_count = 10; + kthread_t *threads[thread_count]; + int i, join_error = 0; + unsigned fibcount = 0; + + print("Starting Threads\n"); + + /* Kick off a number of threads to all compete for our spinlock. */ + for (i = 0; i < thread_count; i++) { + threads[i] = thd_create(0, thd, (void *)(i + 1)); + } + + /* Perform the same logic for the main thread. */ + thd((void*)0); + + /* Wait for each thread to return. */ + for(i = 0; i < thread_count; i++) { + void* result; + + if(thd_join(threads[i], &result) != 0) { + /* Mark the test as failed if the thread failed to join gracefully. */ + fprintf(stderr, "Thread[%i] failed to complete properly!\n", i + 1); + join_error = 1; + } else { + print("Thread[%d] returned.\n", i + 1); + /* Add the number of Fibonacci numbers it calculated to our total. */ + fibcount += (unsigned)result; + } + } + + print("Threads finished and calculated %u fibonacci numbers while they waited!\n", fibcount); + + /* Ensure there were no issues with threads exiting gracefully, + and that the lock_counter was incremented twice for every + thread, plus 2 more for the main thread. + */ + if(join_error || lock_counter != (thread_count + 1) * 2) { + fprintf(stderr, "\n\n***** SPINLOCK TEST FAILED! *****\n\n"); + return EXIT_FAILURE; + } + else { + print("\n\n***** SPINLOCK TEST SUCCESS! *****\n\n"); + return EXIT_SUCCESS; + } +} diff --git a/examples/dreamcast/dreameye/sd/dreameye-sd.c b/examples/dreamcast/dreameye/sd/dreameye-sd.c index 86344b2..423ebf5 100644 --- a/examples/dreamcast/dreameye/sd/dreameye-sd.c +++ b/examples/dreamcast/dreameye/sd/dreameye-sd.c @@ -23,7 +23,7 @@ int main(int argc, char *argv[]) { maple_device_t *dreameye; dreameye_state_t *state; - uint8 *buf; + uint8 *buf = NULL; int size, err; FILE *fp; int img_count, i; diff --git a/examples/dreamcast/keyboard/keytest/keytest.c b/examples/dreamcast/keyboard/keytest/keytest.c index 3a3d92a..9863c8e 100644 --- a/examples/dreamcast/keyboard/keytest/keytest.c +++ b/examples/dreamcast/keyboard/keytest/keytest.c @@ -2,10 +2,10 @@ keytest.c Copyright (C) 2018 Donald Haase - + The Purpose of this program is to provide some testing of the basic keyboard functionality. -Currently it merely takes in a preset number of printable test characters. This allows for the testing +Currently it merely takes in a preset number of printable test characters. This allows for the testing of basic US keyboard functionality, appropriate shift handling, and the newer key repeating feature. Room has been explicitly left open for further tests. It might be useful to include: @@ -28,7 +28,7 @@ Room has been explicitly left open for further tests. It might be useful to incl KOS_INIT_FLAGS(INIT_DEFAULT); extern uint16 *vram_s; -cont_state_t* first_kbd_state; +cont_state_t* first_kbd_state; maple_device_t* first_kbd_dev = NULL; /* Track how many times we try to find a keyboard before just quitting. */ @@ -37,7 +37,7 @@ uint8 no_kbd_loop = 0; uint8 test_phase = 0; -void basic_typing (void) +void basic_typing (void) { int charcount = 0; int rv; @@ -45,21 +45,21 @@ void basic_typing (void) uint32 offset = ((STARTLINE+(lines*BFONT_HEIGHT)) * WIDTH); bfont_draw_str(vram_s + offset, WIDTH, 1, "Test of basic typing. Enter 120 characters: "); offset = ((STARTLINE+((++lines)*BFONT_HEIGHT)) * WIDTH); - + while (charcount < CHARSPERTEST) { rv = kbd_queue_pop(first_kbd_dev, 1); if(rv<0) continue; - + bfont_draw(vram_s + offset, WIDTH, 1, (char)rv); offset += BFONT_THIN_WIDTH; charcount++; - if(!(charcount%CHARSPERLINE)) offset = ((STARTLINE+((++lines)*BFONT_HEIGHT)) * WIDTH); + if(!(charcount%CHARSPERLINE)) offset = ((STARTLINE+((++lines)*BFONT_HEIGHT)) * WIDTH); } return; } -int main(void) +int main(int argc, char **argv) { for(;;) { /* If the dev is null, refresh it. */ @@ -74,16 +74,16 @@ int main(void) } /* Reset the timeout counter */ no_kbd_loop = 0; - + first_kbd_state = (cont_state_t *) maple_dev_status(first_kbd_dev); if(first_kbd_state == NULL) assert_msg(0, "Invalid Keyboard state returned"); - + if(test_phase == 0) basic_typing(); else break; - - test_phase++; + + test_phase++; } return 0; } diff --git a/examples/dreamcast/png/example.c b/examples/dreamcast/png/example.c index ee48614..4c90994 100644 --- a/examples/dreamcast/png/example.c +++ b/examples/dreamcast/png/example.c @@ -211,7 +211,7 @@ void draw_frame(void) { extern uint8 romdisk[]; KOS_INIT_ROMDISK(romdisk); -int main(void) { +int main(int argc, char **argv) { int done = 0; /* init kos */ hooks/post-receive -- A pseudo Operating System for the Dreamcast. |