aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2011-01-04 16:52:47 +0100
committerArnd Bergmann <arnd@arndb.de>2011-01-04 16:52:47 +0100
commitc95ea1903edac9851a976a2bb0e35037b66020a5 (patch)
tree331e691135a6ff27d94ca83bd06ceb805ecb3cbb
parent5acb726787452d09e8fc562c563e4ec02e8f340c (diff)
downloadflashbench-c95ea1903edac9851a976a2bb0e35037b66020a5.tar.gz
flashbench: make code more modular
This makes it possible to call programs from outside of vm.c, and moves all device access to dev.c, as a step towards integrating the flashbench front-end with the vm. Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--Makefile4
-rw-r--r--dev.c112
-rw-r--r--dev.h25
-rw-r--r--flashbench.c101
-rw-r--r--vm.c91
-rw-r--r--vm.h97
6 files changed, 243 insertions, 187 deletions
diff --git a/Makefile b/Makefile
index bdf4316..eb5af93 100644
--- a/Makefile
+++ b/Makefile
@@ -4,9 +4,9 @@ LDFLAGS := -lrt
all: flashbench vm
-flashbench: flashbench.c
+flashbench: flashbench.o dev.o
-vm: vm.c
+vm: vm.o dev.o
clean:
rm flashbench vm
diff --git a/dev.c b/dev.c
new file mode 100644
index 0000000..6bd209d
--- /dev/null
+++ b/dev.c
@@ -0,0 +1,112 @@
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sched.h>
+#include <string.h>
+#include <getopt.h>
+#include <stdbool.h>
+
+#include "dev.h"
+
+static inline long long time_to_ns(struct timespec *ts)
+{
+ return ts->tv_sec * 1000 * 1000 * 1000 + ts->tv_nsec;
+}
+
+static long long get_ns(void)
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ return time_to_ns(&ts);
+}
+
+long long time_read(struct device *dev, off_t pos, size_t size)
+{
+ static char readbuf[64 * 1024 * 1024] __attribute__((aligned(4096)));
+ long long now = get_ns();
+ ssize_t ret;
+
+ if (size > sizeof(readbuf))
+ return -ENOMEM;
+
+ do {
+ ret = pread(dev->fd, readbuf, size, pos % dev->size);
+ if (ret > 0) {
+ size -= ret;
+ pos += ret;
+ }
+ } while (ret > 0 || errno == -EAGAIN);
+
+ if (ret)
+ return -errno;
+
+ return get_ns() - now;
+}
+
+long long time_write(struct device *dev, off_t pos, size_t size, enum writebuf which)
+{
+ static char writebuf[64 * 1024 * 1024] __attribute__((aligned(4096)));
+ long long now = get_ns();
+ ssize_t ret;
+
+ if (size > sizeof(writebuf))
+ return -ENOMEM;
+
+ do {
+ ret = pwrite(dev->fd, writebuf, size, pos % dev->size);
+ if (ret > 0) {
+ size -= ret;
+ pos += ret;
+ }
+ } while (ret > 0 || errno == -EAGAIN);
+
+ if (ret)
+ return -errno;
+
+ return get_ns() - now;
+}
+
+static void set_rtprio(void)
+{
+ int ret;
+ struct sched_param p = {
+ .sched_priority = 10,
+ };
+ ret = sched_setscheduler(0, SCHED_FIFO, &p);
+ if (ret)
+ perror("sched_setscheduler");
+}
+
+
+int setup_dev(struct device *dev, const char *filename)
+{
+ set_rtprio();
+
+ dev->fd = open(filename, O_RDWR | O_DIRECT | O_SYNC | O_NOATIME);
+ if (dev->fd < 0) {
+ perror("open");
+ return -errno;
+ }
+
+ dev->size = lseek(dev->fd, 0, SEEK_END);
+ if (dev->size < 0) {
+ perror("seek");
+ return -errno;
+ }
+
+ return 0;
+}
+
+
+
diff --git a/dev.h b/dev.h
new file mode 100644
index 0000000..865a7c8
--- /dev/null
+++ b/dev.h
@@ -0,0 +1,25 @@
+#ifndef FLASHBENCH_DEV_H
+#define FLASHBENCH_DEV_H
+
+#include <unistd.h>
+
+struct device {
+ void *readbuf;
+ void *writebuf[3];
+ int fd;
+ ssize_t size;
+};
+
+enum writebuf {
+ WBUF_ZERO,
+ WBUF_ONE,
+ WBUF_RAND,
+};
+
+extern int setup_dev(struct device *dev, const char *filename);
+
+long long time_write(struct device *dev, off_t pos, size_t size, enum writebuf which);
+
+long long time_read(struct device *dev, off_t pos, size_t size);
+
+#endif /* FLASHBENCH_DEV_H */
diff --git a/flashbench.c b/flashbench.c
index 26f39d7..7a9b6d9 100644
--- a/flashbench.c
+++ b/flashbench.c
@@ -8,35 +8,18 @@
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
-#include <time.h>
#include <errno.h>
-#include <fcntl.h>
#include <limits.h>
-#include <sched.h>
#include <string.h>
#include <getopt.h>
#include <stdbool.h>
+#include "dev.h"
+
typedef long long ns_t;
-struct device {
- int fd;
- ssize_t size;
-};
#define returnif(x) do { typeof(x) __x = (x); if (__x < 0) return (__x); } while (0)
-static inline ns_t time_to_ns(struct timespec *ts)
-{
- return ts->tv_sec * 1000 * 1000 * 1000 + ts->tv_nsec;
-}
-
-static ns_t get_ns(void)
-{
- struct timespec ts;
- clock_gettime(CLOCK_REALTIME, &ts);
- return time_to_ns(&ts);
-}
-
static ns_t ns_min(int count, ns_t data[])
{
int i;
@@ -134,54 +117,6 @@ static void regression(ns_t ns[], off_t bytes[], int count, ns_t *atime, float *
*throughput = 1000.0 / slope;
}
-static ns_t time_read(struct device *dev, off_t pos, size_t size)
-{
- static char readbuf[64 * 1024 * 1024] __attribute__((aligned(4096)));
- ns_t now = get_ns();
- ssize_t ret;
-
- if (size > sizeof(readbuf))
- return -ENOMEM;
-
- do {
- ret = pread(dev->fd, readbuf, size, pos % dev->size);
- if (ret > 0) {
- size -= ret;
- pos += ret;
- }
- } while (ret > 0 || errno == -EAGAIN);
-
- if (ret)
- return -errno;
-
- return get_ns() - now;
-}
-
-#if 0
-static ns_t time_write(struct device *dev, off_t pos, size_t size)
-{
- static char writebuf[64 * 1024 * 1024] __attribute__((aligned(4096)));
- ns_t now = get_ns();
- ssize_t ret;
-
- if (size > sizeof(writebuf))
- return -ENOMEM;
-
- do {
- ret = pwrite(dev->fd, writebuf, size, pos % dev->size);
- if (ret > 0) {
- size -= ret;
- pos += ret;
- }
- } while (ret > 0 || errno == -EAGAIN);
-
- if (ret)
- return -errno;
-
- return get_ns() - now;
-}
-#endif
-
static void flush_read_cache(struct device *dev)
{
off_t cache_size = 1024 * 1024; /* FIXME: use detected size */
@@ -476,17 +411,6 @@ static int try_read_alignments(struct device *dev, int tries, int blocksize)
return 0;
}
-static void set_rtprio(void)
-{
- int ret;
- struct sched_param p = {
- .sched_priority = 10,
- };
- ret = sched_setscheduler(0, SCHED_FIFO, &p);
- if (ret)
- perror("sched_setscheduler");
-}
-
static void print_help(const char *name)
{
printf("%s [OPTION]... [DEVICE]\n", name);
@@ -615,25 +539,6 @@ static int parse_arguments(int argc, char **argv, struct arguments *args)
return 0;
}
-static int setup_dev(struct device *dev, struct arguments *args)
-{
- set_rtprio();
-
- dev->fd = open(args->dev, O_RDWR | O_DIRECT | O_SYNC | O_NOATIME);
- if (dev->fd < 0) {
- perror("open");
- return -errno;
- }
-
- dev->size = lseek(dev->fd, 0, SEEK_END);
- if (dev->size < 0) {
- perror("seek");
- return -errno;
- }
-
- return 0;
-}
-
static FILE *open_output(const char *filename)
{
if (!filename || !strcmp(filename, "-"))
@@ -651,7 +556,7 @@ int main(int argc, char **argv)
returnif(parse_arguments(argc, argv, &args));
- returnif(setup_dev(&dev, &args));
+ returnif(setup_dev(&dev, args.dev));
output = open_output(args.out);
if (!output) {
diff --git a/vm.c b/vm.c
index b370002..b321a91 100644
--- a/vm.c
+++ b/vm.c
@@ -6,23 +6,7 @@
#include <sys/types.h>
#include <stdlib.h>
-struct device;
-
-typedef union result res_t;
-
-enum resulttype {
- R_NONE,
- R_ARRAY,
- R_NS,
- R_BYTE,
- R_STRING,
-};
-
-union result {
- res_t *_p;
- long long l;
- char s[8];
-} __attribute__((aligned(8)));
+#include "vm.h"
static inline res_t *res_ptr(res_t r)
{
@@ -41,72 +25,6 @@ static inline res_t to_res(res_t *_p, enum resulttype t)
static const res_t res_null = { };
-struct operation {
- enum opcode {
- /* end of program marker */
- O_END = 0,
-
- /* basic operations */
- O_READ,
- O_WRITE_ZERO,
- O_WRITE_ONE,
- O_WRITE_RAND,
- O_ERASE,
-
- /* output */
- O_PRINT,
- O_PRINTF,
- O_FORMAT,
- O_NEWLINE,
-
- /* group */
- O_SEQUENCE,
- O_REPEAT,
-
- /* series */
- O_OFF_FIXED,
- O_OFF_POW2,
- O_OFF_LIN,
- O_OFF_RAND,
- O_LEN_POW2,
- O_MAX_POW2,
- O_MAX_LIN,
-
- /* reduce dimension */
- O_REDUCE,
-
- /* ignore result */
- O_DROP,
-
- /* end of list */
- O_MAX = O_DROP,
- } code;
-
- /* number of indirect results, if any */
- unsigned int num;
-
- /* command code specific value */
- long long val;
-
- /* output string for O_PRINT */
- const char *string;
-
- /* aggregation of results from children */
- enum {
- A_MINIMUM,
- A_MAXIMUM,
- A_AVERAGE,
- A_TOTAL,
- A_IGNORE,
- } aggregate;
-
- /* dynamic result contents */
- res_t result;
- unsigned int size_x;
- unsigned int size_y;
- enum resulttype r_type;
-};
-
struct syntax {
enum opcode opcode;
const char *name;
@@ -122,11 +40,10 @@ struct syntax {
};
static struct syntax syntax[];
-static int verbose = 0;
-#define pr_debug(...) do { if (verbose) printf(__VA_ARGS__); } while(0)
-#define return_err(...) do { printf(__VA_ARGS__); return NULL; } while(0)
-static struct operation *call(struct operation *op, struct device *dev,
+int verbose = 0;
+
+struct operation *call(struct operation *op, struct device *dev,
off_t off, off_t max, size_t len)
{
struct operation *next;
diff --git a/vm.h b/vm.h
new file mode 100644
index 0000000..ac23ead
--- /dev/null
+++ b/vm.h
@@ -0,0 +1,97 @@
+#ifndef FLASHBENCH_VM_H
+#define FLASHBENCH_VM_H
+
+#include <sys/types.h>
+
+typedef union result res_t;
+
+enum resulttype {
+ R_NONE,
+ R_ARRAY,
+ R_NS,
+ R_BYTE,
+ R_STRING,
+};
+
+union result {
+ res_t *_p;
+ long long l;
+ char s[8];
+} __attribute__((aligned(8)));
+
+struct device;
+
+struct operation {
+ enum opcode {
+ /* end of program marker */
+ O_END = 0,
+
+ /* basic operations */
+ O_READ,
+ O_WRITE_ZERO,
+ O_WRITE_ONE,
+ O_WRITE_RAND,
+ O_ERASE,
+
+ /* output */
+ O_PRINT,
+ O_PRINTF,
+ O_FORMAT,
+ O_NEWLINE,
+
+ /* group */
+ O_SEQUENCE,
+ O_REPEAT,
+
+ /* series */
+ O_OFF_FIXED,
+ O_OFF_POW2,
+ O_OFF_LIN,
+ O_OFF_RAND,
+ O_LEN_POW2,
+ O_MAX_POW2,
+ O_MAX_LIN,
+
+ /* reduce dimension */
+ O_REDUCE,
+
+ /* ignore result */
+ O_DROP,
+
+ /* end of list */
+ O_MAX = O_DROP,
+ } code;
+
+ /* number of indirect results, if any */
+ unsigned int num;
+
+ /* command code specific value */
+ long long val;
+
+ /* output string for O_PRINT */
+ const char *string;
+
+ /* aggregation of results from children */
+ enum {
+ A_MINIMUM,
+ A_MAXIMUM,
+ A_AVERAGE,
+ A_TOTAL,
+ A_IGNORE,
+ } aggregate;
+
+ /* dynamic result contents */
+ res_t result;
+ unsigned int size_x;
+ unsigned int size_y;
+ enum resulttype r_type;
+};
+
+extern struct operation *call(struct operation *program, struct device *dev,
+ off_t off, off_t max, size_t len);
+
+extern int verbose;
+#define pr_debug(...) do { if (verbose) printf(__VA_ARGS__); } while(0)
+#define return_err(...) do { printf(__VA_ARGS__); return NULL; } while(0)
+
+#endif /* FLASHBENCH_VM_H */