[Midnightbsd-cvs] src [11673] trunk/tools/tools/syscall_timing: update syscall timing based on freebsd 10 stable

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sun Jul 8 16:11:14 EDT 2018


Revision: 11673
          http://svnweb.midnightbsd.org/src/?rev=11673
Author:   laffer1
Date:     2018-07-08 16:11:13 -0400 (Sun, 08 Jul 2018)
Log Message:
-----------
update syscall timing based on freebsd 10 stable

Modified Paths:
--------------
    trunk/tools/tools/syscall_timing/Makefile
    trunk/tools/tools/syscall_timing/syscall_timing.c

Modified: trunk/tools/tools/syscall_timing/Makefile
===================================================================
--- trunk/tools/tools/syscall_timing/Makefile	2018-07-08 20:10:30 UTC (rev 11672)
+++ trunk/tools/tools/syscall_timing/Makefile	2018-07-08 20:11:13 UTC (rev 11673)
@@ -1,9 +1,10 @@
+# $MidnightBSD$
 #
-# $FreeBSD: src/tools/tools/syscall_timing/Makefile,v 1.3 2004/12/21 08:47:29 ru Exp $
+# $FreeBSD: stable/10/tools/tools/syscall_timing/Makefile 276486 2014-12-31 23:25:37Z ngie $
 #
 
 PROG=	syscall_timing
 CFLAGS+=	-static -O
-NO_MAN=
+MAN=
 
 .include <bsd.prog.mk>

Modified: trunk/tools/tools/syscall_timing/syscall_timing.c
===================================================================
--- trunk/tools/tools/syscall_timing/syscall_timing.c	2018-07-08 20:10:30 UTC (rev 11672)
+++ trunk/tools/tools/syscall_timing/syscall_timing.c	2018-07-08 20:11:13 UTC (rev 11673)
@@ -1,7 +1,11 @@
+/* $MidnightBSD$ */
 /*-
- * Copyright (c) 2003-2004 Robert N. M. Watson
+ * Copyright (c) 2003-2004, 2010 Robert N. M. Watson
  * All rights reserved.
  *
+ * Portions of this software were developed at the University of Cambridge
+ * Computer Laboratory with support from a grant from Google, Inc.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -23,74 +27,146 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/tools/tools/syscall_timing/syscall_timing.c,v 1.3 2005/08/03 17:33:46 rwatson Exp $
+ * $FreeBSD: stable/10/tools/tools/syscall_timing/syscall_timing.c 260627 2014-01-14 14:03:28Z pluknet $
  */
 
 #include <sys/types.h>
+#include <sys/mman.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
 #include <sys/time.h>
+#include <sys/wait.h>
 
 #include <assert.h>
+#include <err.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-#define timespecsub(vvp, uvp)                                           \
-        do {                                                            \
-                (vvp)->tv_sec -= (uvp)->tv_sec;                         \
-                (vvp)->tv_nsec -= (uvp)->tv_nsec;                       \
-                if ((vvp)->tv_nsec < 0) {                               \
-                        (vvp)->tv_sec--;                                \
-                        (vvp)->tv_nsec += 1000000000;                   \
-                }                                                       \
-        } while (0)
+static struct timespec ts_start, ts_end;
+static int alarm_timeout;
+static volatile int alarm_fired;
 
-inline void
-test_getuid(int num)
+#define timespecsub(vvp, uvp)						\
+	do {								\
+		(vvp)->tv_sec -= (uvp)->tv_sec;				\
+		(vvp)->tv_nsec -= (uvp)->tv_nsec;			\
+		if ((vvp)->tv_nsec < 0) {				\
+			(vvp)->tv_sec--;				\
+			(vvp)->tv_nsec += 1000000000;			\
+		}							\
+	} while (0)
+
+static void
+alarm_handler(int signum)
 {
-	int i;
 
+	alarm_fired = 1;
+}
+
+static void
+benchmark_start(void)
+{
+	int error;
+
+	alarm_fired = 0;
+	if (alarm_timeout) {
+		signal(SIGALRM, alarm_handler);
+		alarm(alarm_timeout);
+	}
+	error = clock_gettime(CLOCK_REALTIME, &ts_start);
+	assert(error == 0);
+}
+
+static void
+benchmark_stop(void)
+{
+	int error;
+
+	error = clock_gettime(CLOCK_REALTIME, &ts_end);
+	assert(error == 0);
+}
+  
+uintmax_t
+test_getuid(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	uintmax_t i;
+
 	/*
 	 * Thread-local data should require no locking if system
 	 * call is MPSAFE.
 	 */
-	for (i = 0; i < num; i++)
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
 		getuid();
+	}
+	benchmark_stop();
+	return (i);
 }
 
