mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-02 12:49:03 +00:00
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>
406 lines
10 KiB
C
406 lines
10 KiB
C
/****************************************************************************
|
|
* apps/system/resmonitor/filldisk.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 <dirent.h>
|
|
#include <errno.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/select.h>
|
|
#include <sys/statfs.h>
|
|
#include <syslog.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
#define PATHSIZE 70
|
|
#define FILESIZE 100
|
|
#define FILENAME "testpayload"
|
|
#define INTERVAL 0
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
static time_t interval = INTERVAL;
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
static int getdiv(uintmax_t count)
|
|
{
|
|
int div = 1000;
|
|
if (count > 1000)
|
|
{
|
|
div = 1000;
|
|
}
|
|
else if (count > 100)
|
|
{
|
|
div = 100;
|
|
}
|
|
else if (count > 10)
|
|
{
|
|
div = 10;
|
|
}
|
|
else
|
|
{
|
|
div = 1;
|
|
}
|
|
|
|
return div;
|
|
}
|
|
|
|
static uintmax_t
|
|
get_fillsize(char *filepath, int mode, uintmax_t remain, uintmax_t fill)
|
|
{
|
|
struct statfs diskinfo;
|
|
int ret = statfs(filepath, &diskinfo);
|
|
if (ret != 0)
|
|
{
|
|
syslog(LOG_ERR, "statfs fail!\n");
|
|
return -1;
|
|
}
|
|
|
|
uintmax_t bsize = (uintmax_t)diskinfo.f_bsize;
|
|
uintmax_t bavail = (uintmax_t)diskinfo.f_bavail;
|
|
uintmax_t t_size = bsize * bavail;
|
|
uintmax_t fillsize = 0;
|
|
if (mode == 1)
|
|
{
|
|
fillsize = t_size - remain;
|
|
}
|
|
else if (mode == 2)
|
|
{
|
|
fillsize = (fill < t_size) ? fill : t_size;
|
|
}
|
|
|
|
return fillsize;
|
|
}
|
|
|
|
static clock_t fill_disk(char *file, uintmax_t bufsize, int mode,
|
|
uintmax_t remain, uintmax_t fill)
|
|
{
|
|
FILE *fp;
|
|
clock_t start, finish;
|
|
struct timeval sleeptime;
|
|
int ret;
|
|
if ((fp = fopen(file, "a+")) == NULL)
|
|
{
|
|
syslog(LOG_ERR, "Fail to open file!\n");
|
|
return -1;
|
|
}
|
|
|
|
uintmax_t fillsize = get_fillsize(file, mode, remain, fill);
|
|
if (fillsize <= 0)
|
|
{
|
|
syslog(LOG_WARNING, "out of space !!\n");
|
|
fclose(fp);
|
|
return -1;
|
|
}
|
|
|
|
char *buf = (char *)malloc((size_t)bufsize);
|
|
if (!buf)
|
|
{
|
|
syslog(LOG_ERR, "malloc fail, errno %d\n", errno);
|
|
fclose(fp);
|
|
return -1;
|
|
}
|
|
|
|
memset(buf, 'a', (size_t)bufsize);
|
|
uintmax_t count = fillsize / bufsize;
|
|
int div = getdiv(count);
|
|
start = clock();
|
|
while (fillsize > bufsize)
|
|
{
|
|
ret = fwrite(buf, 1, bufsize, fp);
|
|
if (ret > 0)
|
|
{
|
|
fillsize -= ret;
|
|
count--;
|
|
}
|
|
else
|
|
{
|
|
syslog(LOG_ERR, "write fail \n");
|
|
fclose(fp);
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
|
|
sleeptime.tv_sec = interval / 1000000;
|
|
sleeptime.tv_usec = interval % 1000000;
|
|
select(0, NULL, NULL, NULL, &sleeptime);
|
|
if (count % div == 0)
|
|
{
|
|
syslog(LOG_INFO, "remain %ju B\n", fillsize);
|
|
fillsize = get_fillsize(file, mode, remain, fillsize);
|
|
if (fillsize < 0)
|
|
{
|
|
syslog(LOG_WARNING, "out of space !!\n");
|
|
fclose(fp);
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
|
|
count = fillsize / bufsize;
|
|
div = getdiv(count);
|
|
}
|
|
}
|
|
|
|
fwrite(buf, 1, fillsize, fp);
|
|
fflush(fp);
|
|
finish = clock();
|
|
syslog(LOG_INFO, "write complete !!!\n");
|
|
fclose(fp);
|
|
free(buf);
|
|
return finish - start;
|
|
}
|
|
|
|
static void show_usages(void)
|
|
{
|
|
syslog(LOG_WARNING,
|
|
"Usage: CMD [-d <dir>] [-f <fill size>] [-r <remain size>] [-b "
|
|
"<write buf size>] [-n <file nums>] [-i <write interval (us)>]\n"
|
|
"\t\t-d: set dir to fill (e.g. /data)\n"
|
|
"\t\t-f: set fill file size, can end with KkMm, (disabled if -r is "
|
|
"set)\n"
|
|
"\t\t-n: works only if -f is set, create n files of size -f set, "
|
|
"default 1\n"
|
|
"\t\t-r: set remain size, can end with KkMm\n"
|
|
"\t\t-b: set write buf size, can end with kKMm, default is f_bsize\n"
|
|
"\t\t-i: set write intervals (us), default 0 us, set only if the "
|
|
"program killed by wdt\n");
|
|
exit(1);
|
|
}
|
|
|
|
static void double2str(double f, char *s, int len)
|
|
{
|
|
int ret = snprintf(s, len, "%.2lf", f);
|
|
if (ret < 0)
|
|
{
|
|
syslog(LOG_ERR, "double to str fail, ret %d\n", ret);
|
|
}
|
|
}
|
|
|
|
static uintmax_t bytes(char *s)
|
|
{
|
|
uintmax_t n;
|
|
if (sscanf(s, "%ju", &n) < 1)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if ((s[strlen(s) - 1] == 'k') || (s[strlen(s) - 1] == 'K'))
|
|
{
|
|
n *= 1024;
|
|
}
|
|
|
|
if ((s[strlen(s) - 1] == 'm') || (s[strlen(s) - 1] == 'M'))
|
|
{
|
|
n *= (1024 * 1024);
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
static void print_disk_info(struct statfs *diskinfo)
|
|
{
|
|
syslog(LOG_INFO, "\tfs block size : %zu\n", diskinfo->f_bsize);
|
|
syslog(LOG_INFO,
|
|
"\tfs block nums : %ju\n",
|
|
(uintmax_t)diskinfo->f_blocks);
|
|
syslog(LOG_INFO,
|
|
"\tfs free blocks : %ju\n",
|
|
(uintmax_t)diskinfo->f_bfree);
|
|
syslog(LOG_INFO,
|
|
"\tfs free blocks available : %ju\n",
|
|
(uintmax_t)diskinfo->f_bavail);
|
|
syslog(LOG_INFO,
|
|
"\tfs total file nodes : %ju\n",
|
|
(uintmax_t)diskinfo->f_files);
|
|
syslog(LOG_INFO,
|
|
"\tfs free file nodes : %ju\n",
|
|
(uintmax_t)diskinfo->f_ffree);
|
|
}
|
|
|
|
int main(int argc, FAR char *argv[])
|
|
{
|
|
if (argc == 1)
|
|
{
|
|
show_usages();
|
|
return -1;
|
|
}
|
|
|
|
char filepath[PATHSIZE];
|
|
char sduration_t[15];
|
|
char sduration_w[15];
|
|
char sspeed_t[15];
|
|
char sspeed_w[15];
|
|
uintmax_t fill = 0;
|
|
uintmax_t remain = 0;
|
|
uintmax_t bufsize = 0;
|
|
int nf = 1;
|
|
int mode = 0;
|
|
clock_t write_t = 0;
|
|
struct statfs diskinfo_old;
|
|
struct statfs diskinfo_new;
|
|
uintmax_t fillsize;
|
|
double duration_t;
|
|
double speed_t;
|
|
double duration_w;
|
|
double speed_w;
|
|
clock_t start;
|
|
clock_t finish;
|
|
clock_t tmp;
|
|
int ret;
|
|
int o;
|
|
|
|
interval = INTERVAL;
|
|
memset(filepath, 0, PATHSIZE);
|
|
while ((o = getopt(argc, argv, "d:f:r:b:i:n:")) != EOF)
|
|
{
|
|
switch (o)
|
|
{
|
|
case 'd':
|
|
snprintf(filepath, PATHSIZE, "%s", optarg);
|
|
break;
|
|
case 'f':
|
|
fill = bytes(optarg);
|
|
if (mode != 1)
|
|
{
|
|
mode = 2;
|
|
}
|
|
|
|
break;
|
|
case 'r':
|
|
remain = bytes(optarg);
|
|
mode = 1;
|
|
break;
|
|
case 'i':
|
|
interval = bytes(optarg);
|
|
break;
|
|
case 'b':
|
|
bufsize = bytes(optarg);
|
|
break;
|
|
case 'n':
|
|
nf = atoi(optarg);
|
|
break;
|
|
default:
|
|
show_usages();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (strlen(filepath) == 0)
|
|
{
|
|
syslog(LOG_ERR, "please set dir \n");
|
|
return -1;
|
|
}
|
|
|
|
if (mode == 0)
|
|
{
|
|
syslog(LOG_ERR, "please set -f or -r \n");
|
|
return -1;
|
|
}
|
|
else if (mode != 2)
|
|
{
|
|
nf = 1;
|
|
}
|
|
|
|
ret = statfs(filepath, &diskinfo_old);
|
|
if (ret != 0)
|
|
{
|
|
syslog(LOG_ERR, "statfs fail!\n");
|
|
return -1;
|
|
}
|
|
|
|
if (bufsize == 0)
|
|
{
|
|
bufsize = diskinfo_old.f_bsize;
|
|
}
|
|
|
|
fillsize = get_fillsize(filepath, mode, remain, fill) * nf;
|
|
syslog(LOG_INFO, "outputfilepath: %s\n", filepath);
|
|
start = clock();
|
|
for (int i = 1; i <= nf; i++)
|
|
{
|
|
syslog(LOG_INFO, "create file %d, total %d\n", i, nf);
|
|
char file[FILESIZE];
|
|
ret = snprintf(file, FILESIZE, "%s/%s%d", filepath, FILENAME, i);
|
|
if (ret < 0)
|
|
{
|
|
syslog(LOG_ERR, "snprintf err, ret %d\n", ret);
|
|
return -1;
|
|
}
|
|
|
|
if ((tmp = fill_disk(file, bufsize, mode, remain, fill)) > 0)
|
|
{
|
|
write_t += tmp;
|
|
}
|
|
else
|
|
{
|
|
syslog(LOG_ERR, "fill disk error\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
finish = clock();
|
|
ret = statfs(filepath, &diskinfo_new);
|
|
if (ret != 0)
|
|
{
|
|
syslog(LOG_ERR, "statfs fail!\n");
|
|
return -1;
|
|
}
|
|
|
|
syslog(LOG_INFO, "***diskinfo before filldisk***\n");
|
|
print_disk_info(&diskinfo_old);
|
|
|
|
syslog(LOG_INFO, "***diskinfo after filldisk***\n");
|
|
print_disk_info(&diskinfo_new);
|
|
duration_t = (double)(finish - start) / CLOCKS_PER_SEC;
|
|
speed_t = fillsize / 1024.0 / duration_t;
|
|
duration_w = (double)(write_t) / CLOCKS_PER_SEC;
|
|
speed_w = fillsize / 1024.0 / duration_w;
|
|
double2str(speed_t, sspeed_t, 15);
|
|
double2str(speed_w, sspeed_w, 15);
|
|
double2str(duration_t, sduration_t, 15);
|
|
double2str(duration_w, sduration_w, 15);
|
|
syslog(LOG_INFO, "fill buf size: %ju\n", bufsize);
|
|
syslog(LOG_INFO, "total fill size: %ju\n", fillsize);
|
|
syslog(LOG_INFO,
|
|
"write speed (include open and close) %s KB/s, duration %s s\n",
|
|
sspeed_t,
|
|
sduration_t);
|
|
syslog(LOG_INFO,
|
|
"write speed (only write) %s KB/s, duration %s s\n",
|
|
sspeed_w,
|
|
sduration_w);
|
|
return 0;
|
|
}
|