From 3289d8cd39b0491a72603704b203621fd4edaf51 Mon Sep 17 00:00:00 2001 From: wangzhi16 Date: Thu, 18 Sep 2025 16:21:20 +0800 Subject: [PATCH 1/3] test/mutex: fix mutex testcases. Multiple threads should use the same lock for resource protection. Signed-off-by: wangzhi16 --- .../kernel/sched/cases/api_pthread_test_007.c | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/testing/testsuites/kernel/sched/cases/api_pthread_test_007.c b/testing/testsuites/kernel/sched/cases/api_pthread_test_007.c index 3a50a5f94db..46fac1a00d7 100644 --- a/testing/testsuites/kernel/sched/cases/api_pthread_test_007.c +++ b/testing/testsuites/kernel/sched/cases/api_pthread_test_007.c @@ -40,6 +40,16 @@ #include #include "SchedTest.h" +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +struct resource_s +{ + pthread_mutex_t mutex; + int run_flag; +}; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -50,13 +60,14 @@ static void *schedpthread07threadroutine(void *arg) { + struct resource_s *resource = (struct resource_s *)arg; int i; - pthread_mutex_t schedpthreadtest07_mutex = PTHREAD_MUTEX_INITIALIZER; + for (i = 0; i < 100; i++) { - pthread_mutex_lock(&schedpthreadtest07_mutex); - (*((int *)arg))++; - pthread_mutex_unlock(&schedpthreadtest07_mutex); + pthread_mutex_lock(&resource->mutex); + resource->run_flag++; + pthread_mutex_unlock(&resource->mutex); } return NULL; @@ -74,16 +85,20 @@ void test_nuttx_sched_pthread07(FAR void **state) { int res; pthread_t pt_1, pt_2, pt_3; - int run_flag = 0; + struct resource_s resource = + { + .mutex = PTHREAD_MUTEX_INITIALIZER, + .run_flag = 0 + }; res = pthread_create(&pt_1, NULL, (void *)schedpthread07threadroutine, - &run_flag); + &resource); assert_int_equal(res, OK); res = pthread_create(&pt_2, NULL, (void *)schedpthread07threadroutine, - &run_flag); + &resource); assert_int_equal(res, OK); res = pthread_create(&pt_3, NULL, (void *)schedpthread07threadroutine, - &run_flag); + &resource); assert_int_equal(res, OK); pthread_join(pt_1, NULL); @@ -91,5 +106,5 @@ void test_nuttx_sched_pthread07(FAR void **state) pthread_join(pt_3, NULL); sleep(5); - assert_int_equal(run_flag, 300); + assert_int_equal(resource.run_flag, 300); } From 3f9eb5f704646e172a1addfa31b51e5f8beb60f2 Mon Sep 17 00:00:00 2001 From: wangzhi16 Date: Wed, 7 May 2025 21:03:08 +0800 Subject: [PATCH 2/3] testing/fs: add testcase to test the stability of memfd. Supplement ostest test cases. Signed-off-by: wangzhi16 --- testing/fs/memfd/CMakeLists.txt | 23 +++++++++ testing/fs/memfd/Kconfig | 11 +++++ testing/fs/memfd/Make.defs | 23 +++++++++ testing/fs/memfd/Makefile | 29 +++++++++++ testing/fs/memfd/memfd_test.c | 87 +++++++++++++++++++++++++++++++++ 5 files changed, 173 insertions(+) create mode 100644 testing/fs/memfd/CMakeLists.txt create mode 100644 testing/fs/memfd/Kconfig create mode 100644 testing/fs/memfd/Make.defs create mode 100644 testing/fs/memfd/Makefile create mode 100644 testing/fs/memfd/memfd_test.c diff --git a/testing/fs/memfd/CMakeLists.txt b/testing/fs/memfd/CMakeLists.txt new file mode 100644 index 00000000000..bde18312998 --- /dev/null +++ b/testing/fs/memfd/CMakeLists.txt @@ -0,0 +1,23 @@ +# ############################################################################## +# apps/testing/fs/memfd/CMakeLists.txt +# +# 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. +# +# ############################################################################## + +if(CONFIG_TESTING_MEMFD) + nuttx_add_application(NAME memfd SRCS memfd_test.c) +endif() diff --git a/testing/fs/memfd/Kconfig b/testing/fs/memfd/Kconfig new file mode 100644 index 00000000000..464537bbf9d --- /dev/null +++ b/testing/fs/memfd/Kconfig @@ -0,0 +1,11 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config TESTING_MEMFD + bool "Testing the stability of memfd" + depends on !LIBC_MEMFD_ERROR && MM_KASAN + default n + ---help--- + Enable to test the stability of memfd diff --git a/testing/fs/memfd/Make.defs b/testing/fs/memfd/Make.defs new file mode 100644 index 00000000000..286699d9e9e --- /dev/null +++ b/testing/fs/memfd/Make.defs @@ -0,0 +1,23 @@ +############################################################################ +# apps/testing/fs/memfd/Make.defs +# +# 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. +# +############################################################################ + +ifneq ($(CONFIG_TESTING_MEMFD),) +CONFIGURED_APPS += $(APPDIR)/testing/fs/memfd +endif diff --git a/testing/fs/memfd/Makefile b/testing/fs/memfd/Makefile new file mode 100644 index 00000000000..0080d0f48b8 --- /dev/null +++ b/testing/fs/memfd/Makefile @@ -0,0 +1,29 @@ +############################################################################ +# apps/testing/fs/memfd/Makefile +# +# 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. +# +############################################################################ + +include $(APPDIR)/Make.defs + +PROGNAME = memfd_test +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE) + +MAINSRC = memfd_test.c + +include $(APPDIR)/Application.mk diff --git a/testing/fs/memfd/memfd_test.c b/testing/fs/memfd/memfd_test.c new file mode 100644 index 00000000000..1e72915bf50 --- /dev/null +++ b/testing/fs/memfd/memfd_test.c @@ -0,0 +1,87 @@ +/**************************************************************************** + * apps/testing/fs/memfd/memfd_test.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 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + + #define BUFFER_SIZE 8 + #define THREAD_NUM 50 + #define LOOP_NUM 1000 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void *func(FAR void *arg) +{ + void *buf; + int size = BUFFER_SIZE; + int i; + int memfd; + + for (i = 0; i < LOOP_NUM; i++) + { + memfd = memfd_create("optee", O_CREAT | O_CLOEXEC); + ftruncate(memfd, size); + buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, 0); + close(memfd); + + *((int *)buf) = 0xdeadbeef; + usleep(10); + *((int *)buf) = 0xdeadbeef; + + munmap(buf, size); + } + + printf("thread %d test pass!\n", pthread_self()); + return NULL; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, FAR char *argv[]) +{ + pid_t pid[THREAD_NUM]; + int i; + + for (i = 0; i < THREAD_NUM; i++) + { + pthread_create(&pid[i], NULL, func, NULL); + } + + for (i = 0; i < THREAD_NUM; i++) + { + pthread_join(pid[i], NULL); + } + + return 0; +} From 99f92c21bd4c9a7e9898bc6a2f1b1b7f8ca96c1a Mon Sep 17 00:00:00 2001 From: wangzhi16 Date: Wed, 28 May 2025 22:34:35 +0800 Subject: [PATCH 3/3] examples/pipe: bugfix testcase of fifo There are three bug in fifo testcase. 1. line 211 and line 295 should be nbytes not ret. 2. coverity report error: CID 1667262: (#4 of 11): Double close (USE_AFTER_FREE) 11. double_close: Calling close(int) will close the handle fd that has already been closed. [Note: The source code implementation of this function has been overwritten by the built-in model.] Double close will ocurr when line 234 is true and goto line 341, close again! Now, Using the previous code logic, Use a tid and an errout_with_null_thread to avoid uninitialized problems. 3. since line 295 is used ret not nbytes, error not expose before. When the end of read and write are opened, end of write will write successfully even if end of read not read. Signed-off-by: wangzhi16 --- examples/pipe/interlock_test.c | 55 ++++++++++++++++------------------ 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/examples/pipe/interlock_test.c b/examples/pipe/interlock_test.c index 6be9b6ec405..cb298580070 100644 --- a/examples/pipe/interlock_test.c +++ b/examples/pipe/interlock_test.c @@ -150,8 +150,7 @@ static void *null_writer(pthread_addr_t pvarg) int interlock_test(void) { - pthread_t readerid; - pthread_t writerid; + pthread_t tid; void *value; char data[16]; ssize_t nbytes; @@ -171,7 +170,7 @@ int interlock_test(void) /* Start the null_writer thread */ printf("interlock_test: Starting null_writer thread\n"); - ret = pthread_create(&writerid, NULL, null_writer, NULL); + ret = pthread_create(&tid, NULL, null_writer, NULL); if (ret != 0) { fprintf(stderr, \ @@ -194,7 +193,7 @@ int interlock_test(void) "errno=%d\n", FIFO_PATH2, errno); ret = 3; - goto errout_with_null_writer_thread; + goto errout_with_null_thread; } /* Attempt to read one byte from the FIFO. This should return end-of-file @@ -208,15 +207,15 @@ int interlock_test(void) fprintf(stderr, \ "interlock_test: read failed, errno=%d\n", errno); ret = 4; - goto errout_with_null_writer_thread; + goto errout_with_file; } - else if (ret != 0) + else if (nbytes != 0) { fprintf(stderr, \ "interlock_test: Read %ld bytes of data -- aborting: %d\n", (long)nbytes, errno); ret = 5; - goto errout_with_null_writer_thread; + goto errout_with_file; } printf("interlock_test: read returned\n"); @@ -234,7 +233,7 @@ int interlock_test(void) /* Wait for null_writer thread to complete */ printf("interlock_test: Waiting for null_writer thread\n"); - ret = pthread_join(writerid, &value); + ret = pthread_join(tid, &value); if (ret != 0) { fprintf(stderr, \ @@ -255,7 +254,7 @@ int interlock_test(void) /* Start the null_reader thread */ printf("interlock_test: Starting null_reader thread\n"); - ret = pthread_create(&readerid, NULL, null_reader, NULL); + ret = pthread_create(&tid, NULL, null_reader, NULL); if (ret != 0) { fprintf(stderr, \ @@ -278,29 +277,26 @@ int interlock_test(void) "errno=%d\n", FIFO_PATH2, errno); ret = 9; - goto errout_with_null_reader_thread; + goto errout_with_null_thread; } - /* Attempt to write one byte from the FIFO. This should return 0 bytes - * written because the null_reader closes the FIFO. + /* Attempt to write one byte from the FIFO. This should return n bytes + * written since the null_reader has opened the FIFO. */ printf("interlock_test: Writing to %s\n", FIFO_PATH2); nbytes = write(fd, data, 16); - if (nbytes < 0) + if (nbytes <= 0) { fprintf(stderr, \ "interlock_test: write failed, errno=%d\n", errno); ret = 10; - goto errout_with_null_reader_thread; + goto errout_with_file; } - else if (ret != 0) + else { fprintf(stderr, \ - "interlock_test: Wrote %ld bytes of data -- aborting: %d\n", - (long)nbytes, errno); - ret = 11; - goto errout_with_null_reader_thread; + "interlock_test: Wrote %ld bytes of data\n", (long)nbytes); } printf("interlock_test: write returned\n"); @@ -318,7 +314,7 @@ int interlock_test(void) /* Wait for null_reader thread to complete */ printf("interlock_test: Waiting for null_reader thread\n"); - ret = pthread_join(readerid, &value); + ret = pthread_join(tid, &value); if (ret != 0) { fprintf(stderr, \ @@ -339,20 +335,19 @@ int interlock_test(void) ret = 0; goto errout_with_fifo; -errout_with_null_reader_thread: - pthread_detach(readerid); - pthread_cancel(readerid); +errout_with_file: + if (close(fd) != 0) + { + fprintf(stderr, "interlock_test: close failed: %d\n", errno); + } -errout_with_null_writer_thread: - pthread_detach(writerid); - pthread_cancel(writerid); +errout_with_null_thread: + pthread_detach(tid); + pthread_cancel(tid); errout_with_fifo: - if (fd != -1 && close(fd) != 0) - { - fprintf(stderr, "interlock_test: close failed: %d\n", errno); - } + /* Close the file */ ret = remove(FIFO_PATH2); if (ret != 0)