-inline void
-test_getppid(int num)
+uintmax_t
+test_getppid(uintmax_t num, uintmax_t int_arg, const char *path)
 {
-	int i;
+	uintmax_t i;
 
 	/*
 	 * This is process-local, but can change, so will require a
 	 * lock.
 	 */
-	for (i = 0; i < num; i++)
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
 		getppid();
+	}
+	benchmark_stop();
+	return (i);
 }
 
-inline void
-test_clock_gettime(int num)
+uintmax_t
+test_clock_gettime(uintmax_t num, uintmax_t int_arg, const char *path)
 {
 	struct timespec ts;
-	int i;
+	uintmax_t i;
 
+	benchmark_start();
 	for (i = 0; i < num; i++) {
-		if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
-			perror("clock_gettime");
-			exit(-1);
-		}
+		if (alarm_fired)
+			break;
+		(void)clock_gettime(CLOCK_REALTIME, &ts);
 	}
+	benchmark_stop();
+	return (i);
 }
 
-inline void
-test_pipe(int num)
+uintmax_t
+test_gettimeofday(uintmax_t num, uintmax_t int_arg, const char *path)
 {
-	int i;
+	struct timeval tv;
+	uintmax_t i;
 
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		(void)gettimeofday(&tv, NULL);
+	}
+	benchmark_stop();
+	return (i);
+}
+
+uintmax_t
+test_pipe(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	int fd[2], i;
+
 	/*
 	 * pipe creation is expensive, as it will allocate a new file
 	 * descriptor, allocate a new pipe, hook it all up, and return.
@@ -97,87 +173,518 @@
 	 * Destroying is also expensive, as we now have to free up
 	 * the file descriptors and return the pipe.
 	 */
+	if (pipe(fd) < 0)
+		err(-1, "test_pipe: pipe");
+	close(fd[0]);
+	close(fd[1]);
+	benchmark_start();
 	for (i = 0; i < num; i++) {
-		int fd[2];
-		if (pipe(fd) == -1) {
-			perror("pipe");
-			exit(-1);
-		}
-
+		if (alarm_fired)
+			break;
+		if (pipe(fd) == -1)
+			err(-1, "test_pipe: pipe");
 		close(fd[0]);
 		close(fd[1]);
 	}
+	benchmark_stop();
+	return (i);
 }
 
-inline void
-test_socket_stream(int num)
+uintmax_t
+test_socket_stream(uintmax_t num, uintmax_t int_arg, const char *path)
 {
-	int i, so;
+	uintmax_t i;
+	int so;
 
+	so = socket(int_arg, SOCK_STREAM, 0);
+	if (so < 0)
+		err(-1, "test_socket_stream: socket");
+	close(so);
+	benchmark_start();
 	for (i = 0; i < num; i++) {
-		so = socket(PF_LOCAL, SOCK_STREAM, 0);
-		if (so == -1) {
-			perror("socket_stream");
-			exit(-1);
-		}
+		if (alarm_fired)
+			break;
+		so = socket(int_arg, SOCK_STREAM, 0);
+		if (so == -1)
+			err(-1, "test_socket_stream: socket");
 		close(so);
 	}
+	benchmark_stop();
+	return (i);
 }
 
