--- /dev/null
+/* emikulic@gmail.com was here 2013 */
+#define _GNU_SOURCE /* for O_NOATIME and O_DIRECT */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <time.h>
+
+static const char scratch_file_name[] = "scratch";
+/* also block and fragment size of root fs: */
+static const size_t buf_size = 4096;
+/* write at most this often: */
+static const int period_usec = 500000;
+
+int main() {
+ int fd;
+ char *buf;
+
+ if (posix_memalign((void**)(&buf), buf_size, buf_size) != 0)
+ errx(1, "posix_memalign() failed");
+
+ if ((fd = open(scratch_file_name,
+ O_CREAT | O_TRUNC | O_NOATIME | O_RDWR | O_DIRECT,
+ 0600)) == -1)
+ err(1, "open() failed");
+ /* O_SYNC doesn't seem to be needed here. */
+
+ for (;;) {
+ ssize_t ret;
+ struct timespec t1, t2, tr;
+ int diff_sec, diff_nsec, sleep_len;
+
+ if (clock_gettime(CLOCK_REALTIME, &tr) == -1)
+ err(1, "clock_gettime() failed");
+ if (clock_gettime(CLOCK_MONOTONIC, &t1) == -1)
+ err(1, "clock_gettime() failed");
+
+ ret = pwrite(fd, buf, buf_size, 0);
+ if (ret == -1)
+ err(1, "pwrite() failed (errno=%d)", errno);
+ if (ret != buf_size)
+ warn("pwrite() returned %d, expected %d", (int)ret, (int)buf_size);
+
+ if (clock_gettime(CLOCK_MONOTONIC, &t2) == -1)
+ err(1, "clock_gettime() failed");
+
+ diff_sec = t2.tv_sec - t1.tv_sec;
+ diff_nsec = t2.tv_nsec - t1.tv_nsec;
+ if (diff_nsec < 0) {
+ diff_sec--;
+ diff_nsec += 1000000000;
+ }
+
+ printf("r %d.%09d m %d.%09d wr %d.%09d\n",
+ (int)tr.tv_sec, (int)tr.tv_nsec,
+ (int)t1.tv_sec, (int)t1.tv_nsec,
+ diff_sec, diff_nsec);
+ fflush(stdout);
+
+ if (diff_sec > 0) {
+ sleep_len = 1;
+ } else {
+ sleep_len = period_usec - diff_nsec / 1000;
+ if (sleep_len < 0)
+ sleep_len = 1;
+ }
+ usleep(sleep_len);
+ }
+ return 0;
+}
+/* vim:set ts=2 sw=2 et tw=80: */