From 26d597c6439032318dc1f9e6310c51a70786f0c7 Mon Sep 17 00:00:00 2001 From: TaiJu Wu Date: Wed, 20 Sep 2023 09:41:55 +0000 Subject: [PATCH 1/2] feature: implement simple spinlock test Two threads use share variable and the variable should be same as excepted. Signed-off-by: TaiJu Wu --- testing/ostest/CMakeLists.txt | 4 ++ testing/ostest/Makefile | 4 ++ testing/ostest/ostest.h | 6 +++ testing/ostest/ostest_main.c | 6 +++ testing/ostest/spinlock.c | 92 +++++++++++++++++++++++++++++++++++ 5 files changed, 112 insertions(+) create mode 100644 testing/ostest/spinlock.c diff --git a/testing/ostest/CMakeLists.txt b/testing/ostest/CMakeLists.txt index 3aa8a67726..79eb225a7b 100644 --- a/testing/ostest/CMakeLists.txt +++ b/testing/ostest/CMakeLists.txt @@ -136,6 +136,10 @@ if(CONFIG_TESTING_OSTEST) list(APPEND SRCS smp_call.c) endif() + if(CONFIG_SPINLOCK) + list(APPEND SRCS spinlock.c) + endif() + target_sources(apps PRIVATE ${SRCS}) nuttx_add_application(NAME ostest SRCS ostest_main.c) diff --git a/testing/ostest/Makefile b/testing/ostest/Makefile index 88dffd9288..72cd0e2cf9 100644 --- a/testing/ostest/Makefile +++ b/testing/ostest/Makefile @@ -137,4 +137,8 @@ ifeq ($(CONFIG_SMP_CALL),y) CSRCS += smp_call.c endif +ifeq ($(CONFIG_SPINLOCK),y) +CSRCS += spinlock.c +endif + include $(APPDIR)/Application.mk diff --git a/testing/ostest/ostest.h b/testing/ostest/ostest.h index e169f4b710..16ecb060a2 100644 --- a/testing/ostest/ostest.h +++ b/testing/ostest/ostest.h @@ -256,6 +256,12 @@ void priority_inheritance(void); void sched_lock_test(void); +/* spinlock.c ***************************************************************/ + +#if defined(CONFIG_SPINLOCK) +void spinlock_test(void); +#endif + /* vfork.c ******************************************************************/ #if defined(CONFIG_ARCH_HAVE_FORK) && defined(CONFIG_SCHED_WAITPID) diff --git a/testing/ostest/ostest_main.c b/testing/ostest/ostest_main.c index c856aea402..3d94ad6cdf 100644 --- a/testing/ostest/ostest_main.c +++ b/testing/ostest/ostest_main.c @@ -602,6 +602,12 @@ static int user_main(int argc, char *argv[]) smp_call_test(); #endif +#if defined(CONFIG_SPINLOCK) + printf("\nuser_main: spinlock test\n"); + spinlock_test(); + check_test_memory_usage(); +#endif + /* Compare memory usage at time ostest_main started until * user_main exits. These should not be identical, but should * be similar enough that we can detect any serious OS memory diff --git a/testing/ostest/spinlock.c b/testing/ostest/spinlock.c new file mode 100644 index 0000000000..c9d808fe31 --- /dev/null +++ b/testing/ostest/spinlock.c @@ -0,0 +1,92 @@ +/**************************************************************************** + * apps/testing/ostest/spinlock.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include "ostest.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static spinlock_t lock = SP_UNLOCKED; + +static pthread_t g_thread1; +static pthread_t g_thread2; + +static int g_result = 0; + +static FAR void thread_spinlock(FAR void *parameter) +{ + int pid = *(int *)parameter; + + for (int i = 0; i < 10; i++) + { + printf("pid %d get lock g_result:%d\n", pid, g_result); + spin_lock(&lock); + g_result++; + spin_unlock(&lock); + printf("pid %d release lock g_result:%d\n", pid, g_result); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void spinlock_test(void) +{ + int status; + g_result = 0; + + status = pthread_create(&g_thread1, NULL, + (void *)thread_spinlock, &g_thread1); + if (status != 0) + { + printf("spinlock_test: ERROR pthread_create failed, status=%d\n", + status); + ASSERT(false); + } + + status = pthread_create(&g_thread2, NULL, + (void *)thread_spinlock, &g_thread2); + if (status != 0) + { + printf("spinlock_test: ERROR pthread_create failed, status=%d\n", + status); + ASSERT(false); + } + + pthread_join(g_thread1, NULL); + pthread_join(g_thread2, NULL); + + assert(g_result == 20); +} From 0dda3b224b76cbf1fa900bdecbc1f345001989d7 Mon Sep 17 00:00:00 2001 From: TaiJu Wu Date: Wed, 20 Sep 2023 13:15:45 +0000 Subject: [PATCH 2/2] feature: read-write spinlock test Signed-off-by: TaiJu Wu --- testing/ostest/spinlock.c | 121 ++++++++++++++++++++++++++++++++++---- 1 file changed, 111 insertions(+), 10 deletions(-) diff --git a/testing/ostest/spinlock.c b/testing/ostest/spinlock.c index c9d808fe31..6fa774ccdf 100644 --- a/testing/ostest/spinlock.c +++ b/testing/ostest/spinlock.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "ostest.h" @@ -42,33 +43,39 @@ static spinlock_t lock = SP_UNLOCKED; static pthread_t g_thread1; static pthread_t g_thread2; +#ifdef CONFIG_RW_SPINLOCK +static pthread_t g_thread3; +static rwlock_t rw_lock = RW_SP_UNLOCKED; +static atomic_int reader_counter = 0; +#endif + static int g_result = 0; -static FAR void thread_spinlock(FAR void *parameter) +static FAR void *thread_native_spinlock(FAR FAR void *parameter) { - int pid = *(int *)parameter; + int pid = *(FAR int *)parameter; for (int i = 0; i < 10; i++) { - printf("pid %d get lock g_result:%d\n", pid, g_result); + printf("pid %d try to get lock g_result:%d\n", pid, g_result); spin_lock(&lock); g_result++; spin_unlock(&lock); printf("pid %d release lock g_result:%d\n", pid, g_result); } -} -/**************************************************************************** - * Public Functions - ****************************************************************************/ + return NULL; +} -void spinlock_test(void) +static FAR void test_native_spinlock(void) { int status; g_result = 0; + lock = SP_UNLOCKED; + spin_initialize(&lock, SP_UNLOCKED); status = pthread_create(&g_thread1, NULL, - (void *)thread_spinlock, &g_thread1); + thread_native_spinlock, &g_thread1); if (status != 0) { printf("spinlock_test: ERROR pthread_create failed, status=%d\n", @@ -77,7 +84,7 @@ void spinlock_test(void) } status = pthread_create(&g_thread2, NULL, - (void *)thread_spinlock, &g_thread2); + thread_native_spinlock, &g_thread2); if (status != 0) { printf("spinlock_test: ERROR pthread_create failed, status=%d\n", @@ -90,3 +97,97 @@ void spinlock_test(void) assert(g_result == 20); } + +#if defined(CONFIG_RW_SPINLOCK) +static void FAR *thread_read_spinlock(FAR void *parameter) +{ + int pid = *(FAR int *)parameter; + int test; + + for (int i = 0; i < 10; ++i) + { + printf("pid %d try to get read lock g_result:%d\n", pid, g_result); + read_lock(&rw_lock); + atomic_fetch_add(&reader_counter, 1); + test = g_result + 1; + atomic_fetch_sub(&reader_counter, 1); + read_unlock(&rw_lock); + printf("pid %d release read lock g_result+1:%d\n", pid, test); + } + + return NULL; +} + +static void FAR *thread_wrt_spinlock(FAR void *parameter) +{ + static int writer_counter = 0; + int pid = *(FAR int *)parameter; + + for (int i = 0; i < 10; ++i) + { + printf("pid %d try to get write lock g_result:%d\n", pid, g_result); + write_lock(&rw_lock); + writer_counter += 1; + g_result++; + ASSERT(atomic_load(&reader_counter) == 0 && writer_counter == 1); + writer_counter -= 1; + write_unlock(&rw_lock); + printf("pid %d release write lock g_result:%d\n", pid, g_result); + } + + return NULL; +} + +static FAR void test_rw_spinlock(void) +{ + int status; + g_result = 0; + rwlock_init(&rw_lock); + + status = pthread_create(&g_thread1, NULL, + thread_read_spinlock, &g_thread1); + if (status != 0) + { + printf("spinlock_test: ERROR pthread_create failed, status=%d\n", + status); + ASSERT(false); + } + + status = pthread_create(&g_thread2, NULL, + thread_read_spinlock, &g_thread2); + if (status != 0) + { + printf("spinlock_test: ERROR pthread_create failed, status=%d\n", + status); + ASSERT(false); + } + + status = pthread_create(&g_thread3, NULL, + thread_wrt_spinlock, &g_thread3); + if (status != 0) + { + printf("spinlock_test: ERROR pthread_create failed, status=%d\n", + status); + ASSERT(false); + } + + pthread_join(g_thread1, NULL); + pthread_join(g_thread2, NULL); + pthread_join(g_thread3, NULL); + + assert(g_result == 10); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void spinlock_test(void) +{ + test_native_spinlock(); + +#if defined(CONFIG_RW_SPINLOCK) + test_rw_spinlock(); +#endif +}