-inline void
-test_socket_dgram(int num)
+uintmax_t
+test_socket_dgram(uintmax_t num, uintmax_t int_arg, const char *path)
 {
-	int i, so;
+	uintmax_t i;
+	int so;
 
+	so = socket(int_arg, SOCK_DGRAM, 0);
+	if (so < 0)
+		err(-1, "test_socket_dgram: socket");
+	close(so);
+	benchmark_start();
 	for (i = 0; i < num; i++) {
-		so = socket(PF_LOCAL, SOCK_DGRAM, 0);
-		if (so == -1) {
-			perror("socket_dgram");
-			exit(-1);
-		}
+		if (alarm_fired)
+			break;
+		so = socket(int_arg, SOCK_DGRAM, 0);
+		if (so == -1)
+			err(-1, "test_socket_dgram: socket");
 		close(so);
 	}
+	benchmark_stop();
+	return (i);
 }
 
-inline void
-test_socketpair_stream(int num)
+uintmax_t
+test_socketpair_stream(uintmax_t num, uintmax_t int_arg, const char *path)
 {
-	int i, so[2];
+	uintmax_t i;
+	int so[2];
 
+	if (socketpair(PF_LOCAL, SOCK_STREAM, 0, so) == -1)
+		err(-1, "test_socketpair_stream: socketpair");
+	close(so[0]);
+	close(so[1]);
+	benchmark_start();
 	for (i = 0; i < num; i++) {
-		if (socketpair(PF_LOCAL, SOCK_STREAM, 0, so) == -1) {
-			perror("socketpair_stream");
-			exit(-1);
-		}
+		if (alarm_fired)
+			break;
+		if (socketpair(PF_LOCAL, SOCK_STREAM, 0, so) == -1)
+			err(-1, "test_socketpair_stream: socketpair");
 		close(so[0]);
 		close(so[1]);
 	}
+	benchmark_stop();
+	return (i);
 }
 
-inline void
-test_socketpair_dgram(int num)
+uintmax_t
+test_socketpair_dgram(uintmax_t num, uintmax_t int_arg, const char *path)
 {
-	int i, so[2];
+	uintmax_t i;
+	int so[2];
 
+	if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, so) == -1)
+		err(-1, "test_socketpair_dgram: socketpair");
+	close(so[0]);
+	close(so[1]);
+	benchmark_start();
 	for (i = 0; i < num; i++) {
-		if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, so) == -1) {
-			perror("socketpair_dgram");
-			exit(-1);
-		}
+		if (alarm_fired)
+			break;
+		if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, so) == -1)
+			err(-1, "test_socketpair_dgram: socketpair");
 		close(so[0]);
 		close(so[1]);
 	}
+	benchmark_stop();
+	return (i);
 }
 
