* Copyright (C) 2016 Jens Axboe
*
*/
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static struct reader_thread reader_thread;
static struct writer_thread writer_thread;
-uint64_t utime_since(const struct timeval *s, const struct timeval *e)
+uint64_t utime_since(const struct timespec *s, const struct timespec *e)
{
long sec, usec;
uint64_t ret;
sec = e->tv_sec - s->tv_sec;
- usec = e->tv_usec - s->tv_usec;
+ usec = (e->tv_nsec - s->tv_nsec) / 1000;
if (sec > 0 && usec < 0) {
sec--;
usec += 1000000;
static int write_work(struct work_item *work)
{
- struct timeval s, e;
+ struct timespec s, e;
ssize_t ret;
- gettimeofday(&s, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &s);
ret = write(STDOUT_FILENO, work->buf, work->buf_size);
- gettimeofday(&e, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &e);
assert(ret == work->buf_size);
add_lat(&work->writer->s, utime_since(&s, &e), "write");
static void reader_work(struct work_item *work)
{
- struct timeval s, e;
+ struct timespec s, e;
ssize_t ret;
size_t left;
void *buf;
off_t off;
- gettimeofday(&s, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &s);
left = work->buf_size;
buf = work->buf;
buf += ret;
}
- gettimeofday(&e, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &e);
add_lat(&work->reader->s, utime_since(&s, &e), "read");
pthread_cond_signal(&rt->thread.cond);
} else {
int ret = pthread_create(&work->thread, NULL, reader_one_off, work);
- if (ret)
+ if (ret) {
fprintf(stderr, "pthread_create=%d\n", ret);
- else
- pthread_detach(work->thread);
+ } else {
+ ret = pthread_detach(work->thread);
+ if (ret)
+ fprintf(stderr, "pthread_detach=%d\n", ret);
+ }
}
}
static void init_thread(struct thread_data *thread)
{
- pthread_cond_init(&thread->cond, NULL);
- pthread_cond_init(&thread->done_cond, NULL);
+ pthread_condattr_t cattr;
+ int ret;
+
+ ret = pthread_condattr_init(&cattr);
+ assert(ret == 0);
+#ifdef CONFIG_PTHREAD_CONDATTR_SETCLOCK
+ ret = pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
+ assert(ret == 0);
+#endif
+ pthread_cond_init(&thread->cond, &cattr);
+ pthread_cond_init(&thread->done_cond, &cattr);
pthread_mutex_init(&thread->lock, NULL);
pthread_mutex_init(&thread->done_lock, NULL);
thread->exit = 0;
pthread_mutex_lock(&thread->done_lock);
if (fn) {
- struct timeval tv;
struct timespec ts;
- gettimeofday(&tv, NULL);
- ts.tv_sec = tv.tv_sec + 1;
- ts.tv_nsec = tv.tv_usec * 1000ULL;
+#ifdef CONFIG_PTHREAD_CONDATTR_SETCLOCK
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+#else
+ clock_gettime(CLOCK_REALTIME, &ts);
+#endif
+ ts.tv_sec++;
pthread_cond_timedwait(&thread->done_cond, &thread->done_lock, &ts);
fn(wt);
while ((c = getopt(argc, argv, "f:b:t:w:")) != -1) {
switch (c) {
case 'f':
+ if (file)
+ return usage(argv);
file = strdup(optarg);
break;
case 'b':
int main(int argc, char *argv[])
{
- struct timeval s, re, we;
+ pthread_condattr_t cattr;
+ struct timespec s, re, we;
struct reader_thread *rt;
struct writer_thread *wt;
unsigned long rate;
+ uint64_t elapsed;
struct stat sb;
size_t bytes;
off_t off;
int fd, seq;
+ int ret;
if (parse_options(argc, argv))
return 1;
seq = 0;
bytes = 0;
- gettimeofday(&s, NULL);
+ ret = pthread_condattr_init(&cattr);
+ assert(ret == 0);
+#ifdef CONFIG_PTHREAD_CONDATTR_SETCLOCK
+ ret = pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
+ assert(ret == 0);
+#endif
+
+ clock_gettime(CLOCK_MONOTONIC, &s);
while (sb.st_size) {
struct work_item *work;
size_t this_len;
struct timespec ts;
- struct timeval tv;
prune_done_entries(wt);
work->seq = ++seq;
work->writer = wt;
work->reader = rt;
- pthread_cond_init(&work->cond, NULL);
+ pthread_cond_init(&work->cond, &cattr);
pthread_mutex_init(&work->lock, NULL);
queue_work(rt, work);
- gettimeofday(&tv, NULL);
- ts.tv_sec = tv.tv_sec;
- ts.tv_nsec = tv.tv_usec * 1000ULL;
+#ifdef CONFIG_PTHREAD_CONDATTR_SETCLOCK
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+#else
+ clock_gettime(CLOCK_REALTIME, &ts);
+#endif
ts.tv_nsec += max_us * 1000ULL;
if (ts.tv_nsec >= 1000000000ULL) {
ts.tv_nsec -= 1000000000ULL;
}
exit_thread(&rt->thread, NULL, NULL);
- gettimeofday(&re, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &re);
exit_thread(&wt->thread, prune_done_entries, wt);
- gettimeofday(&we, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &we);
show_latencies(&rt->s, "READERS");
show_latencies(&wt->s, "WRITERS");
bytes /= 1024;
- rate = (bytes * 1000UL * 1000UL) / utime_since(&s, &re);
- fprintf(stderr, "Read rate (KB/sec) : %lu\n", rate);
- rate = (bytes * 1000UL * 1000UL) / utime_since(&s, &we);
- fprintf(stderr, "Write rate (KB/sec): %lu\n", rate);
+ elapsed = utime_since(&s, &re);
+ rate = elapsed ? (bytes * 1000UL * 1000UL) / elapsed : 0;
+ fprintf(stderr, "Read rate (KiB/sec) : %lu\n", rate);
+ elapsed = utime_since(&s, &we);
+ rate = elapsed ? (bytes * 1000UL * 1000UL) / elapsed : 0;
+ fprintf(stderr, "Write rate (KiB/sec): %lu\n", rate);
close(fd);
return 0;