diff --git a/benchmarks/tacle-bench/0001-tacle-bench-add-makefile-and-all-in-one-main-file.patch b/benchmarks/tacle-bench/0001-tacle-bench-add-makefile-and-all-in-one-main-file.patch index 4958ac5a8a5..fb1e2e400b9 100644 --- a/benchmarks/tacle-bench/0001-tacle-bench-add-makefile-and-all-in-one-main-file.patch +++ b/benchmarks/tacle-bench/0001-tacle-bench-add-makefile-and-all-in-one-main-file.patch @@ -1,10 +1,11 @@ -From 71f51cd5ca4f492a464fb12d5bce91e5fbba300a Mon Sep 17 00:00:00 2001 +From 6d0be04a4b4208447e75c369e9811d089f466739 Mon Sep 17 00:00:00 2001 From: ouyangxiangzhen -Date: Tue, 11 Jun 2024 16:01:23 +0800 +Date: Thu, 3 Apr 2025 11:59:02 +0800 Subject: [PATCH] tacle-bench: add makefile and all-in-one main file The original taclebench is used for WCET analysis. This commit allows most taclebench test cases (except parallel test cases) to be compiled and executed. +Change-Id: I707b8ac58d3ddc4b7974c5bedecac1a7b5c887f9 Signed-off-by: ouyangxiangzhen --- Makefile | 12 + @@ -65,14 +66,14 @@ Signed-off-by: ouyangxiangzhen bench/test/cover/cover.c | 3 + bench/test/duff/duff.c | 3 + bench/test/test3/test3.c | 3 + - taclebench.c | 349 ++++++++++++++++++ - 59 files changed, 532 insertions(+) + taclebench.c | 366 ++++++++++++++++++ + 59 files changed, 549 insertions(+) create mode 100644 Makefile create mode 100644 taclebench.c diff --git a/Makefile b/Makefile new file mode 100644 -index 0000000..2385c61 +index 0000000..75ca0a1 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ @@ -83,7 +84,7 @@ index 0000000..2385c61 +TEST_SRCS := $(shell find bench/test -name "*.c") + +all: -+ cc -DALL_IN_ONE ${APP_SRCS} ${KERNEL_SRCS} ${SEQUENTIAL_SRCS} ${TEST_SRCS} bench/kernel/cosf/wcclibm.c taclebench.c -static -o taclebench ++ cc -DALL_IN_ONE ${APP_SRCS} ${KERNEL_SRCS} ${SEQUENTIAL_SRCS} ${TEST_SRCS} bench/kernel/cosf/wcclibm.c taclebench.c -static -o taclebench -O3 + +clean: + rm -f taclebench @@ -888,11 +889,12 @@ index 0235738..6eaf8c2 100755 diff --git a/taclebench.c b/taclebench.c new file mode 100644 -index 0000000..1231b87 +index 0000000..aaff1bb --- /dev/null +++ b/taclebench.c -@@ -0,0 +1,349 @@ +@@ -0,0 +1,366 @@ +#include ++#include + +int main_epic(void); +int main_mpeg2(void); @@ -954,6 +956,10 @@ index 0000000..1231b87 + +int main(void) +{ ++ struct timespec start_ts; ++ struct timespec end_ts; ++ clock_gettime(CLOCK_MONOTONIC, &start_ts); ++ + if (main_epic() != 0) + { + printf("main_epic error\n"); @@ -1239,6 +1245,18 @@ index 0000000..1231b87 + printf("main_bitonic error\n"); + } + ++ clock_gettime(CLOCK_MONOTONIC, &end_ts); ++ long sec_diff = end_ts.tv_sec - start_ts.tv_sec; ++ long nsec_diff = end_ts.tv_nsec - start_ts.tv_nsec; ++ ++ if (nsec_diff < 0) ++ { ++ sec_diff -= 1; ++ nsec_diff += 1000000000; ++ } ++ ++ printf("%ld.%09ld seconds\n", sec_diff, nsec_diff); ++ + return 0; +} -- diff --git a/testing/drivers/drivertest/drivertest_posix_timer.c b/testing/drivers/drivertest/drivertest_posix_timer.c index 00b7fb20317..65b95ee24c5 100644 --- a/testing/drivers/drivertest/drivertest_posix_timer.c +++ b/testing/drivers/drivertest/drivertest_posix_timer.c @@ -41,7 +41,7 @@ * Pre-processor Definitions ****************************************************************************/ -#define RTC_DEFAULT_DEVIATION 10 +#define RTC_DEFAULT_DEVIATION 100 #define DEFAULT_TIME_OUT 2 #define SLEEPSECONDS 10 @@ -64,7 +64,8 @@ struct posix_timer_state_s { struct itimerspec it; - uint32_t tim; + uint64_t tim; + uint32_t trigger_count; uint32_t deviation; }; @@ -140,12 +141,12 @@ static void parse_commandline( * Name: get_timestamp ****************************************************************************/ -static uint32_t get_timestamp(void) +static uint64_t get_timestamp(void) { struct timespec ts; - uint32_t ms; + uint64_t ms; clock_gettime(CLOCK_MONOTONIC, &ts); - ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; + ms = (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000; return ms; } @@ -157,14 +158,17 @@ static void posix_timer_callback(union sigval arg) { FAR struct posix_timer_state_s *sigev_para = (FAR struct posix_timer_state_s *)arg.sival_ptr; - int range = get_timestamp() - (*sigev_para).tim; + uint64_t expected = (*sigev_para).tim + + DEFAULT_TIME_OUT * (*sigev_para).trigger_count; + int range = get_timestamp() - expected; - assert_in_range(range, - sigev_para->it.it_interval.tv_sec * 1000 - sigev_para->deviation, - sigev_para->it.it_interval.tv_sec * 1000 + sigev_para->deviation); + syslog(0, "range: %d ms\n", range); + + assert(range >= sigev_para->it.it_interval.tv_sec * 1000 - + sigev_para->deviation); syslog(LOG_DEBUG, "callback trigger!!!\n"); - (*sigev_para).tim = get_timestamp(); + (*sigev_para).trigger_count++; } /**************************************************************************** @@ -195,11 +199,11 @@ static void drivertest_posix_timer(FAR void **state) /* Start the timer */ + posix_timer_state->tim = get_timestamp(); + ret = timer_settime(timerid, 0, &(posix_timer_state->it), NULL); assert_return_code(ret, OK); - posix_timer_state->tim = get_timestamp(); - /* Get the timer status */ ret = timer_gettime(timerid, &it); @@ -225,6 +229,7 @@ int main(int argc, FAR char *argv[]) .it.it_value.tv_nsec = 0, .it.it_interval.tv_sec = DEFAULT_TIME_OUT, .it.it_interval.tv_nsec = 0, + .trigger_count = 0, .deviation = RTC_DEFAULT_DEVIATION }; diff --git a/testing/ostest/CMakeLists.txt b/testing/ostest/CMakeLists.txt index 777c68744c1..a8a2ca9211e 100644 --- a/testing/ostest/CMakeLists.txt +++ b/testing/ostest/CMakeLists.txt @@ -162,7 +162,7 @@ if(CONFIG_TESTING_OSTEST) endif() if(CONFIG_BUILD_FLAT) - list(APPEND SRCS wdog.c) + list(APPEND SRCS wdog.c spinlock.c) endif() set(OSTEST_SRCS ostest_main.c ${SRCS}) diff --git a/testing/ostest/Kconfig b/testing/ostest/Kconfig index 83054fa688a..100afb73e95 100644 --- a/testing/ostest/Kconfig +++ b/testing/ostest/Kconfig @@ -115,4 +115,13 @@ config TESTING_OSTEST_POWEROFF default n depends on BOARDCTL_POWEROFF && TESTING_OSTEST_WAITRESULT +config TESTING_OSTEST_SPINLOCK_THREADS + int "Number of spinlock test threads" + default 2 + range 1 32 + +config TEST_LOOP_SCALE + int "Loop scale of spinlock test (N x 10,000)" + default 100 + endif # TESTING_OSTEST diff --git a/testing/ostest/Makefile b/testing/ostest/Makefile index 1fedfcf54ee..817fcdb51d4 100644 --- a/testing/ostest/Makefile +++ b/testing/ostest/Makefile @@ -31,7 +31,7 @@ MODULE = $(CONFIG_TESTING_OSTEST) # NuttX OS Test -CSRCS = getopt.c libc_memmem.c restart.c sighelper.c +CSRCS = getopt.c libc_memmem.c restart.c sighelper.c ifeq ($(CONFIG_ENABLE_ALL_SIGNALS),y) CSRCS += sighand.c signest.c @@ -167,7 +167,7 @@ endif endif ifeq ($(CONFIG_BUILD_FLAT),y) -CSRCS += wdog.c +CSRCS += wdog.c spinlock.c endif include $(APPDIR)/Application.mk diff --git a/testing/ostest/ostest.h b/testing/ostest/ostest.h index 321ecd2d330..1a396ba285c 100644 --- a/testing/ostest/ostest.h +++ b/testing/ostest/ostest.h @@ -286,6 +286,10 @@ void setjmp_test(void); void smp_call_test(void); #endif +/* spinlock.c ***************************************************************/ + +void spinlock_test(void); + /* APIs exported (conditionally) by the OS specifically for testing of * priority inheritance */ diff --git a/testing/ostest/ostest_main.c b/testing/ostest/ostest_main.c index 6bf75d86fed..8247b47883b 100644 --- a/testing/ostest/ostest_main.c +++ b/testing/ostest/ostest_main.c @@ -381,7 +381,7 @@ static int user_main(int argc, char *argv[]) check_test_memory_usage(); #endif -#if !defined(CONFIG_DISABLE_PTHREAD) && defined(__KERNEL__) && \ +#if !defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_BUILD_FLAT) && \ defined(CONFIG_SCHED_WORKQUEUE) /* Check work queues */ @@ -548,6 +548,10 @@ static int user_main(int argc, char *argv[]) #endif #ifdef CONFIG_BUILD_FLAT + printf("\nuser_main: spinlock test\n"); + spinlock_test(); + check_test_memory_usage(); + printf("\nuser_main: wdog test\n"); wdog_test(); check_test_memory_usage(); diff --git a/testing/ostest/spinlock.c b/testing/ostest/spinlock.c new file mode 100644 index 00000000000..1ebe290f1d9 --- /dev/null +++ b/testing/ostest/spinlock.c @@ -0,0 +1,272 @@ +/**************************************************************************** + * 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 +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ + +#define MAX_THREAD_NUM (CONFIG_SMP_NCPUS) +#define LOOP_TIMES (CONFIG_TEST_LOOP_SCALE * 100000) + +aligned_data(64) struct spinlock_pub_args_s +{ + FAR void *lock; + volatile uint32_t counter; + atomic_t barrier; + uint32_t thread_num; +}; + +struct spinlock_thread_args_s +{ + uint64_t delta; + FAR struct spinlock_pub_args_s *pub; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Helper functions for timespec calculating */ + +static inline uint64_t calc_diff(FAR struct timespec *start, + FAR struct timespec *end) +{ + uint64_t diff_sec = end->tv_sec - start->tv_sec; + long diff_nsec = end->tv_nsec - start->tv_nsec; + if (diff_nsec < 0) + { + diff_sec -= 1; + diff_nsec += 1000000000L; + } + + return diff_sec * 1000000000ULL + diff_nsec; +} + +#define LOCK_TEST_FUNC(lock_type, lock_func, unlock_func) \ +FAR static void * lock_type##_test_thread(FAR void *arg) \ +{ \ + struct spinlock_thread_args_s *param = \ + (struct spinlock_thread_args_s *)arg; \ + irqstate_t flags; \ + struct timespec start; \ + struct timespec end; \ + uint32_t i; \ + FAR struct spinlock_pub_args_s *pub = param->pub; \ + FAR lock_type *l = (FAR lock_type *)pub->lock; \ + atomic_fetch_add(&pub->barrier, 1); \ + while (atomic_read(&pub->barrier) != pub->thread_num) \ + { \ + sched_yield(); \ + } \ + clock_gettime(CLOCK_REALTIME, &start); \ + for (i = 0; i < LOOP_TIMES; i++) \ + { \ + flags = lock_func(l); \ + pub->counter++; \ + unlock_func(l, flags); \ + } \ + clock_gettime(CLOCK_REALTIME, &end); \ + param->delta = calc_diff(&start, &end); \ + return NULL; \ +} + +LOCK_TEST_FUNC(spinlock_t, spin_lock_irqsave, spin_unlock_irqrestore) +LOCK_TEST_FUNC(rspinlock_t, rspin_lock_irqsave, rspin_unlock_irqrestore) +LOCK_TEST_FUNC(seqcount_t, write_seqlock_irqsave, write_sequnlock_irqrestore) + +static inline +void run_test_thread(void *lock, FAR void *(*thread_func)(FAR void *arg), + uint32_t thread_num, const char *lock_type) +{ + pthread_t tid[MAX_THREAD_NUM]; + struct spinlock_pub_args_s pub; + pthread_attr_t attr; + struct sched_param sparam; + struct spinlock_thread_args_s param[MAX_THREAD_NUM]; + struct timespec stime; + struct timespec etime; + cpu_set_t cpu_set = 1u; + uint64_t total_ns = 0u; + int status; + int i; + + /* Initialize the public parameters. */ + + printf("Test type: %s\n", lock_type); + + pub.lock = lock; + pub.counter = 0u; + pub.thread_num = thread_num; + atomic_set_release(&pub.barrier, 0u); + + /* Set affinity to CPU0 */ + +#ifdef CONFIG_SMP + if (OK != sched_setaffinity(getpid(), sizeof(cpu_set_t), &cpu_set)) + { + printf("spinlock_test: ERROR: nxsched_set_affinity failed"); + ASSERT(false); + } +#else + UNUSED(cpu_set); +#endif + + /* Boost to maximum priority for test threads. */ + + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("spinlock_test: ERROR: " + "pthread_attr_init failed, status=%d\n", status); + ASSERT(false); + } + + sparam.sched_priority = SCHED_PRIORITY_MAX; + status = pthread_attr_setschedparam(&attr, &sparam); + if (status != OK) + { + printf("spinlock_test: ERROR: " + "pthread_attr_setschedparam failed, status=%d\n", status); + ASSERT(false); + } + + clock_gettime(CLOCK_REALTIME, &stime); + + /* Create new test threads. */ + + for (i = 0; i < thread_num; i++) + { + param[i].pub = &pub; + param[i].delta = 0; + + /* Set affinity */ + +#ifdef CONFIG_SMP + cpu_set = 1u << ((i + 1) % CONFIG_SMP_NCPUS); + + status = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), + &cpu_set); + if (status != OK) + { + printf("spinlock_test: ERROR: " + "pthread_attr_setaffinity_np failed, status=%d\n", status); + ASSERT(false); + } +#endif + + status = pthread_create(&tid[i], &attr, thread_func, ¶m[i]); + if (status != 0) + { + printf("spinlock_test: ERROR: " + "pthread_create failed, status=%d\n", status); + ASSERT(false); + } + } + + for (i = 0; i < thread_num; i++) + { + status = pthread_join(tid[i], NULL); + if (status != 0) + { + printf("spinlock_test: ERROR: " + "pthread_join failed, status=%d\n", status); + ASSERT(false); + } + } + + /* Calculate the average throughput. */ + + clock_gettime(CLOCK_REALTIME, &etime); + for (i = 0; i < thread_num; i++) + { + total_ns += param[i].delta; + } + + if (total_ns != 0) + { + printf("%s: Test Results:\n", lock_type); + printf("%s: Final counter: %" PRIu32 "\n", lock_type, pub.counter); + assert(pub.counter == thread_num * LOOP_TIMES); + printf("%s: Average throughput : %" PRIu64 " op/s\n", lock_type, + (uint64_t)NSEC_PER_SEC * LOOP_TIMES * thread_num / total_ns); + printf("%s: Total execution time: %" PRIu64 " ns\n \n", + lock_type, calc_diff(&stime, &etime)); + } + else + { + printf("spinlock_test: ERROR: total_ns is 0\n"); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: spinlock_test + ****************************************************************************/ + +static void spinlock_test_thread_num(unsigned thread_num) +{ + aligned_data(64) union + { + spinlock_t spinlock; + rspinlock_t rspinlock; + seqcount_t seqcount; + } lock; + + printf("Start Lock test:\n"); + printf("Thread num: %u, Loop times: %d\n\n", thread_num, LOOP_TIMES); + + spin_lock_init(&lock.spinlock); + run_test_thread(&lock, spinlock_t_test_thread, thread_num, "spinlock"); + + rspin_lock_init(&lock.rspinlock); + run_test_thread(&lock, rspinlock_t_test_thread, thread_num, "rspinlock"); + + seqlock_init(&lock.seqcount); + run_test_thread(&lock, seqcount_t_test_thread, thread_num, "seqcount"); +} + +void spinlock_test(void) +{ + unsigned tnr; + + for (tnr = 1; tnr <= MAX_THREAD_NUM; tnr++) + { + spinlock_test_thread_num(tnr); + } +} diff --git a/testing/ostest/wdog.c b/testing/ostest/wdog.c index 273a680e916..e64f1246fbb 100644 --- a/testing/ostest/wdog.c +++ b/testing/ostest/wdog.c @@ -70,13 +70,13 @@ static void wdtest_callback(wdparm_t param) { FAR wdtest_param_t *wdtest_param = (FAR wdtest_param_t *)param; - /* Increment the callback count */ - - wdtest_param->callback_cnt += 1; - /* Record the system tick at which the callback was triggered */ wdtest_param->triggered_tick = clock_systime_ticks(); + + /* Increment the callback count */ + + wdtest_param->callback_cnt += 1; } static void wdtest_checkdelay(sclock_t diff, sclock_t delay_tick) diff --git a/testing/sched/timerjitter/timerjitter.c b/testing/sched/timerjitter/timerjitter.c index 214bbf7356a..01eed10d5b7 100644 --- a/testing/sched/timerjitter/timerjitter.c +++ b/testing/sched/timerjitter/timerjitter.c @@ -35,8 +35,8 @@ ****************************************************************************/ #define DEFAULT_CLOCKID CLOCK_REALTIME -#define DEFAULT_INTERVAL 1000 -#define DEFAULT_ITERATION 1000 +#define DEFAULT_INTERVAL (1000 * USEC_PER_TICK) +#define DEFAULT_ITERATION (USEC_PER_SEC / DEFAULT_INTERVAL) /* Fix compilation error for Non-NuttX OS */ #ifndef FAR @@ -137,12 +137,15 @@ static FAR void *timerjitter(FAR void *arg) struct timespec next; struct timespec intv; struct itimerspec tspec; - struct sigevent sigev; sigset_t sigset; timer_t timer; int64_t diff; int sigs; int ret; + struct sigevent sigev = + { + 0 + }; sigemptyset(&sigset); sigaddset(&sigset, SIGALRM); @@ -154,8 +157,20 @@ static FAR void *timerjitter(FAR void *arg) sigev.sigev_notify = SIGEV_SIGNAL; sigev.sigev_signo = SIGALRM; - timer_create(param->clockid, &sigev, &timer); - clock_gettime(param->clockid, &now); + ret = timer_create(param->clockid, &sigev, &timer); + + if (ret != 0) + { + printf("timer_create failed %d\n", ret); + return NULL; + } + + ret = clock_gettime(param->clockid, &now); + + if (ret) + { + printf("clock_gettime failed %d\n", ret); + } next = now; calc_next(&next, &intv); @@ -167,7 +182,13 @@ static FAR void *timerjitter(FAR void *arg) /* Using TIMER_ABSTIME */ tspec.it_value = next; - timer_settime(timer, TIMER_ABSTIME, &tspec, NULL); + ret = timer_settime(timer, TIMER_ABSTIME, &tspec, NULL); + + if (ret) + { + printf("timer_settime failed %d\n", ret); + return NULL; + } param->avg = 0; param->max = 0; diff --git a/testing/testsuites/kernel/time/cases/clock_test_timer03.c b/testing/testsuites/kernel/time/cases/clock_test_timer03.c index 7539f4479f6..76a42c76032 100644 --- a/testing/testsuites/kernel/time/cases/clock_test_timer03.c +++ b/testing/testsuites/kernel/time/cases/clock_test_timer03.c @@ -123,7 +123,7 @@ void test_nuttx_clock_test_timer03(FAR void **state) start.tv_sec * (int64_t)(1e9) - start.tv_nsec; failed += (escaped < expected || - (escaped - expected) >= 20000000); /* 20000000, 2 ticks. */ + (escaped - expected) > 100000000ul); /* 100 ms */ syslog(LOG_INFO, "expected = %" PRId64 " escaped = %" PRId64 "failed = %d", expected, escaped, failed); }