+uintmax_t
+test_create_unlink(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	uintmax_t i;
+	int fd;
+
+	(void)unlink(path);
+	fd = open(path, O_RDWR | O_CREAT, 0600);
+	if (fd < 0)
+		err(-1, "test_create_unlink: create: %s", path);
+	close(fd);
+	if (unlink(path) < 0)
+		err(-1, "test_create_unlink: unlink: %s", path);
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		fd = open(path, O_RDWR | O_CREAT, 0600);
+		if (fd < 0)
+			err(-1, "test_create_unlink: create: %s", path);
+		close(fd);
+		if (unlink(path) < 0)
+			err(-1, "test_create_unlink: unlink: %s", path);
+	}
+	benchmark_stop();
+	return (i);
+}
+
+uintmax_t
+test_open_close(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	uintmax_t i;
+	int fd;
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		err(-1, "test_open_close: %s", path);
+	close(fd);
+
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		fd = open(path, O_RDONLY);
+		if (fd < 0)
+			err(-1, "test_open_close: %s", path);
+		close(fd);
+	}
+	benchmark_stop();
+	return (i);
+}
+
+uintmax_t
+test_read(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	char buf[int_arg];
+	uintmax_t i;
+	int fd;
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		err(-1, "test_open_read: %s", path);
+	(void)pread(fd, buf, int_arg, 0);
+
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		(void)pread(fd, buf, int_arg, 0);
+	}
+	benchmark_stop();
+	close(fd);
+	return (i);
+}
+
+uintmax_t
+test_open_read_close(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	char buf[int_arg];
+	uintmax_t i;
+	int fd;
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		err(-1, "test_open_read_close: %s", path);
+	(void)read(fd, buf, int_arg);
+	close(fd);
+
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		fd = open(path, O_RDONLY);
+		if (fd < 0)
+			err(-1, "test_open_read_close: %s", path);
+		(void)read(fd, buf, int_arg);
+		close(fd);
+	}
+	benchmark_stop();
+	return (i);
+}
+
+uintmax_t
+test_dup(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	int fd, i, shmfd;
+
+	shmfd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0600);
+	if (shmfd < 0)
+		err(-1, "test_dup: shm_open");
+	fd = dup(shmfd);
+	if (fd >= 0)
+		close(fd);
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		fd = dup(shmfd);
+		if (fd >= 0)
+			close(fd);
+	}
+	benchmark_stop();
+	close(shmfd);
+	return (i);
+}
+
+uintmax_t
+test_shmfd(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	uintmax_t i;
+	int shmfd;
+
+	shmfd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0600);
+	if (shmfd < 0)
+		err(-1, "test_shmfd: shm_open");
+	close(shmfd);
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		shmfd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0600);
+		if (shmfd < 0)
+			err(-1, "test_shmfd: shm_open");
+		close(shmfd);
+	}
+	benchmark_stop();
+	return (i);
+}
+
+uintmax_t
+test_fstat_shmfd(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	struct stat sb;
+	uintmax_t i;
+	int shmfd;
+
+	shmfd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0600);
+	if (shmfd < 0)
+		err(-1, "test_fstat_shmfd: shm_open");
+	if (fstat(shmfd, &sb) < 0)
+		err(-1, "test_fstat_shmfd: fstat");
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		(void)fstat(shmfd, &sb);
+	}
+	benchmark_stop();
+	close(shmfd);
+	return (i);
+}
+
+uintmax_t
+test_fork(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	pid_t pid;
+	uintmax_t i;
+
+	pid = fork();
+	if (pid < 0)
+		err(-1, "test_fork: fork");
+	if (pid == 0)
+		_exit(0);
+	if (waitpid(pid, NULL, 0) < 0)
+		err(-1, "test_fork: waitpid");
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		pid = fork();
+		if (pid < 0)
+			err(-1, "test_fork: fork");
+		if (pid == 0)
+			_exit(0);
+		if (waitpid(pid, NULL, 0) < 0)
+			err(-1, "test_fork: waitpid");
+	}
+	benchmark_stop();
+	return (i);
+}
+
+uintmax_t
+test_vfork(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	pid_t pid;
+	uintmax_t i;
+
+	pid = vfork();
+	if (pid < 0)
+		err(-1, "test_vfork: vfork");
+	if (pid == 0)
+		_exit(0);
+	if (waitpid(pid, NULL, 0) < 0)
+		err(-1, "test_vfork: waitpid");
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		pid = vfork();
+		if (pid < 0)
+			err(-1, "test_vfork: vfork");
+		if (pid == 0)
+			_exit(0);
+		if (waitpid(pid, NULL, 0) < 0)
+			err(-1, "test_vfork: waitpid");
+	}
+	benchmark_stop();
+	return (i);
+}
+
+#define	USR_BIN_TRUE	"/usr/bin/true"
+static char *execve_args[] = { USR_BIN_TRUE, NULL};
+extern char **environ;
+
+uintmax_t
+test_fork_exec(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	pid_t pid;
+	uintmax_t i;
+
+	pid = fork();
+	if (pid < 0)
+		err(-1, "test_fork_exec: fork");
+	if (pid == 0) {
+		(void)execve(USR_BIN_TRUE, execve_args, environ);
+		err(-1, "execve");
+	}
+	if (waitpid(pid, NULL, 0) < 0)
+		err(-1, "test_fork: waitpid");
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		pid = fork();
+		if (pid < 0)
+			err(-1, "test_fork_exec: fork");
+		if (pid == 0) {
+			(void)execve(USR_BIN_TRUE, execve_args, environ);
+			err(-1, "test_fork_exec: execve");
+		}
+		if (waitpid(pid, NULL, 0) < 0)
+			err(-1, "test_fork_exec: waitpid");
+	}
+	benchmark_stop();
+	return (i);
+}
+
+uintmax_t
+test_vfork_exec(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	pid_t pid;
+	uintmax_t i;
+
+	pid = vfork();
+	if (pid < 0)
+		err(-1, "test_vfork_exec: vfork");
+	if (pid == 0) {
+		(void)execve(USR_BIN_TRUE, execve_args, environ);
+		err(-1, "test_vfork_exec: execve");
+	}
+	if (waitpid(pid, NULL, 0) < 0)
+		err(-1, "test_vfork_exec: waitpid");
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		pid = vfork();
+		if (pid < 0)
+			err(-1, "test_vfork_exec: vfork");
+		if (pid == 0) {
+			(void)execve(USR_BIN_TRUE, execve_args, environ);
+			err(-1, "execve");
+		}
+		if (waitpid(pid, NULL, 0) < 0)
+			err(-1, "test_vfork_exec: waitpid");
+	}
+	benchmark_stop();
+	return (i);
+}
+
+uintmax_t
+test_chroot(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	uintmax_t i;
+
+	if (chroot("/") < 0)
+		err(-1, "test_chroot: chroot");
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		if (chroot("/") < 0)
+			err(-1, "test_chroot: chroot");
+	}
+	benchmark_stop();
+	return (i);
+}
+
+uintmax_t
+test_setuid(uintmax_t num, uintmax_t int_arg, const char *path)
+{
+	uid_t uid;
+	uintmax_t i;
+
+	uid = getuid();
+	if (setuid(uid) < 0)
+		err(-1, "test_setuid: setuid");
+	benchmark_start();
+	for (i = 0; i < num; i++) {
+		if (alarm_fired)
+			break;
+		if (setuid(uid) < 0)
+			err(-1, "test_setuid: setuid");
+	}
+	benchmark_stop();
+	return (i);
+}
+
+struct test {
+	const char	*t_name;
+	uintmax_t	(*t_func)(uintmax_t, uintmax_t, const char *);
+	int		 t_flags;
+	uintmax_t	 t_int;
+};
+
+#define	FLAG_PATH	0x00000001
+
+static const struct test tests[] = {
+	{ "getuid", test_getuid },
+	{ "getppid", test_getppid },
+	{ "clock_gettime", test_clock_gettime },
+	{ "gettimeofday", test_gettimeofday },
+	{ "pipe", test_pipe },
+	{ "socket_local_stream", test_socket_stream, .t_int = PF_LOCAL },
+	{ "socket_local_dgram", test_socket_dgram, .t_int = PF_LOCAL },
+	{ "socketpair_stream", test_socketpair_stream },
+	{ "socketpair_dgram", test_socketpair_dgram },
+	{ "socket_tcp", test_socket_stream, .t_int = PF_INET },
+	{ "socket_udp", test_socket_dgram, .t_int = PF_INET },
+	{ "create_unlink", test_create_unlink, .t_flags = FLAG_PATH },
+	{ "open_close", test_open_close, .t_flags = FLAG_PATH },
+	{ "open_read_close_1", test_open_read_close, .t_flags = FLAG_PATH,
+	    .t_int = 1 },
+	{ "open_read_close_10", test_open_read_close, .t_flags = FLAG_PATH,
+	    .t_int = 10 },
+	{ "open_read_close_100", test_open_read_close, .t_flags = FLAG_PATH,
+	    .t_int = 100 },
+	{ "open_read_close_1000", test_open_read_close, .t_flags = FLAG_PATH,
+	    .t_int = 1000 },
+	{ "open_read_close_10000", test_open_read_close,
+	    .t_flags = FLAG_PATH, .t_int = 10000 },
+	{ "open_read_close_100000", test_open_read_close,
+	    .t_flags = FLAG_PATH, .t_int = 100000 },
+	{ "open_read_close_1000000", test_open_read_close,
+	    .t_flags = FLAG_PATH, .t_int = 1000000 },
+	{ "read_1", test_read, .t_flags = FLAG_PATH, .t_int = 1 },
+	{ "read_10", test_read, .t_flags = FLAG_PATH, .t_int = 10 },
+	{ "read_100", test_read, .t_flags = FLAG_PATH, .t_int = 100 },
+	{ "read_1000", test_read, .t_flags = FLAG_PATH, .t_int = 1000 },
+	{ "read_10000", test_read, .t_flags = FLAG_PATH, .t_int = 10000 },
+	{ "read_100000", test_read, .t_flags = FLAG_PATH, .t_int = 100000 },
+	{ "read_1000000", test_read, .t_flags = FLAG_PATH, .t_int = 1000000 },
+	{ "dup", test_dup },
+	{ "shmfd", test_shmfd },
+	{ "fstat_shmfd", test_fstat_shmfd },
+	{ "fork", test_fork },
+	{ "vfork", test_vfork },
+	{ "fork_exec", test_fork_exec },
+	{ "vfork_exec", test_vfork_exec },
+	{ "chroot", test_chroot },
+	{ "setuid", test_setuid },
+};
+static const int tests_count = sizeof(tests) / sizeof(tests[0]);
+
 static void
 usage(void)
 {
+	int i;
 
-	fprintf(stderr, "syscall_timing [iterations] [test]\n");
-	fprintf(stderr,
-	    "supported tests: getuid getppid clock_gettime pipe\n"
-	    "socket_stream socket_dgram socketpair_stream\n"
-	    "socketpair_dgram\n");
+	fprintf(stderr, "syscall_timing [-i iterations] [-l loops] "
+	    "[-p path] [-s seconds] test\n");
+	for (i = 0; i < tests_count; i++)
+		fprintf(stderr, "  %s\n", tests[i].t_name);
 	exit(-1);
 }
 
