nuttx-apps/testing/ostest/semtimed.c
Xiang Xiao f9f59bd0f8 !apps: drop redundant casts on tv_sec/tv_nsec and fix printf formats
Now that time_t is unconditionally 64-bit (signed int64_t) and the
struct timespec fields tv_sec / tv_nsec are wide enough on their own,
the explicit (uint64_t)/(int64_t)/(int) casts that used to guard the
multiplications and subtractions in *_us / *_ms / *_ns helpers are no
longer needed.  Drop them to keep the timekeeping math readable.

In the same spirit, this commit also normalises the printf-style format
specifiers and casts used to print tv_sec / tv_nsec / tv_usec values.
The prior code was a mix of "%d"/"%u"/"%ld"/"%lu"/"%lld" with matching
(int)/(unsigned long)/(long long) casts; some formats truncated time_t
on 32-bit hosts, others mismatched signedness or width.  Replace all
such cases with the portable POSIX-recommended forms:

  - tv_sec  (time_t,       signed, impl-defined width) -> %jd  + (intmax_t)
  - tv_nsec (long,         signed)                     -> %ld  (no cast)
  - tv_usec (suseconds_t / long)                       -> %ld  (no cast)

Also drop two stale `(FAR const time_t *)&ts.tv_sec` casts that are
unnecessary now that ts.tv_sec is plain time_t.

Arithmetic-cleanup files (existing scope):

  - benchmarks/cyclictest/cyclictest.c:        timediff_us()
  - benchmarks/sd_bench/sd_bench_main.c:       get_time_delta_us()
  - examples/oneshot/oneshot_main.c:           maxus computation
  - examples/watchdog/watchdog_main.c:         current_time_ms (x2)
  - industry/nxmodbus/nxmb_internal.h:         nxmb_util_clock_ms()
  - netutils/ntpclient/ntpclient.c:            timespec2ntp()
  - netutils/ptpd/ptpd.c:                      ptp_adjtime()
  - system/dd/dd_main.c:                       elapsed accounting
  - testing/drivers/drivertest/drivertest_posix_timer.c:
                                               get_timestamp()
  - testing/drivers/sd_stress/sd_stress_main.c:get_time_delta()
  - testing/sched/getprime/getprime_main.c:    elapsed accounting
  - testing/sched/pthread_mutex_perf/pthread_mutex_perf.c:
                                               timespec_avg()

Printf-format-fix files (new in this revision):

  - examples/adjtime/adjtime_main.c
  - examples/charger/charger_main.c
  - examples/netpkt/netpkt_ethercat.c
  - fsutils/mkfatfs/mkfatfs.c
  - graphics/tiff/tiff_initialize.c
  - netutils/ptpd/ptpd.c
  - nshlib/nsh_timcmds.c
  - system/coredump/coredump.c
  - system/ptpd/ptpd_main.c
  - testing/drivers/drivertest/drivertest_oneshot.c
  - testing/mm/kasantest/kasantest.c
  - testing/ostest/semtimed.c
  - testing/sched/pthread_mutex_perf/pthread_mutex_perf.c
  - testing/sched/timerjitter/timerjitter.c
  - testing/testsuites/kernel/time/cases/clock_test_clock01.c
  - testing/testsuites/kernel/time/cases/clock_test_smoke.c

No behavioural change.

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2026-05-22 13:38:25 +08:00

270 lines
7.1 KiB
C

