diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 963e40a9..9c94b1c8 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,6 +8,7 @@ add_subdirectory(allocator) add_subdirectory(arc4) add_subdirectory(array) add_subdirectory(ascii85) +add_subdirectory(atomic) add_subdirectory(base32) add_subdirectory(base64) add_subdirectory(bfdev) diff --git a/examples/atomic/.gitignore b/examples/atomic/.gitignore new file mode 100644 index 00000000..bcba1f6d --- /dev/null +++ b/examples/atomic/.gitignore @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +/atomic-spinlock diff --git a/examples/atomic/CMakeLists.txt b/examples/atomic/CMakeLists.txt new file mode 100644 index 00000000..e9d79989 --- /dev/null +++ b/examples/atomic/CMakeLists.txt @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright(c) 2023 John Sanpe +# + +add_executable(atomic-spinlock spinlock.c) +target_link_libraries(atomic-spinlock bfdev) +add_test(atomic-spinlock atomic-spinlock) + +if(${CMAKE_PROJECT_NAME} STREQUAL "bfdev") + install(FILES + spinlock.c + DESTINATION + ${CMAKE_INSTALL_DOCDIR}/examples/atomic + ) + + install(TARGETS + atomic-spinlock + DESTINATION + ${CMAKE_INSTALL_DOCDIR}/bin + ) +endif() diff --git a/examples/atomic/spinlock.c b/examples/atomic/spinlock.c new file mode 100644 index 00000000..469e7c09 --- /dev/null +++ b/examples/atomic/spinlock.c @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright(c) 2025 John Sanpe + */ + +#define MODULE_NAME "atomic-spinlock" +#define bfdev_log_fmt(fmt) MODULE_NAME ": " fmt + +#include +#include +#include +#include +#include + +static +bfdev_atomic_t lock; + +static volatile +long counter; + +static void +spin_lock(bfdev_atomic_t *lock) +{ + while (bfdev_cmpxchg(lock, 1, 0) != 1) + sched_yield(); +} + +static void +spin_unlock(bfdev_atomic_t *lock) +{ + if (bfdev_cmpxchg(lock, 0, 1) == 0) + sched_yield(); +} + +static void * +thread1_task(void *unused) +{ + unsigned int time; + + for (time = 0; time < 1000000; ++time) { + spin_lock(&lock); + counter++; + spin_unlock(&lock); + } + + return NULL; +} + +static void * +thread2_task(void *unused) +{ + unsigned int time; + + for (time = 0; time < 1000000; ++time) { + spin_lock(&lock); + counter--; + spin_unlock(&lock); + } + + return NULL; +} + +int +main(int argc, const char *argv[]) +{ + pthread_t thread1, thread2; + + bfdev_atomic_write(&lock, 1); + pthread_create(&thread1, NULL, thread1_task, NULL); + pthread_create(&thread2, NULL, thread2_task, NULL); + + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + + bfdev_log_info("counter: %ld\n", counter); + if (counter) + return 1; + + return 0; +}