@@ -184,66 +691,119 @@
 int
 main(int argc, char *argv[])
 {
-	struct timespec ts_start, ts_end, ts_res;
-	int count;
+	struct timespec ts_res;
+	const struct test *the_test;
+	const char *path;
+	long long ll;
+	char *endp;
+	int ch, error, i, j, k;
+	uintmax_t iterations, loops;
 
-	if (argc != 3)
-		usage();
-	count = atoi(argv[1]);
+	alarm_timeout = 1;
+	iterations = 0;
+	loops = 10;
+	path = NULL;
+	while ((ch = getopt(argc, argv, "i:l:p:s:")) != -1) {
+		switch (ch) {
+		case 'i':
+			ll = strtol(optarg, &endp, 10);
+			if (*endp != 0 || ll < 1 || ll > 100000)
+				usage();
+			iterations = ll;
+			break;
 
-	assert(clock_getres(CLOCK_REALTIME, &ts_res) == 0);
-	printf("Clock resolution: %d.%09lu\n", ts_res.tv_sec, ts_res.tv_nsec);
+		case 'l':
+			ll = strtol(optarg, &endp, 10);
+			if (*endp != 0 || ll < 1 || ll > 100000)
+				usage();
+			loops = ll;
+			break;
 
-	if (strcmp(argv[2], "getuid") == 0) {
-		assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0);
-		test_getuid(count);
-		assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0);
-	} else if (strcmp(argv[2], "getppid") == 0) {
-		assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0);
-		test_getppid(count);
-		assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0);
-	} else if (strcmp(argv[2], "clock_gettime") == 0) {
-		assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0);
-		test_clock_gettime(count);
-		assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0);
-	} else if (strcmp(argv[2], "pipe") == 0) {
-		assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0);
-		test_pipe(count);
-		assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0);
-	} else if (strcmp(argv[2], "socket_stream") == 0) {
-		assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0);
-		test_socket_stream(count);
-		assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0);
-	} else if (strcmp(argv[2], "socket_dgram") == 0) {
-		assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0);
-		test_socket_dgram(count);
-		assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0);
-	} else if (strcmp(argv[2], "socketpair_stream") == 0) {
-		assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0);
-		test_socketpair_stream(count);
-		assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0);
-	} else if (strcmp(argv[2], "socketpair_dgram") == 0) {
-		assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0);
-		test_socketpair_dgram(count);
-		assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0);
-	 } else
-		usage();
+		case 'p':
+			path = optarg;
+			break;
 