/****************************************************************************
* apps/testing/ostest/semtimed.c
*
* SPDX-License-Identifier: Apache-2.0
*
* 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 <assert.h>
#include <errno.h>
#include <pthread.h>
#include <sched.h>
#include <semaphore.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include "ostest.h"
/****************************************************************************
* Preprocessor Definitions
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static sem_t sem;
/****************************************************************************
* Private Functions
****************************************************************************/
static void *poster_func(void *parameter)
{
int status;
/* Wait for one second, then post the semaphore */
printf("poster_func: Waiting for 1 second\n");
sleep(1);
printf("poster_func: Posting\n");
status = sem_post(&sem);
if (status != OK)
{
printf("poster_func: ERROR: sem_post failed\n");
ASSERT(false);
}
return NULL;
}
static void ostest_gettime(struct timespec *tp)
{
int status;
status = clock_gettime(CLOCK_REALTIME, tp);
if (status != OK)
{
printf("ostest_gettime: ERROR: clock_gettime failed\n");
ASSERT(false);
}
else if (tp->tv_sec < 0 || tp->tv_nsec < 0 ||
tp->tv_nsec >= 1000 * 1000 * 1000)
{
printf("ostest_gettime: ERROR: clock_gettime returned bogus time\n");
ASSERT(false);
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
void semtimed_test(void)
{
pthread_t poster_thread = (pthread_t)0;
#ifdef SDCC
pthread_addr_t result;
#endif
struct sched_param sparam;
struct timespec abstime;
struct timespec before;
struct timespec after;
int prio_min;
int prio_max;
int prio_mid;
int errcode;
pthread_attr_t attr;
int status;
printf("semtimed_test: Initializing semaphore to 0\n");
status = sem_init(&sem, 0, 0);
if (status != OK)
{
printf("semtimed_test: ERROR: sem_init failed\n");
ASSERT(false);
}
/* First,
* make sure that the timeout expires if the semaphore is never posted
*/
ostest_gettime(&before);
abstime.tv_sec = before.tv_sec + 2;
abstime.tv_nsec = before.tv_nsec;
printf("semtimed_test: Waiting for two second timeout\n");
status = sem_timedwait(&sem, &abstime);
errcode = errno;
ostest_gettime(&after);
if (status == OK)
{
printf("semtimed_test: ERROR: sem_timedwait succeeded\n");
ASSERT(false);
}
else
{
if (errcode == ETIMEDOUT)
{
printf("semtimed_test: PASS: first test returned timeout\n");
}
else
{
printf("semtimed_test: ERROR: sem_timedwait failed with: %d\n",
errcode);
ASSERT(false);
}
}
printf("BEFORE: (%jd sec, %ld nsec)\n",
(intmax_t)before.tv_sec, before.tv_nsec);
printf("AFTER: (%jd sec, %ld nsec)\n",
(intmax_t)after.tv_sec, after.tv_nsec);
/* Now make sure that the time wait returns successfully if the semaphore
* is posted
*/
/* Start a poster thread. It will wait 1 seconds and post the semaphore */
printf("semtimed_test: Starting poster thread\n");
status = pthread_attr_init(&attr);
if (status != OK)
{
printf("semtimed_test: ERROR: pthread_attr_init failed, status=%d\n",
status);
ASSERT(false);
}
prio_min = sched_get_priority_min(SCHED_FIFO);
prio_max = sched_get_priority_max(SCHED_FIFO);
prio_mid = (prio_min + prio_max) / 2;
sparam.sched_priority = (prio_mid + prio_max) / 2;
status = pthread_attr_setschedparam(&attr, &sparam);
if (status != OK)
{
printf("semtimed_test: ERROR: "
"pthread_attr_setschedparam failed, status=%d\n", status);
ASSERT(false);
}
else
{
printf("semtimed_test: Set thread 1 priority to %d\n",
sparam.sched_priority);
}
printf("semtimed_test: Starting poster thread 3\n");
status = pthread_attr_init(&attr);
if (status != 0)
{
printf("semtimed_test: ERROR: pthread_attr_init failed, status=%d\n",
status);
ASSERT(false);
}
sparam.sched_priority = (prio_min + prio_mid) / 2;
status = pthread_attr_setschedparam(&attr, &sparam);
if (status != OK)
{
printf("semtimed_test: "
"ERROR pthread_attr_setschedparam failed, status=%d\n",
status);
ASSERT(false);
}
else
{
printf("semtimed_test: Set thread 3 priority to %d\n",
sparam.sched_priority);
}
status = pthread_create(&poster_thread, &attr, poster_func, NULL);
if (status != 0)
{
printf("semtimed_test: ERROR: Poster thread creation failed: %d\n",
status);
ASSERT(false);
sem_destroy(&sem);
return;
}
/* Up to two seconds for the semaphore to be posted */
ostest_gettime(&before);
abstime.tv_sec = before.tv_sec + 2;
abstime.tv_nsec = before.tv_nsec;
printf("semtimed_test: Waiting for two second timeout\n");
status = sem_timedwait(&sem, &abstime);
errcode = errno;
ostest_gettime(&after);
if (status < 0)
{
printf("semtimed_test: ERROR: sem_timedwait failed with: %d\n",
errcode);
ASSERT(false);
}
else
{
printf("semtimed_test: PASS: sem_timedwait succeeded\n");
}
printf("BEFORE: (%jd sec, %ld nsec)\n",
(intmax_t)before.tv_sec, before.tv_nsec);
printf("AFTER: (%jd sec, %ld nsec)\n",
(intmax_t)after.tv_sec, after.tv_nsec);
/* Clean up detritus left by the pthread */
#ifdef SDCC
if (poster_thread != (pthread_t)0)
{
pthread_join(poster_thread, &result);
}
#else
if (poster_thread != (pthread_t)0)
{
pthread_join(poster_thread, NULL);
}
#endif
sem_destroy(&sem);
}