-	timespecsub(&ts_end, &ts_start);
+		case 's':
+			ll = strtol(optarg, &endp, 10);
+			if (*endp != 0 || ll < 1 || ll > 60*60)
+				usage();
+			alarm_timeout = ll;
+			break;
 
-	printf("test: %s\n", argv[2]);
+		case '?':
+		default:
+			usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
 
-	printf("%d.%09lu for %d iterations\n", ts_end.tv_sec,
-	    ts_end.tv_nsec, count);
+	if (iterations < 1 && alarm_timeout < 1)
+		usage();
+	if (iterations < 1)
+		iterations = UINT64_MAX;
+	if (loops < 1)
+		loops = 1;
 
+	if (argc < 1)
+		usage();
+
 	/*
-	 * Note.  This assumes that each iteration takes less than
-	 * a second, and that our total nanoseconds doesn't exceed
-	 * the room in our arithmetic unit.  Fine for system calls,
-	 * but not for long things.
+	 * Validate test list and that, if a path is required, it is
+	 * defined.
 	 */
-	ts_end.tv_sec *= 1000000000 / count;
-	printf("0.%09lu per/iteration\n", 
-	    ts_end.tv_sec + ts_end.tv_nsec / count);
+	for (j = 0; j < argc; j++) {
+		the_test = NULL;
+		for (i = 0; i < tests_count; i++) {
+			if (strcmp(argv[j], tests[i].t_name) == 0)
+				the_test = &tests[i];
+		}
+		if (the_test == NULL)
+			usage();
+		if ((the_test->t_flags & FLAG_PATH) && (path == NULL)) {
+			errx(-1, "%s requires -p", the_test->t_name);
+		}
+	}
+
+	error = clock_getres(CLOCK_REALTIME, &ts_res);
+	assert(error == 0);
+	printf("Clock resolution: %ju.%09ju\n", (uintmax_t)ts_res.tv_sec,
+	    (uintmax_t)ts_res.tv_nsec);
+	printf("test\tloop\ttime\titerations\tperiteration\n");
+
+	for (j = 0; j < argc; j++) {
+		uintmax_t calls, nsecsperit;
+
+		the_test = NULL;
+		for (i = 0; i < tests_count; i++) {
+			if (strcmp(argv[j], tests[i].t_name) == 0)
+				the_test = &tests[i];
+		}
+
+		/*
+		 * Run one warmup, then do the real thing (loops) times.
+		 */
+		the_test->t_func(iterations, the_test->t_int, path);
+		calls = 0;
+		for (k = 0; k < loops; k++) {
+			calls = the_test->t_func(iterations, the_test->t_int,
+			    path);
+			timespecsub(&ts_end, &ts_start);
+			printf("%s\t%d\t", the_test->t_name, k);
+			printf("%ju.%09ju\t%ju\t", (uintmax_t)ts_end.tv_sec,
+			    (uintmax_t)ts_end.tv_nsec, calls);
+
+		/*
+		 * Note.  This assumes that each iteration takes less than
+		 * a second, and that our total nanoseconds doesn't exceed
+		 * the room in our arithmetic unit.  Fine for system calls,
+		 * but not for long things.
+		 */
+			nsecsperit = ts_end.tv_sec * 1000000000;
+			nsecsperit += ts_end.tv_nsec;
+			nsecsperit /= calls;
+			printf("0.%09ju\n", (uintmax_t)nsecsperit);
+		}
+	}
 	return (0);
 }



More information about the Midnightbsd-cvs mailing list