diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2009-10-08 15:54:14 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2009-10-08 16:35:25 +0200 |
commit | 76f7b56c73ba495e38f79389de15d434b3f926bb (patch) | |
tree | 2f4220cf61ef710029d7f4f9b07a1dfd9a35658f | |
download | ptx-sisyphus-76f7b56c73ba495e38f79389de15d434b3f926bb.tar.gz ptx-sisyphus-76f7b56c73ba495e38f79389de15d434b3f926bb.tar.xz |
initial import
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r-- | GNUmakefile.am | 34 | ||||
-rwxr-xr-x | autogen-oldtools.sh | 45 | ||||
-rwxr-xr-x | autogen.sh | 22 | ||||
-rw-r--r-- | config/GNUmakefile.am | 8 | ||||
-rw-r--r-- | config/m4/.secret-world-domination-project | 0 | ||||
-rw-r--r-- | config/m4/acx_pthread.m4 | 238 | ||||
-rw-r--r-- | config/ptx-sisyphus.pc.in | 12 | ||||
-rw-r--r-- | configure.ac | 135 | ||||
-rw-r--r-- | include/GNUmakefile.am | 9 | ||||
-rw-r--r-- | include/gettext.h | 9 | ||||
-rw-r--r-- | include/ptx-sisyphusstuff.h | 5 | ||||
-rw-r--r-- | src/GNUmakefile.am | 42 | ||||
-rw-r--r-- | src/alignment.c | 46 | ||||
-rw-r--r-- | src/context-switches.c | 190 | ||||
-rw-r--r-- | src/ff_bench.c | 408 | ||||
-rw-r--r-- | src/float_bench.c | 843 | ||||
-rw-r--r-- | src/memxfer5b.c | 336 | ||||
-rw-r--r-- | src/pi8.c | 316 | ||||
-rw-r--r-- | src/timeout.c | 188 | ||||
-rwxr-xr-x | wizzard.sh | 35 |
20 files changed, 2921 insertions, 0 deletions
diff --git a/GNUmakefile.am b/GNUmakefile.am new file mode 100644 index 0000000..7f8d6f8 --- /dev/null +++ b/GNUmakefile.am @@ -0,0 +1,34 @@ +SUBDIRS = \ + include \ + config \ + src \ + tests + +EXTRA_DIST = \ + autogen.sh \ + config/m4/.secret-world-domination-project + +MAINTAINERCLEANFILES = \ + configure \ + GNUmakefile.in \ + aclocal.m4 \ + config/autoconf/compile \ + config/autoconf/config.guess \ + config/autoconf/config.sub \ + config/autoconf/depcomp \ + config/autoconf/install-sh \ + config/autoconf/ltmain.sh \ + config/autoconf/mdate-sh \ + config/autoconf/missing \ + config/autoconf/texinfo.tex \ + config/m4/libtool.m4 \ + config/m4/ltoptions.m4 \ + config/m4/ltsugar.m4 \ + config/m4/ltversion.m4 \ + config/m4/lt~obsolete.m4 \ + $(DIST_ARCHIVES) + +maintainer-clean-local: + -chmod -R a+rw $(distdir) + -rm -fr $(distdir) + diff --git a/autogen-oldtools.sh b/autogen-oldtools.sh new file mode 100755 index 0000000..cbb9522 --- /dev/null +++ b/autogen-oldtools.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# +# usage: +# +# banner <target name> +# +banner() { + + echo + TG=`echo $1 | sed -e "s,/.*/,,g"` + LINE=`echo $TG |sed -e "s/./-/g"` + echo $LINE + echo $TG + echo $LINE + echo +} + + +ACLOCAL=${ACLOCAL:=aclocal} +AUTOHEADER=${AUTOHEADER:=autoheader} +AUTOMAKE=${AUTOMAKE:=automake} +AUTOCONF=${AUTOCONF:=autoconf} + +banner "running libtoolize" +libtoolize --force +[ $? != 0 ] && exit + +banner "running aclocal" +$ACLOCAL -I config/m4 +[ $? != 0 ] && exit + +banner "running autoheader" +$AUTOHEADER +[ $? != 0 ] && exit + +banner "running automake" +$AUTOMAKE --gnu --add-missing -Wall +[ $? != 0 ] && exit + +banner "running autoconf" +$AUTOCONF -Wall +[ $? != 0 ] && exit + +banner "Finished" diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..29db9c9 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# +# usage: +# +# banner <target name> +# +banner() { + echo + TG=`echo $1 | sed -e "s,/.*/,,g"` + LINE=`echo $TG |sed -e "s/./-/g"` + echo $LINE + echo $TG + echo $LINE + echo +} + +banner "autoreconf" + +autoreconf --force --install --symlink -Wall || exit $? + +banner "Finished" diff --git a/config/GNUmakefile.am b/config/GNUmakefile.am new file mode 100644 index 0000000..d3654cc --- /dev/null +++ b/config/GNUmakefile.am @@ -0,0 +1,8 @@ +EXTRA_DIST = \ + ptx-sisyphus.pc.in + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = ptx-sisyphus.pc + +MAINTAINERCLEANFILES = \ + GNUmakefile.in diff --git a/config/m4/.secret-world-domination-project b/config/m4/.secret-world-domination-project new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/config/m4/.secret-world-domination-project diff --git a/config/m4/acx_pthread.m4 b/config/m4/acx_pthread.m4 new file mode 100644 index 0000000..06af842 --- /dev/null +++ b/config/m4/acx_pthread.m4 @@ -0,0 +1,238 @@ +dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +dnl +dnl @summary figure out how to build C programs using POSIX threads +dnl +dnl This macro figures out how to build C programs using POSIX threads. +dnl It sets the PTHREAD_LIBS output variable to the threads library and +dnl linker flags, and the PTHREAD_CFLAGS output variable to any special +dnl C compiler flags that are needed. (The user can also force certain +dnl compiler flags/libs to be tested by setting these environment +dnl variables.) +dnl +dnl Also sets PTHREAD_CC to any special C compiler that is needed for +dnl multi-threaded programs (defaults to the value of CC otherwise). +dnl (This is necessary on AIX to use the special cc_r compiler alias.) +dnl +dnl NOTE: You are assumed to not only compile your program with these +dnl flags, but also link it with them as well. e.g. you should link +dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS +dnl $LIBS +dnl +dnl If you are only building threads programs, you may wish to use +dnl these variables in your default LIBS, CFLAGS, and CC: +dnl +dnl LIBS="$PTHREAD_LIBS $LIBS" +dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +dnl CC="$PTHREAD_CC" +dnl +dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute +dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to +dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +dnl +dnl ACTION-IF-FOUND is a list of shell commands to run if a threads +dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to +dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the +dnl default action will define HAVE_PTHREAD. +dnl +dnl Please let the authors know if this macro fails on any platform, or +dnl if you have any other suggestions or comments. This macro was based +dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with +dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros +dnl posted by Alejandro Forero Cuervo to the autoconf macro repository. +dnl We are also grateful for the helpful feedback of numerous users. +dnl +dnl @category InstalledPackages +dnl @author Steven G. Johnson <stevenj@alum.mit.edu> +dnl @version 2005-06-15 +dnl @license GPLWithACException + +AC_DEFUN([ACX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_SAVE +AC_LANG_C +acx_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) + AC_MSG_RESULT($acx_pthread_ok) + if test x"$acx_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case "${host_cpu}-${host_os}" in + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" + ;; +esac + +if test x"$acx_pthread_ok" = xno; then +for flag in $acx_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) + if test x"$acx_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_TRY_LINK([#include <pthread.h>], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [acx_pthread_ok=yes]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT($acx_pthread_ok) + if test "x$acx_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$acx_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_MSG_CHECKING([for joinable pthread attribute]) + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;], + [attr_name=$attr; break]) + done + AC_MSG_RESULT($attr_name) + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + esac + AC_MSG_RESULT(${flag}) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with cc_r + AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) +else + PTHREAD_CC="$CC" +fi + +AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_CC) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$acx_pthread_ok" = xyes; then + ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) + : +else + acx_pthread_ok=no + $2 +fi +AC_LANG_RESTORE +])dnl ACX_PTHREAD diff --git a/config/ptx-sisyphus.pc.in b/config/ptx-sisyphus.pc.in new file mode 100644 index 0000000..e77e96a --- /dev/null +++ b/config/ptx-sisyphus.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: <name> +Description: <description> +Requires: @REQUIRES_LIBRN@ +Version: @VERSION@ +Libs: -L${libdir} -lptx-sisyphus +#Libs.private: -lm -lpthread ...etc... +Cflags: -I${includedir} diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..526ec42 --- /dev/null +++ b/configure.ac @@ -0,0 +1,135 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. +AC_PREREQ(2.59) + +AC_INIT([ptx-sisyphus], [0.0.0], [bugs@pengutronix.de]) +AC_CONFIG_HEADERS([include/ptx-sisyphus_config.h]) +AC_CONFIG_SRCDIR([src/ptx-sisyphus.c]) +AC_CONFIG_MACRO_DIR([config/m4]) +AC_CONFIG_AUX_DIR([config/autoconf]) +AC_CANONICAL_BUILD +AC_CANONICAL_HOST + +AM_MAINTAINER_MODE + +CFLAGS="${CFLAGS} -Wall" + +# +# libtool library versioning stuff +# +# Library code modified: REVISION++ +# Interfaces changed/added/removed: CURRENT++ REVISION=0 +# Interfaces added: AGE++ +# Interfaces removed: AGE=0 +LT_CURRENT=0 +LT_REVISION=0 +LT_AGE=0 +AC_SUBST(LT_CURRENT) +AC_SUBST(LT_REVISION) +AC_SUBST(LT_AGE) + + +# +# Checks for programs. +# +AC_PROG_CC +#AM_MISSING_PROG(PERL, perl, $missing_dir) +# libtool, old: +AC_LIBTOOL_WIN32_DLL +#AC_LIBTOOL_TAGS([]) +AC_PROG_LIBTOOL +# libtool, new: +# LT_INIT(win32-dll) + +AM_INIT_AUTOMAKE([foreign no-exeext dist-bzip2]) + + +# +# Checks for libraries. +# + +## +# librn +## +# REQUIRES_LIBRN="librn >= 0.4.2" +# AC_SUBST(REQUIRES_LIBRN) +# PKG_CHECK_MODULES([librn], +# [${REQUIRES_LIBRN}], +# [], +# [AC_MSG_ERROR([*** ${REQUIRES_LIBRN} not found by pkg-config on your system])] +# ) +# AC_SUBST(librn_CFLAGS) +# AC_SUBST(librn_LIBS) + +# +# Checks for header files. +# +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS([ \ + arpa/inet.h \ + limits.h \ + netdb.h \ + netinet/in.h \ + stddef.h \ + stdlib.h \ + string.h \ + sys/param.h \ + sys/socket.h \ + sys/time.h \ + sys/un.h \ + unistd.h \ + utime.h \ + ]) + + +# +# Checks for typedefs, structures, and compiler characteristics. +# +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T +AC_HEADER_TIME + + +# +# Checks for library functions. +# +AC_FUNC_MEMCMP +AC_TYPE_SIGNAL +AC_FUNC_STAT +AC_FUNC_UTIME_NULL +AC_CHECK_FUNCS([gethostbyaddr gethostbyname gethostname gettimeofday memset mkdir socket utime]) + + +# +# Debugging +# +AC_MSG_CHECKING([whether to enable debugging]) +AC_ARG_ENABLE(debug, + AS_HELP_STRING([--enable-debug], [enable debugging @<:@default=yes@:>@]), + [case "$enableval" in + y | yes) CONFIG_DEBUG=yes ;; + *) CONFIG_DEBUG=no ;; + esac], + [CONFIG_DEBUG=yes]) +AC_MSG_RESULT([${CONFIG_DEBUG}]) +if test "${CONFIG_DEBUG}" = "yes"; then + CFLAGS="${CFLAGS} -Werror -Wsign-compare -Wfloat-equal -Wformat-security -g -O1" + AC_DEFINE(DEBUG, 1, [debugging]) +else + CFLAGS="${CFLAGS} -O2" +fi + + +AC_CONFIG_FILES([ + GNUmakefile + config/ptx-sisyphus.pc + config/GNUmakefile + include/GNUmakefile + src/GNUmakefile + tests/GNUmakefile + ]) +AC_OUTPUT + diff --git a/include/GNUmakefile.am b/include/GNUmakefile.am new file mode 100644 index 0000000..30150f1 --- /dev/null +++ b/include/GNUmakefile.am @@ -0,0 +1,9 @@ +noinst_HEADERS = \ + ptx-sisyphusstuff.h + +nobase_include_HEADERS = \ + ptx-sisyphus.h + +MAINTAINERCLEANFILES = \ + ptx-sisyphus_config.h.in \ + GNUmakefile.in diff --git a/include/gettext.h b/include/gettext.h new file mode 100644 index 0000000..0565c9e --- /dev/null +++ b/include/gettext.h @@ -0,0 +1,9 @@ +/* simple wrapper */ +#if ENABLE_NLS +# include <libintl.h> +# include <locale.h> +# define _(string) gettext (string) +#else +# define _(string) (string) +#endif + diff --git a/include/ptx-sisyphusstuff.h b/include/ptx-sisyphusstuff.h new file mode 100644 index 0000000..91c4380 --- /dev/null +++ b/include/ptx-sisyphusstuff.h @@ -0,0 +1,5 @@ +#ifndef PTX-SISYPHUS_H +#define PTX-SISYPHUS_H + + +#endif diff --git a/src/GNUmakefile.am b/src/GNUmakefile.am new file mode 100644 index 0000000..9fbaa6f --- /dev/null +++ b/src/GNUmakefile.am @@ -0,0 +1,42 @@ +lib_LTLIBRARIES = \ + libptx-sisyphus.la + +bin_PROGRAMS = \ + alignment \ + context-switches \ + ff_bench \ + float_bench \ + pi_int \ + pi_fpu \ + memxfer + +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include + +float_bench_SOURCES = \ + float_bench.c +float_bench_LDADD = -lm + +ff_bench_SOURCES = \ + ff_bench.c +ff_bench_LDADD = -lm + +pi_int_SOURCES = \ + pi8.c + +pi_fpu_SOURCES = \ + pi8.c +pi_fpu_CPPFLAGS = -DUSEFPU + +alignment_SOURCES = \ + alignment.c + +context_switches_SOURCES = \ + context-switches.c + +timeout_SOURCES = \ + timeout.c + +MAINTAINERCLEANFILES = \ + GNUmakefile.in diff --git a/src/alignment.c b/src/alignment.c new file mode 100644 index 0000000..4b0cb81 --- /dev/null +++ b/src/alignment.c @@ -0,0 +1,46 @@ +/* + * Simple tool to check if unaligned accesses to memory work + * as expected + * + * Copyleft 2009 Sascha Hauer, <s.hauer@pengutronix.de> + * + * + * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + * Version 2, December 2004 + * + * Copyright (C) 2004 Sam Hocevar + * 14 rue de Plaisance, 75014 Paris, France + * Everyone is permitted to copy and distribute verbatim or modified + * copies of this license document, and changing it is allowed as long + * as the name is changed. + * + * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + * + * 0. You just DO WHAT THE FUCK YOU WANT TO. + */ + +#include <stdio.h> +#include <stdlib.h> + +int main(void) +{ + char space[sizeof(unsigned int)]; + char *s = space; + unsigned int *unaligned; + int aligned1 = 0xdeadbeef, aligned2; + + unaligned = (unsigned int *)(s + 1); + + *unaligned = aligned1; + aligned2 = *unaligned; + + if (aligned1 != aligned2) { + fprintf(stderr, "unaligned access failed (0x%08x != 0x%08x)\n", + aligned1, aligned2); + exit(1); + } + + exit(0); +} + diff --git a/src/context-switches.c b/src/context-switches.c new file mode 100644 index 0000000..27a4d60 --- /dev/null +++ b/src/context-switches.c @@ -0,0 +1,190 @@ +/* + * This is a simple tool to measure the amount of context switches on + * a system in a specific period of time. + * It can be used to detect changes in the kernel/scheduler that change + * systems behaviour over the time of development + * + * Its intended for automated usage, so it does no human readable output. + * + * It terminates in to ways: By absolute time or by turns of 1 seconds. + * It can output the measured context switches one value per turn or as two + * values (min max) when it is going to terminate. + */ + +#ifdef HAVE_CONFIG_H +#include <ptx-sisyphus_config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <fcntl.h> +#include <ctype.h> +#include <time.h> +#include <gettext.h> + +static int read_one_string(FILE *fd, char *buffer) +{ + int c; + + while (1) { + c = fgetc(fd); + if (c == EOF || isspace(c)) { + *buffer = '\0'; + break; + } + *buffer++ = c; + }; + + return c == EOF ? 1 : 0; +} + +static unsigned long read_taskswitches(FILE *fd) +{ + char buffer[100]; + int rc; + + /* search for the string 'ctxt', the next value is the one we need */ + do { + rc = read_one_string(fd, buffer); + if (!strcmp(buffer, "ctxt")) { + rc = read_one_string(fd, buffer); + break; + } + } while (rc == 0); + + if (rc != 0) + return -1; + + return strtoul(buffer, NULL, 10); +} + +static int do_the_job(const char *statf, int job_time, int iterations, int collect) +{ + FILE *fd; + unsigned long min, max, last_val, current_val, diff_val; + int rc; + struct timespec tp_start, tp_current; + + /* check if the file exists */ + fd = fopen(statf, "r"); + if (fd == NULL) { + fprintf(stderr, _("Cannot open status file '%s'\n"), statf); + return 1; + } + + if (job_time != -1) { + rc = clock_gettime(CLOCK_MONOTONIC , &tp_start); + if (rc == -1) { + fprintf(stderr, _("Cannot read monotonic time stamp.\n")); + return 1; + } + } + + min = -1; + max = 0UL; + last_val = read_taskswitches(fd); + fclose(fd); + if (last_val == -1) { + fprintf(stderr, _("Failure while reading content of '%s'\n"), statf); + return 1; + } + + while (1) { + sleep(1); + fd = fopen(statf, "r"); + current_val = read_taskswitches(fd); + fclose(fd); + if (last_val == -1) { + fprintf(stderr, _("Failure while reading content of '%s'\n"), statf); + return 1; + } + if (current_val < last_val) { + fprintf(stderr, _("Counter overrun. Please run again")); + return -1; + } + + diff_val = current_val - last_val; + last_val = current_val; + + if (max < diff_val) + max = diff_val; + if (min > diff_val) + min = diff_val; + + if (collect == 0) + printf("%lu\n", diff_val); + + /* check if we have to terminate the loop */ + if (iterations > 0) { + iterations--; + if (iterations == 0) + break; + } + if (job_time != -1) { + rc = clock_gettime(CLOCK_MONOTONIC , &tp_current); + if (tp_current.tv_sec - tp_start.tv_sec >= job_time) + break; + } + }; + + if (collect != 0) + printf("%lu %lu\n", min, max); + + return 0; +} + +static void print_usage(const char *pname) +{ + printf(_("Usage is\n %s [options]\n"), pname); + printf(_("Optional [options] are:\n")); + printf(_(" -s time\n Defines the whole time this programm should run in seconds\n")); + printf(_(" -t turns\n Iteration count, with 1 second pause between each iteration\n")); + printf(_(" -c\n Collect all measurements and output one min/max pair at the end\n")); + printf(_(" -h\n This help text\n")); + printf(_(" -v\n Output version and terminate\n")); + printf(_("Default is no time limit, 10 iterations, no collection\n")); + printf(_("Send bugs to '%s'\n"), PACKAGE_BUGREPORT); +} + +int main(int argc, char *argv[]) +{ + int c, job_time = -1, iterations = -1, collect = 0; + +#if ENABLE_NLS + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); +#endif + + while (1) { + c = getopt(argc, argv, "s:t:hvc"); + if (c == -1) + break; + + switch (c) { + case 't': + iterations = atoi(optarg); + break; + case 's': + job_time = atoi(optarg); + break; + case 'c': + collect = 1; + break; + case 'h': + print_usage(argv[0]); + exit(0); + case 'v': + printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION); + exit(0); + } + } + + c = do_the_job("/proc/stat", job_time, iterations, collect); + + return c; +} diff --git a/src/ff_bench.c b/src/ff_bench.c new file mode 100644 index 0000000..69357ca --- /dev/null +++ b/src/ff_bench.c @@ -0,0 +1,408 @@ +/* + + Two-dimensional FFT benchmark + + Designed and implemented by John Walker in April of 1989. + + This benchmark executes a specified number of passes (default + 20) through a loop in which each iteration performs a fast + Fourier transform of a square matrix (default size 256x256) of + complex numbers (default precision double), followed by the + inverse transform. After all loop iterations are performed + the results are checked against known correct values. + + This benchmark is intended for use on C implementations which + define "int" as 32 bits or longer and permit allocation and + direct addressing of arrays larger than one megabyte. + + If CAPOUT is defined, the result after all iterations is + written as a CA Lab pattern file. This is intended for + debugging in case horribly wrong results are obtained on a + given machine. + + Archival timings are run with the definitions below set as + follows: Float = double, Asize = 256, Passes = 20, CAPOUT not + defined. + + Time (seconds) System + + 2393.93 Sun 3/260, SunOS 3.4, C, "-f68881 -O". + (John Walker). + + 1928 Macintosh IIx, MPW C 3.0, "-mc68020 + -mc68881 -elems881 -m". (Hugh Hoover). + + 1636.1 Sun 4/110, "cc -O3 -lm". (Michael McClary). + The suspicion is that this is software + floating point. + + 1556.7 Macintosh II, A/UX, "cc -O -lm" + (Michael McClary). + + 1388.8 Sun 386i/250, SunOS 4.0.1 C + "-O /usr/lib/trig.il". (James Carrington). + + 1331.93 Sun 3/60, SunOS 4.0.1, C, + "-O4 -f68881 /usr/lib/libm.il" + (Bob Elman). + + 1204.0 Apollo Domain DN4000, C, "-cpu 3000 -opt 4". + (Sam Crupi). + + 1174.66 Compaq 386/25, SCO Xenix 386 C. + (Peter Shieh). + + 1068 Compaq 386/25, SCO Xenix 386, + Metaware High C. (Robert Wenig). + + 1064.0 Sun 3/80, SunOS 4.0.3 Beta C + "-O3 -f68881 /usr/lib/libm.il". (James Carrington). + + 1061.4 Compaq 386/25, SCO Xenix, High C 1.4. + (James Carrington). + + 1059.79 Compaq 386/25, 387/25, High C 1.4, + DOS|Extender 2.2, 387 inline code + generation. (Nathan Bender). + + 777.14 Compaq 386/25, IIT 3C87-25 (387 Compatible), + High C 1.5, DOS|Extender 2.2, 387 inline + code generation. (Nathan Bender). + + 751 Compaq DeskPro 386/33, High C 1.5 + DOS|Extender, + 387 code generation. (James Carrington). + + 431.44 Compaq 386/25, Weitek 3167-25, DOS 3.31, + High C 1.4, DOS|Extender, Weitek code generation. + (Nathan Bender). + + 344.9 Compaq 486/25, Metaware High C 1.6, Phar Lap + DOS|Extender, in-line floating point. (Nathan + Bender). + + 324.2 Data General Motorola 88000, 16 Mhz, Gnu C. + + 323.1 Sun 4/280, C, "-O4". (Eric Hill). + + 254 Compaq SystemPro 486/33, High C 1.5 + DOS|Extender, + 387 code generation. (James Carrington). + + 242.8 Silicon Graphics Personal IRIS, MIPS R2000A, + 12.5 Mhz, "-O3" (highest level optimisation). + (Mike Zentner). + + 233.0 Sun SPARCStation 1, C, "-O4", SunOS 4.0.3. + (Nathan Bender). + + 187.30 DEC PMAX 3100, MIPS 2000 chip. + (Robert Wenig). + + 120.46 Sun SparcStation 2, C, "-O4", SunOS 4.1.1. + (John Walker). + + 120.21 DEC 3MAX, MIPS 3000, "-O4". + + 98.0 Intel i860 experimental environment, + OS/2, data caching disabled. (Kern + Sibbald). + + 34.9 Silicon Graphics Indigo², MIPS R4400, + 175 Mhz, IRIX 5.2, "-O". + + 32.4 Pentium 133, Windows NT, Microsoft Visual + C++ 4.0. + + 17.25 Silicon Graphics Indigo², MIPS R4400, + 175 Mhz, IRIX 6.5, "-O3". + + 14.10 Dell Dimension XPS R100, Pentium II 400 MHz, + Windows 98, Microsoft Visual C 5.0. + + 10.7 Hewlett-Packard Kayak XU 450Mhz Pentium II, + Microsoft Visual C++ 6.0, Windows NT 4.0sp3. (Nathan Bender). + + 5.09 Sun Ultra 2, UltraSPARC V9, 300 MHz, gcc -O3. + + 0.846 Dell Inspiron 9100, Pentium 4, 3.4 GHz, gcc -O3. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/time.h> +#include <math.h> + +/* The program may be run with Float defined as either float or + double. With IEEE arithmetic, the same answers are generated for + either floating point mode. */ + +#define Float double /* Floating point type used in FFT */ + +#define Asize 256 /* Array edge size */ +#define Passes 20 /* Number of FFT/Inverse passes */ + +#define max(a,b) ((a)>(b)?(a):(b)) +#define min(a,b) ((a)<=(b)?(a):(b)) + +#define FWMODE "w" + +/* + + Multi-dimensional fast Fourier transform + + Adapted from Press et al., "Numerical Recipes in C". + +*/ + +#define SWAP(a,b) tempr=(a); (a)=(b); (b)=tempr + +static void fourn(Float data[], int nn[], int ndim, int isign) +{ + int i1, i2, i3; + int i2rev, i3rev, ip1, ip2, ip3, ifp1, ifp2; + int ibit, idim, k1, k2, n, nprev, nrem, ntot; + Float tempi, tempr; + double theta, wi, wpi, wpr, wr, wtemp; + + ntot = 1; + for (idim = 1; idim <= ndim; idim++) + ntot *= nn[idim]; + nprev = 1; + for (idim = ndim; idim >= 1; idim--) { + n = nn[idim]; + nrem = ntot / (n * nprev); + ip1 = nprev << 1; + ip2 = ip1 * n; + ip3 = ip2 * nrem; + i2rev = 1; + for (i2 = 1; i2 <= ip2; i2 += ip1) { + if (i2 < i2rev) { + for (i1 = i2; i1 <= i2 + ip1 - 2; i1 += 2) { + for (i3 = i1; i3 <= ip3; i3 += ip2) { + i3rev = i2rev + i3 - i2; + SWAP(data[i3], data[i3rev]); + SWAP(data[i3 + 1], data[i3rev + 1]); + } + } + } + ibit = ip2 >> 1; + while (ibit >= ip1 && i2rev > ibit) { + i2rev -= ibit; + ibit >>= 1; + } + i2rev += ibit; + } + ifp1 = ip1; + while (ifp1 < ip2) { + ifp2 = ifp1 << 1; + theta = isign * 6.28318530717959 / (ifp2 / ip1); + wtemp = sin(0.5 * theta); + wpr = -2.0 * wtemp * wtemp; + wpi = sin(theta); + wr = 1.0; + wi = 0.0; + for (i3 = 1; i3 <= ifp1; i3 += ip1) { + for (i1 = i3; i1 <= i3 + ip1 - 2; i1 += 2) { + for (i2 = i1; i2 <= ip3; i2 += ifp2) { + k1 = i2; + k2 = k1 + ifp1; + tempr = wr * data[k2] - wi * data[k2 + 1]; + tempi = wr * data[k2 + 1] + wi * data[k2]; + data[k2] = data[k1] - tempr; + data[k2 + 1] = data[k1 + 1] - tempi; + data[k1] += tempr; + data[k1 + 1] += tempi; + } + } + wr = (wtemp = wr) * wpr - wi * wpi + wr; + wi = wi * wpr + wtemp * wpi + wi; + } + ifp1 = ifp2; + } + nprev *= n; + } +} +#undef SWAP + +static void usage(const char *prg, FILE *out) +{ + fprintf(out, "usage: %s [options]\n", prg); + fprintf(out, " options are:\n"); + fprintf(out, " '-d value' calculate a dimension of (value * value). Default is (256 * 256)\n"); + fprintf(out, " '-p value' passes. Default is 20\n"); + fprintf(out, " '-v' print program version and exit\n"); + fprintf(out, " '-h' print this help and exit\n"); +} + +int main(int argc, char *argv[]) +{ + int i, j, k, l, m, npasses = Passes, faedge = Asize, c, ret; + Float *fdata; + static int nsize[] = {0, 0, 0}; + long fanum, fasize; + double mapbase, mapscale, rmin, rmax, imin, imax; + struct timeval begin_tv, end_tv, diff_tv; + + /* handle command line options first */ + while (1) { + c = getopt(argc, argv, "d:p:hv"); + if (c == -1) + break; + + switch (c) { + case 'd': + faedge = atoi(optarg); /* FFT array edge size */ + break; + case 'p': + npasses = atoi(optarg); + break; + case 'h': + usage(argv[0], stdout); + exit(0); + case 'v': + printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION); + exit(0); + } + } + + /* now we start. Get the current time */ + gettimeofday(&begin_tv, NULL); + + fanum = faedge * faedge; /* Elements in FFT array */ + fasize = ((fanum + 1) * 2 * sizeof(Float)); /* FFT array size */ + nsize[1] = nsize[2] = faedge; + + fdata = (Float *) malloc(fasize); + if (fdata == NULL) { + fprintf(stderr, "Can't allocate data array.\n"); + exit(1); + } + + /* Generate data array to process. */ + +#define Re(x,y) fdata[1 + (faedge * (x) + (y)) * 2] +#define Im(x,y) fdata[2 + (faedge * (x) + (y)) * 2] + + memset(fdata, 0, fasize); + for (i = 0; i < faedge; i++) { + for (j = 0; j < faedge; j++) { + if (((i & 15) == 8) || ((j & 15) == 8)) + Re(i, j) = 128.0; + } + } + + for (i = 0; i < npasses; i++) { + /* Transform image to frequency domain. */ + fourn(fdata, nsize, 2, 1); + + /* Back-transform to image. */ + fourn(fdata, nsize, 2, -1); + } + + { + double r, ij, ar, ai; + rmin = 1e10; rmax = -1e10; + imin = 1e10; imax = -1e10; + ar = 0; + ai = 0; + + for (i = 1; i <= fanum; i += 2) { + r = fdata[i]; + ij = fdata[i + 1]; + ar += r; + ai += ij; + rmin = min(r, rmin); + rmax = max(r, rmax); + imin = min(ij, imin); + imax = max(ij, imax); + } +#ifdef DEBUG + printf("Real min %.4g, max %.4g. Imaginary min %.4g, max %.4g.\n", + rmin, rmax, imin, imax); + printf("Average real %.4g, imaginary %.4g.\n", + ar / fanum, ai / fanum); +#endif + mapbase = rmin; + mapscale = 255 / (rmax - rmin); + } + + /* See if we got the right answers. */ + + m = 0; + for (i = 0; i < faedge; i++) { + for (j = 0; j < faedge; j++) { + k = (Re(i, j) - mapbase) * mapscale; + l = (((i & 15) == 8) || ((j & 15) == 8)) ? 255 : 0; + if (k != l) { + m++; + fprintf(stderr, + "Wrong answer at (%d,%d)! Expected %d, got %d.\n", + i, j, l, k); + } + } + } + if (m == 0) { + fprintf(stderr, "%d passes. No errors in results.\n", npasses); + ret = 0; + } else { + fprintf(stderr, "%d passes. %d errors in results.\n", + npasses, m); + ret = 1; + } + +#ifdef CAPOUT + + /* Output the result of the transform as a CA Lab pattern + file for debugging. */ + + { +#define SCRX 322 +#define SCRY 200 +#define SCRN (SCRX * SCRY) + unsigned char patarr[SCRY][SCRX]; + FILE *fp; + +/* Map user external state numbers to internal state index */ + +#define UtoI(x) (((((x) >> 1) & 0x7F) | ((x) << 7)) & 0xFF) + + /* Copy data from FFT buffer to map. */ + + memset(patarr, 0, sizeof patarr); + l = (SCRX - faedge) / 2; + m = (faedge > SCRY) ? 0 : ((SCRY - faedge) / 2); + for (i = 1; i < faedge; i++) { + for (j = 0; j < min(SCRY, faedge); j++) { + k = (Re(i, j) - mapbase) * mapscale; + patarr[j + m][i + l] = UtoI(k); + } + } + + /* Dump pattern map to file. */ + + fp = fopen("fft.cap", "w"); + if (fp == NULL) { + fprintf(stderr, "Cannot open output file.\n"); + exit(0); + } + putc(':', fp); + putc(1, fp); + fwrite(patarr, SCRN, 1, fp); + putc(6, fp); + fclose(fp); + } +#endif + + gettimeofday(&end_tv, NULL); + timersub(&end_tv, &begin_tv, &diff_tv); + + printf("Time(s): %u.%u\n", diff_tv.tv_sec, diff_tv.tv_usec); + + return ret; +} diff --git a/src/float_bench.c b/src/float_bench.c new file mode 100644 index 0000000..a415173 --- /dev/null +++ b/src/float_bench.c @@ -0,0 +1,843 @@ +/* + + John Walker's Floating Point Benchmark, derived from... + + Marinchip Interactive Lens Design System + + John Walker December 1980 + + By John Walker + http://www.fourmilab.ch/ + + This program may be used, distributed, and modified freely as + long as the origin information is preserved. + + This is a complete optical design raytracing algorithm, + stripped of its user interface and recast into portable C. It + not only determines execution speed on an extremely floating + point (including trig function) intensive real-world + application, it checks accuracy on an algorithm that is + exquisitely sensitive to errors. The performance of this + program is typically far more sensitive to changes in the + efficiency of the trigonometric library routines than the + average floating point program. + + The benchmark may be compiled in two modes. If the symbol + INTRIG is defined, built-in trigonometric and square root + routines will be used for all calculations. Timings made with + INTRIG defined reflect the machine's basic floating point + performance for the arithmetic operators. If INTRIG is not + defined, the system library <math.h> functions are used. + Results with INTRIG not defined reflect the system's library + performance and/or floating point hardware support for trig + functions and square root. Results with INTRIG defined are a + good guide to general floating point performance, while + results with INTRIG undefined indicate the performance of an + application which is math function intensive. + + Special note regarding errors in accuracy: this program has + generated numbers identical to the last digit it formats and + checks on the following machines, floating point + architectures, and languages: + + Marinchip 9900 QBASIC IBM 370 double-precision (REAL * 8) format + + IBM PC / XT / AT Lattice C IEEE 64 bit, 80 bit temporaries + High C same, in line 80x87 code + BASICA "Double precision" + Quick BASIC IEEE double precision, software routines + + Sun 3 C IEEE 64 bit, 80 bit temporaries, + in-line 68881 code, in-line FPA code. + + MicroVAX II C Vax "G" format floating point + + Macintosh Plus MPW C SANE floating point, IEEE 64 bit format + implemented in ROM. + + Inaccuracies reported by this program should be taken VERY + SERIOUSLY INDEED, as the program has been demonstrated to be + invariant under changes in floating point format, as long as + the format is a recognised double precision format. If you + encounter errors, please remember that they are just as likely + to be in the floating point editing library or the + trigonometric libraries as in the low level operator code. + + The benchmark assumes that results are basically reliable, and + only tests the last result computed against the reference. If + you're running on a suspect system you can compile this + program with ACCURACY defined. This will generate a version + which executes as an infinite loop, performing the ray trace + and checking the results on every pass. All incorrect results + will be reported. + + Representative timings are given below. All have been + normalised as if run for 1000 iterations. + + Time in seconds Computer, Compiler, and notes + Normal INTRIG + + 3466.00 4031.00 Commodore 128, 2 Mhz 8510 with software floating + point. Abacus Software/Data-Becker Super-C 128, + version 3.00, run in fast (2 Mhz) mode. Note: + the results generated by this system differed + from the reference results in the 8th to 10th + decimal place. + + 3290.00 IBM PC/AT 6 Mhz, Microsoft/IBM BASICA version A3.00. + Run with the "/d" switch, software floating point. + + 2131.50 IBM PC/AT 6 Mhz, Lattice C version 2.14, small model. + This version of Lattice compiles subroutine + calls which either do software floating point + or use the 80x87. The machine on which I ran + this had an 80287, but the results were so bad + I wonder if it was being used. + + 1598.00 Macintosh Plus, MPW C, SANE Software floating point. + + 1582.13 Marinchip 9900 2 Mhz, QBASIC compiler with software + floating point. This was a QBASIC version of the + program which contained the identical algorithm. + + 404.00 IBM PC/AT 6 Mhz, Microsoft QuickBASIC version 2.0. + Software floating point. + + 165.15 IBM PC/AT 6 Mhz, Metaware High C version 1.3, small + model. This was compiled to call subroutines for + floating point, and the machine contained an 80287 + which was used by the subroutines. + + 143.20 Macintosh II, MPW C, SANE calls. I was unable to + determine whether SANE was using the 68881 chip or + not. + + 121.80 Sun 3/160 16 Mhz, Sun C. Compiled with -fsoft switch + which executes floating point in software. + + 78.78 110.11 IBM RT PC (Model 6150). IBM AIX 1.0 C compiler + with -O switch. + + 75.2 254.0 Microsoft Quick C 1.0, in-line 8087 instructions, + compiled with 80286 optimisation on. (Switches + were -Ol -FPi87-G2 -AS). Small memory model. + + 69.50 IBM PC/AT 6Mhz, Borland Turbo BASIC 1.0. Compiled + in "8087 required" mode to generate in-line + code for the math coprocessor. + + 66.96 IBM PC/AT 6Mhz, Microsoft QuickBASIC 4.0. This + release of QuickBASIC compiles code for the + 80287 math coprocessor. + + 66.36 206.35 IBM PC/AT 6Mhz, Metaware High C version 1.3, small + model. This was compiled with in-line code for the + 80287 math coprocessor. Trig functions still call + library routines. + + 63.07 220.43 IBM PC/AT, 6Mhz, Borland Turbo C, in-line 8087 code, + small model, word alignment, no stack checking, + 8086 code mode. + + 17.18 Apollo DN-3000, 12 Mhz 68020 with 68881, compiled + with in-line code for the 68881 coprocessor. + According to Apollo, the library routines are chosen + at runtime based on coprocessor presence. Since the + coprocessor was present, the library is supposed to + use in-line floating point code. + + 15.55 27.56 VAXstation II GPX. Compiled and executed under + VAX/VMS C. + + 15.14 37.93 Macintosh II, Unix system V. Green Hills 68020 + Unix compiler with in-line code for the 68881 + coprocessor (-O -ZI switches). + + 12.69 Sun 3/160 16 Mhz, Sun C. Compiled with -fswitch, + which calls a subroutine to select the fastest + floating point processor. This was using the 68881. + + 11.74 26.73 Compaq Deskpro 386, 16 Mhz 80386 with 16 Mhz 80387. + Metaware High C version 1.3, compiled with in-line + for the math coprocessor (but not optimised for the + 80386/80387). Trig functions still call library + routines. + + 8.43 30.49 Sun 3/160 16 Mhz, Sun C. Compiled with -f68881, + generating in-line MC68881 instructions. Trig + functions still call library routines. + + 6.29 25.17 Sun 3/260 25 Mhz, Sun C. Compiled with -f68881, + generating in-line MC68881 instructions. Trig + functions still call library routines. + + 4.57 Sun 3/260 25 Mhz, Sun FORTRAN 77. Compiled with + -O -f68881, generating in-line MC68881 instructions. + Trig functions are compiled in-line. This used + the FORTRAN 77 version of the program, FBFORT77.F. + + 4.00 14.20 Sun386i/25 Mhz model 250, Sun C compiler. + + 4.00 14.00 Sun386i/25 Mhz model 250, Metaware C. + + 3.10 12.00 Compaq 386/387 25 Mhz running SCO Xenix 2. + Compiled with Metaware HighC 386, optimized + for 386. + + 3.00 12.00 Compaq 386/387 25MHZ optimized for 386/387. + + 2.96 5.17 Sun 4/260, Sparc RISC processor. Sun C, + compiled with the -O2 switch for global + optimisation. + + 2.47 COMPAQ 486/25, secondary cache disabled, High C, + 486/387, inline f.p., small memory model. + + 2.20 3.40 Data General Motorola 88000, 16 Mhz, Gnu C. + + 1.56 COMPAQ 486/25, 128K secondary cache, High C, 486/387, + inline f.p., small memory model. + + 0.66 1.50 DEC Pmax, Mips processor. + + 0.63 0.91 Sun SparcStation 2, Sun C (SunOS 4.1.1) with + -O4 optimisation and "/usr/lib/libm.il" inline + floating point. + + 0.60 1.07 Intel 860 RISC processor, 33 Mhz, Greenhills + C compiler. + + 0.40 0.90 Dec 3MAX, MIPS 3000 processor, -O4. + + 0.31 0.90 IBM RS/6000, -O. + + 0.1129 0.2119 Dell Dimension XPS P133c, Pentium 133 MHz, + Windows 95, Microsoft Visual C 5.0. + + 0.0883 0.2166 Silicon Graphics Indigo², MIPS R4400, + 175 Mhz, "-O3". + + 0.0351 0.0561 Dell Dimension XPS R100, Pentium II 400 MHz, + Windows 98, Microsoft Visual C 5.0. + + 0.0312 0.0542 Sun Ultra 2, UltraSPARC V9, 300 MHz, Solaris + 2.5.1. + + 0.00862 0.01074 Dell Inspiron 9100, Pentium 4, 3.4 GHz, gcc -O3. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#ifndef INTRIG +#include <math.h> +#endif + +#define cot(x) (1.0 / tan(x)) + +#define TRUE 1 +#define FALSE 0 + +#define max_surfaces 10 + +/* Local variables */ + +/* static char tbfr[132]; */ + +static short current_surfaces; +static short paraxial; + +static double clear_aperture; + +static double aberr_lspher; +static double aberr_osc; +static double aberr_lchrom; + +static double max_lspher; +static double max_osc; +static double max_lchrom; + +static double radius_of_curvature; +static double object_distance; +static double ray_height; +static double axis_slope_angle; +static double from_index; +static double to_index; + +static double spectral_line[9]; +static double s[max_surfaces][5]; +static double od_sa[2][2]; + +static char outarr[8][80]; /* Computed output of program goes here */ + +int itercount; /* The iteration counter for the main loop + in the program is made global so that + the compiler should not be allowed to + optimise out the loop over the ray + tracing code. */ + +#ifndef ITERATIONS +#define ITERATIONS 1000 +#endif +int niter = ITERATIONS; /* Iteration counter */ + +static char *refarr[] = { /* Reference results. These happen to + be derived from a run on Microsoft + Quick BASIC on the IBM PC/AT. */ + + " Marginal ray 47.09479120920 0.04178472683", + " Paraxial ray 47.08372160249 0.04177864821", + "Longitudinal spherical aberration: -0.01106960671", + " (Maximum permissible): 0.05306749907", + "Offense against sine condition (coma): 0.00008954761", + " (Maximum permissible): 0.00250000000", + "Axial chromatic aberration: 0.00448229032", + " (Maximum permissible): 0.05306749907" +}; + +/* The test case used in this program is the design for a 4 inch + achromatic telescope objective used as the example in Wyld's + classic work on ray tracing by hand, given in Amateur Telescope + Making, Volume 3. */ + +static double testcase[4][4] = { + {27.05, 1.5137, 63.6, 0.52}, + {-16.68, 1, 0, 0.138}, + {-16.68, 1.6164, 36.7, 0.38}, + {-78.1, 1, 0, 0} +}; + +/* Internal trig functions (used only if INTRIG is defined). These + standard functions may be enabled to obtain timings that reflect + the machine's floating point performance rather than the speed of + its trig function evaluation. */ + +#ifdef INTRIG + +/* The following definitions should keep you from getting intro trouble + with compilers which don't let you redefine intrinsic functions. */ + +#define sin I_sin +#define cos I_cos +#define tan I_tan +#define sqrt I_sqrt +#define atan I_atan +#define atan2 I_atan2 +#define asin I_asin + +#define fabs(x) ((x < 0.0) ? -x : x) + +#define pic 3.1415926535897932 + +/* Commonly used constants */ + +static double pi = pic, + twopi =pic * 2.0, + piover4 = pic / 4.0, + fouroverpi = 4.0 / pic, + piover2 = pic / 2.0; + +/* Coefficients for ATAN evaluation */ + +static double atanc[] = { + 0.0, + 0.4636476090008061165, + 0.7853981633974483094, + 0.98279372324732906714, + 1.1071487177940905022, + 1.1902899496825317322, + 1.2490457723982544262, + 1.2924966677897852673, + 1.3258176636680324644 +}; + +/* aint(x) Return integer part of number. Truncates towards 0 */ + +static double aint(double x) +{ + long l; + + /* Note that this routine cannot handle the full floating point + number range. This function should be in the machine-dependent + floating point library! */ + + l = x; + if ((int)(-0.5) != 0 && l < 0 ) + l++; + x = l; + return x; +} + +/* sin(x) Return sine, x in radians */ + +static double sin(double x) +{ + int sign; + double y, r, z; + + x = (((sign= (x < 0.0)) != 0) ? -x: x); + + if (x > twopi) + x -= (aint(x / twopi) * twopi); + + if (x > pi) { + x -= pi; + sign = !sign; + } + + if (x > piover2) + x = pi - x; + + if (x < piover4) { + y = x * fouroverpi; + z = y * y; + r = y * (((((((-0.202253129293E-13 * z + 0.69481520350522E-11) * z - + 0.17572474176170806E-8) * z + 0.313361688917325348E-6) * z - + 0.365762041821464001E-4) * z + 0.249039457019271628E-2) * z - + 0.0807455121882807815) * z + 0.785398163397448310); + } else { + y = (piover2 - x) * fouroverpi; + z = y * y; + r = ((((((-0.38577620372E-12 * z + 0.11500497024263E-9) * z - + 0.2461136382637005E-7) * z + 0.359086044588581953E-5) * z - + 0.325991886926687550E-3) * z + 0.0158543442438154109) * z - + 0.308425137534042452) * z + 1.0; + } + return sign ? -r : r; +} + +/* cos(x) Return cosine, x in radians, by identity */ + +static double cos(double x) +{ + x = (x < 0.0) ? -x : x; + if (x > twopi) /* Do range reduction here to limit */ + x = x - (aint(x / twopi) * twopi); /* roundoff on add of PI/2 */ + return sin(x + piover2); +} + +/* tan(x) Return tangent, x in radians, by identity */ + +static double tan(double x) +{ + return sin(x) / cos(x); +} + +/* sqrt(x) Return square root. Initial guess, then Newton- + Raphson refinement */ + +double sqrt(double x) +{ + double c, cl, y; + int n; + + if (x == 0.0) + return 0.0; + + if (x < 0.0) { + fprintf(stderr, + "\nGood work! You tried to take the square root of %g", + x); + fprintf(stderr, + "\nunfortunately, that is too complex for me to handle.\n"); + exit(1); + } + + y = (0.154116 + 1.893872 * x) / (1.0 + 1.047988 * x); + + c = (y - x / y) / 2.0; + cl = 0.0; + for (n = 50; c != cl && n--;) { + y = y - c; + cl = c; + c = (y - x / y) / 2.0; + } + return y; +} + +/* atan(x) Return arctangent in radians, + range -pi/2 to pi/2 */ + +static double atan(double x) +{ + int sign, l, y; + double a, b, z; + + x = (((sign = (x < 0.0)) != 0) ? -x : x); + l = 0; + + if (x >= 4.0) { + l = -1; + x = 1.0 / x; + y = 0; + goto atl; + } else { + if (x < 0.25) { + y = 0; + goto atl; + } + } + + y = aint(x / 0.5); + z = y * 0.5; + x = (x - z) / (x * z + 1); + +atl: + z = x * x; + b = ((((893025.0 * z + 49116375.0) * z + 425675250.0) * z + + 1277025750.0) * z + 1550674125.0) * z + 654729075.0; + a = (((13852575.0 * z + 216602100.0) * z + 891080190.0) * z + + 1332431100.0) * z + 654729075.0; + a = (a / b) * x + atanc[y]; + if (l) + a=piover2 - a; + return sign ? -a : a; +} + +/* atan2(y,x) Return arctangent in radians of y/x, + range -pi to pi */ + +static double atan2(double y, double x) +{ + double temp; + + if (x == 0.0) { + if (y == 0.0) /* Special case: atan2(0,0) = 0 */ + return 0.0; + else if (y > 0) + return piover2; + else + return -piover2; + } + temp = atan(y / x); + if (x < 0.0) { + if (y >= 0.0) + temp += pic; + else + temp -= pic; + } + return temp; +} + +/* asin(x) Return arcsine in radians of x */ + +static double asin(double x) +{ + if (fabs(x)>1.0) { + fprintf(stderr, + "\nInverse trig functions lose much of their gloss when"); + fprintf(stderr, + "\ntheir arguments are greater than 1, such as the"); + fprintf(stderr, + "\nvalue %g you passed.\n", x); + exit(1); + } + return atan2(x, sqrt(1 - x * x)); +} +#endif + +/* Calculate passage through surface + + If the variable PARAXIAL is true, the trace through the + surface will be done using the paraxial approximations. + Otherwise, the normal trigonometric trace will be done. + + This routine takes the following inputs: + + RADIUS_OF_CURVATURE Radius of curvature of surface + being crossed. If 0, surface is + plane. + + OBJECT_DISTANCE Distance of object focus from + lens vertex. If 0, incoming + rays are parallel and + the following must be specified: + + RAY_HEIGHT Height of ray from axis. Only + relevant if OBJECT.DISTANCE == 0 + + AXIS_SLOPE_ANGLE Angle incoming ray makes with axis + at intercept + + FROM_INDEX Refractive index of medium being left + + TO_INDEX Refractive index of medium being + entered. + + The outputs are the following variables: + + OBJECT_DISTANCE Distance from vertex to object focus + after refraction. + + AXIS_SLOPE_ANGLE Angle incoming ray makes with axis + at intercept after refraction. + +*/ + +static void transit_surface(void) { + double iang, /* Incidence angle */ + rang, /* Refraction angle */ + iang_sin, /* Incidence angle sin */ + rang_sin, /* Refraction angle sin */ + old_axis_slope_angle, sagitta; + + if (paraxial) { + if (radius_of_curvature != 0.0) { + if (object_distance == 0.0) { + axis_slope_angle = 0.0; + iang_sin = ray_height / radius_of_curvature; + } else + iang_sin = ((object_distance - + radius_of_curvature) / radius_of_curvature) * + axis_slope_angle; + + rang_sin = (from_index / to_index) * + iang_sin; + old_axis_slope_angle = axis_slope_angle; + axis_slope_angle = axis_slope_angle + + iang_sin - rang_sin; + if (object_distance != 0.0) + ray_height = object_distance * old_axis_slope_angle; + object_distance = ray_height / axis_slope_angle; + return; + } + object_distance = object_distance * (to_index / from_index); + axis_slope_angle = axis_slope_angle * (from_index / to_index); + return; + } + + if (radius_of_curvature != 0.0) { + if (object_distance == 0.0) { + axis_slope_angle = 0.0; + iang_sin = ray_height / radius_of_curvature; + } else { + iang_sin = ((object_distance - + radius_of_curvature) / radius_of_curvature) * + sin(axis_slope_angle); + } + iang = asin(iang_sin); + rang_sin = (from_index / to_index) * + iang_sin; + old_axis_slope_angle = axis_slope_angle; + axis_slope_angle = axis_slope_angle + + iang - asin(rang_sin); + sagitta = sin((old_axis_slope_angle + iang) / 2.0); + sagitta = 2.0 * radius_of_curvature*sagitta*sagitta; + object_distance = ((radius_of_curvature * sin( + old_axis_slope_angle + iang)) * + cot(axis_slope_angle)) + sagitta; + return; + } + + rang = -asin((from_index / to_index) * + sin(axis_slope_angle)); + object_distance = object_distance * ((to_index * + cos(-rang)) / (from_index * + cos(axis_slope_angle))); + axis_slope_angle = -rang; +} + +/* Perform ray trace in specific spectral line */ + +static void trace_line(int line, double ray_h) +{ + int i; + + object_distance = 0.0; + ray_height = ray_h; + from_index = 1.0; + + for (i = 1; i <= current_surfaces; i++) { + radius_of_curvature = s[i][1]; + to_index = s[i][2]; + if (to_index > 1.0) + to_index = to_index + ((spectral_line[4] - + spectral_line[line]) / + (spectral_line[3] - spectral_line[6])) * ((s[i][2] - 1.0) / + s[i][3]); + transit_surface(); + from_index = to_index; + if (i < current_surfaces) + object_distance = object_distance - s[i][4]; + } +} + +/* Initialise when called the first time */ + +int main(int argc, char *argv[]) +{ + int i, j, k, errors; + double od_fline, od_cline; +#ifdef ACCURACY + long passes; +#endif + struct timeval begin_tv, end_tv, diff_tv; + + spectral_line[1] = 7621.0; /* A */ + spectral_line[2] = 6869.955; /* B */ + spectral_line[3] = 6562.816; /* C */ + spectral_line[4] = 5895.944; /* D */ + spectral_line[5] = 5269.557; /* E */ + spectral_line[6] = 4861.344; /* F */ + spectral_line[7] = 4340.477; /* G'*/ + spectral_line[8] = 3968.494; /* H */ + + /* Process the number of iterations argument, if one is supplied. */ + + if (argc > 1) { + niter = atoi(argv[1]); + if (*argv[1] == '-' || niter < 1) { + printf("This is John Walker's floating point accuracy and\n"); + printf("performance benchmark program. You call it with\n"); + printf("\n%s <itercount>\n\n", argv[0]); + printf("where <itercount> is the number of iterations\n"); + printf("to be executed. Archival timings should be made\n"); + printf("with the iteration count set so that roughly five\n"); + printf("minutes of execution is timed.\n"); + exit(0); + } + } + + /* Load test case into working array */ + + clear_aperture = 4.0; + current_surfaces = 4; + for (i = 0; i < current_surfaces; i++) + for (j = 0; j < 4; j++) + s[i + 1][j + 1] = testcase[i][j]; + +#ifdef ACCURACY + printf("Beginning execution of floating point accuracy test...\n"); + passes = 0; +#else +/* + printf("Ready to begin John Walker's floating point accuracy\n"); + printf("and performance benchmark. %d iterations will be made.\n\n", niter); + + printf("\nMeasured run time in seconds should be divided by %.f\n", niter / 1000.0); + printf("to normalise for reporting results. For archival results,\n"); + printf("adjust iteration count so the benchmark runs about five minutes.\n\n"); +*/ + /* now we start. Get the current time */ + gettimeofday(&begin_tv, NULL); +#endif + + /* Perform ray trace the specified number of times. */ + +#ifdef ACCURACY + while (TRUE) { + passes++; + if ((passes % 100L) == 0) { + printf("Pass %ld.\n", passes); + } +#else + for (itercount = 0; itercount < niter; itercount++) { +#endif + + for (paraxial = 0; paraxial <= 1; paraxial++) { + + /* Do main trace in D light */ + + trace_line(4, clear_aperture / 2.0); + od_sa[paraxial][0] = object_distance; + od_sa[paraxial][1] = axis_slope_angle; + } + paraxial = FALSE; + + /* Trace marginal ray in C */ + + trace_line(3, clear_aperture / 2.0); + od_cline = object_distance; + + /* Trace marginal ray in F */ + + trace_line(6, clear_aperture / 2.0); + od_fline = object_distance; + + aberr_lspher = od_sa[1][0] - od_sa[0][0]; + aberr_osc = 1.0 - (od_sa[1][0] * od_sa[1][1]) / + (sin(od_sa[0][1]) * od_sa[0][0]); + aberr_lchrom = od_fline - od_cline; + max_lspher = sin(od_sa[0][1]); + + /* D light */ + + max_lspher = 0.0000926 / (max_lspher * max_lspher); + max_osc = 0.0025; + max_lchrom = max_lspher; +#ifndef ACCURACY + } + + gettimeofday(&end_tv, NULL); +#endif + + /* Now evaluate the accuracy of the results from the last ray trace */ + + sprintf(outarr[0], "%15s %21.11f %14.11f", + "Marginal ray", od_sa[0][0], od_sa[0][1]); + sprintf(outarr[1], "%15s %21.11f %14.11f", + "Paraxial ray", od_sa[1][0], od_sa[1][1]); + sprintf(outarr[2], + "Longitudinal spherical aberration: %16.11f", + aberr_lspher); + sprintf(outarr[3], + " (Maximum permissible): %16.11f", + max_lspher); + sprintf(outarr[4], + "Offense against sine condition (coma): %16.11f", + aberr_osc); + sprintf(outarr[5], + " (Maximum permissible): %16.11f", + max_osc); + sprintf(outarr[6], + "Axial chromatic aberration: %16.11f", + aberr_lchrom); + sprintf(outarr[7], + " (Maximum permissible): %16.11f", + max_lchrom); + + /* Now compare the edited results with the master values from + reference executions of this program. */ + + errors = 0; + for (i = 0; i < 8; i++) { + if (strcmp(outarr[i], refarr[i]) != 0) { +#ifdef ACCURACY + printf("\nError in pass %ld for results on line %d...\n", + passes, i + 1); +#else + printf("\nError in results on line %d...\n", i + 1); +#endif + printf("Expected: \"%s\"\n", refarr[i]); + printf("Received: \"%s\"\n", outarr[i]); + printf("(Errors) "); + k = strlen(refarr[i]); + for (j = 0; j < k; j++) { + printf("%c", refarr[i][j] == outarr[i][j] ? ' ' : '^'); + if (refarr[i][j] != outarr[i][j]) + errors++; + } + printf("\n"); + } + } +#ifdef ACCURACY + } +#else + if (errors > 0) { + fprintf(stderr, "\n%d error%s in results. This is VERY SERIOUS.\n", + errors, errors > 1 ? "s" : ""); + return 1; + } +#endif + timersub(&end_tv, &begin_tv, &diff_tv); + + printf("Time(s): %u.%u\n", diff_tv.tv_sec, diff_tv.tv_usec); + + return 0; +} diff --git a/src/memxfer5b.c b/src/memxfer5b.c new file mode 100644 index 0000000..179b2d4 --- /dev/null +++ b/src/memxfer5b.c @@ -0,0 +1,336 @@ +/* Memory streaming benchmark */ + +/* + * Copyright (C) 2003-2006 IBM + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#define __int64 long long +#include <sys/time.h> +#define SLASHC '/' +#define SLASHSTR "/" +#include <sys/types.h> +#include <string.h> +#include <stddef.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <gettext.h> + +#define equal !strcmp + +size_t atoik(char *); +void *Malloc(size_t sz); +void tstart(void); +void tend(void); +double tval(void); + +char *methods[] = { + "\"memcpy\"", + "\"char *\"", + "\"short *\"", + "\"int *\"", + "\"long *\"", + "\"__int64 *\"", + "\"double *\"", +}; +int nmethods = sizeof(methods)/sizeof(methods[0]); + +int fflag = 0; // if 0, then just Malloc once; else malloc/free each time +int wflag = 0; // if 1, call SetProcessWorkingSetSize() (WINDOWS ONLY) +int sflag = 0; // if 1, only print averages. +int pflag = 0; +int csvflag = 0; // Print Comma separated list for spreadsheet input. +char *progname; + +double tottim = 0.0; + +int main(int ac, char *av[]) +{ + size_t size; + int i; + unsigned ui; + size_t j; + unsigned cnt; + int method = 0; + char *p1, *p2; + char *p,*q; + short *sp, *sq; + int *ip, *iq; + long *lp, *lq; + __int64 *llp, *llq; + double *dp, *dq; + double t; + +#if ENABLE_NLS + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); +#endif + + progname = av[0]; + if(strrchr(progname,SLASHC)) + progname = strrchr(progname,SLASHC) + 1; + + while(ac > 1) { + if(equal(av[1], "-f")) { + ac--; + fflag = 1; + av++; + } + else if(equal(av[1], "-w")) { + ac--; + wflag = 1; + av++; + } + else if(equal(av[1], "-s")) { + ac--; + sflag = 1; + av++; + } + else if(equal(av[1], "-p")) { + ac--; + pflag = 1; + av++; + } + else if(equal(av[1], "-csv")) { + ac--; + csvflag++; + av++; + } + else + break; + } + if(ac < 3) { + (void)printf(_("Usage: %s [-f] [-w] [-s] [-p] size cnt [method]\n"),progname); + (void)printf(_("\t-f flag says to malloc and free of the \"cnt\" times.\n")); + (void)printf(_("\t-w = set process min and max working set size to \"size\"\n")); + (void)printf(_("\t-s = silent; only print averages\n")); + (void)printf(_("\t-p = prep; \"freshen\" cache before; -w disables\n")); + (void)printf(_("\t-csv = print output in CSV format\n")); + + (void)printf(_("\tmethods:\n")); + for(i = 0; i < nmethods; i++) + printf("\t%2d:\t%s\n",i,methods[i]); + return 0; + } + + size = atoik(av[1]); + + // + // Round size up to 4*sizeof(double) bytes. + // + if(size != ((size/ (4*sizeof(double)) ) * (4*sizeof(double)) )) { + size += (4*sizeof(double)); + size /= (4*sizeof(double)); + size *= (4*sizeof(double)); + } + cnt = (unsigned)atoik(av[2]); + + if(fflag == 0) { + p1 = (char *)Malloc(size); + p2 = (char *)Malloc(size); + if(pflag) + memcpy(p1,p2,size); + } + +#if 0 + /* disable this output as it confuses our automated detection */ + printf("%s ",progname); + if(fflag) printf("-f "); + if(wflag) printf("-w "); + if(sflag) printf("-s "); + if(pflag) printf("-p "); + if(csvflag) printf("-csv "); + printf("%u %u ", size, cnt); + if(csvflag) { + printf("Linux"); + } + printf("\n"); +#endif + + if(ac == 3) { + ac = 4; + av[3] = "0"; + } + + for(; ac > 3; ac--, av++) { + if(isdigit(*av[3])) method = *av[3] - '0'; + if(method < 0 || method >= nmethods) + method = 0; + if(sflag) + tstart(); + for(ui = 0; ui < cnt; ui++) { + if(!sflag) { + (void)printf("%s %d %d %-18.18s\t", + progname, size, cnt, methods[method]); + tstart(); + } + if(fflag == 1) { + p1 = (char *)Malloc(size); + p2 = (char *)Malloc(size); + } + switch(method) { + case 0: + (void)memcpy(p1, p2, size); + break; + case 1: + p = p1; + q = p2; + for(j = 0; j < size; j++) + *p++ = *q++; + break; + case 2: + sp = (short *)p1; + sq = (short *)p2; + for(j = 0; j < size; j += sizeof(short)) + *sp++ = *sq++; + break; + case 3: + ip = (int *)p1; + iq = (int *)p2; + for(j = 0; j < size; j += sizeof(int)) + *ip++ = *iq++; + break; + case 4: + lp = (long *)p1; + lq = (long *)p2; + for(j = 0; j < size; j += sizeof(long)) + *lp++ = *lq++; + break; + case 5: + llp = (__int64 *)p1; + llq = (__int64 *)p2; + for(j = 0; j < size; j += sizeof(__int64)) + *llp++ = *llq++; + break; + case 6: + dp = (double *)p1; + dq = (double *)p2; + for(j = 0; j < size; j += 4*sizeof(double)) { + *dp++ = *dq++; + *dp++ = *dq++; + *dp++ = *dq++; + *dp++ = *dq++; + } + break; + + } + if(fflag == 1) { + free(p1); + free(p2); + } + if(!sflag) { + tend(); + t = tval(); + tottim += t; + if(t == 0.0) + t = .0001; + printf(_(" %8.6f seconds %8.3f MB/s\n"), + t, + (double)size/t/1000000.); + } + } + if(sflag) { + tend(); + tottim = tval(); + } + if(csvflag) { + printf("%s,%u,%u,%8.3f,%8.3f\n", + methods[method],size,size*cnt,tottim,(double)size/(tottim/cnt)/1000000.); + } + else { + (void)printf(_("\tAVG: %d %-18.18s\t"), size, methods[method]); + (void)printf(" %8.3f MB/s\n", (double)size/(tottim/cnt)/1000000.); + } + tottim = 0.0; + } + return 0; +} + + +size_t atoik(char *s) +{ + size_t ret = 0; + size_t base; + + if(*s == '0') { + base = 8; + if(*++s == 'x' || *s == 'X') { + base = 16; + s++; + } + } + else + base = 10; + + for(; isxdigit(*s); s++) { + if(base == 16) + if(isalpha(*s)) + ret = base*ret + (toupper(*s) - 'A'); + else + ret = base*ret + (*s - '0'); + else if(isdigit(*s)) + ret = base*ret + (*s - '0'); + else + break; + } + for(; isalpha(*s); s++) { + switch(toupper(*s)) { + case 'K': ret *= 1024; break; + case 'M': ret *= 1024*1024; break; + default: + return ret; + } + } + return ret; +} +void *Malloc(size_t sz) +{ + char *p; + + p = (char *)malloc(sz); + if(p == NULL) { + (void)printf(_("malloc(%d) failed\n"),sz); + exit(1); + } + return (void *)p; +} + +static struct timeval _tstart, _tend; + +void tstart(void) +{ + gettimeofday(&_tstart, NULL); +} +void tend(void) +{ + gettimeofday(&_tend, NULL); +} + +double tval() +{ + double t1, t2; + + t1 = (double)_tstart.tv_sec + (double)_tstart.tv_usec/(1000*1000); + t2 = (double)_tend.tv_sec + (double)_tend.tv_usec/(1000*1000); + return t2-t1; +} diff --git a/src/pi8.c b/src/pi8.c new file mode 100644 index 0000000..b26ed6f --- /dev/null +++ b/src/pi8.c @@ -0,0 +1,316 @@ +/* +++Date last modified: 01-Oct-1996 */ + +/* + pi8.c Sept 9, 1996. + + This program is placed into the public domain by its author, + Carey Bloodworth. + + This pi program can calculate pi with either integers, or doubles. + It can also use a variety of formulas. + + This code isn't really optimized because it has to work with both the + long integer version and the double version, and several formulas. + Compromises had to be made in several places. + + When compiling, you can chose to use the FPU or the integer version. + By default, it will chose to work only in integers. If you want to + use the FPU, compile with additional flag -DUSEFPU + + You have a choice of formulas. By default, it will use the Machin + formula of: pi=16arctan(1/5)-4arctan(1/239) + + You could chose to use one of the other formulas. + + for pi=8arctan(1/3)+4arctan(1/7) +#define ARC3 1 + for pi=12arctan(1/4)+4arctan(1/20)+4arctan(1/1985) +#define ARC4 1 + for pi=16arctan(1/5)-4arctan(1/70)+4arctan(1/99) +#define ARC5 1 + for pi=32arctan(1/10)-4arctan(1/239)-16arctan(1/515) +#define ARC10 1 + + Or, of course, you could define it on the compile command line with + the -D switch. + + Timings were done on a Cyrix 486/66, with the slow Turbo C++ v3.0 + 1,000 2,000 3,000 4,000 1,000F 2,000F 3,000F 4,000F + Machin 4 18 45 86 1 5 11 20 + Arc3 6 29 74 140 2 9 20 35 + Arc4 5 24 64 116 2 7 16 29 + Arc5 6 26 65 123 1 6 15 26 + Arc10 4 19 46 86 1 5 11 19 + + All of the combinations above were verified to their indicated + precision and in each case, only the last few digits were wrong, + which is a normal round off / truncation error. + + Better compilers will of course result in faster computations, + but the ratios should be the same. When I used GCC 2.6.3 for + DOS, I computed 4,000 digits with with the Machin formula and + the FPU in 8 seconds. The integer version took 17 seconds. + + I also used the FPU GCC version to compute 65,536 digits of + pi and verified them against the Gutenberg PIMIL10.TXT, and + only the last 4 digits were incorrect. The computations took + 33 minutes and 54 seconds. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <sys/time.h> +#include <unistd.h> + +#define SHOWTIME + +#define DEFAULT_DIGIT_COUNT 2000 + +#if defined USEFPU + +#define BASE 1000000000L +#define BASEDIGITS 9 + +typedef long int SHORT; +typedef double LONG; +#else + +#define BASE 100 +#define BASEDIGITS 2 + +typedef unsigned char SHORT; +typedef long int LONG; +#endif + +typedef long int INDEXER; + + +SHORT *pi, *powers, *term; +INDEXER size = DEFAULT_DIGIT_COUNT; + + +void OutDig(int dig) +{ + static int printed = 0; + + putchar(dig + '0'); + printed++; + if ((printed%1000) == 0) + { + printed = 0; + printf("\n\n\n"); + } + if ((printed%50) == 0) + printf("\n"); + else if ((printed%10) == 0) + putchar(' '); +} + + +void PrintShort(SHORT num) +{ + int x; + int digits[BASEDIGITS + 1]; + + for (x = 0; x < BASEDIGITS; x++) + { + digits[x] = num % 10; + num /= 10; + } + for (x = BASEDIGITS - 1; x >= 0; x--) + OutDig(digits[x]); +} + +void Print(SHORT *num) +{ + INDEXER x; + + printf("\nPI = 3.\n"); + for (x = 1; x < size; x++) + PrintShort(num[x]); + printf("\n"); +} + +void arctan(int multiplier, int denom, int sign) +{ + INDEXER x; + LONG remain, temp, divisor, denom2; + SHORT NotZero = 1; + INDEXER adv; + + for (x = 0; x < size; x++) + powers[x] = 0; + + divisor = 1; + denom2 = (LONG)denom;denom2 *= denom2; + adv = 0; + + remain = (LONG)multiplier * denom; + while (NotZero) + { + for (x = adv; x < size; x++) + { + temp = (LONG)powers[x] + remain; + powers[x] = (SHORT)(temp / denom2); + remain = (temp - (denom2 * (LONG)powers[x])) * BASE; + } + + remain = 0; + for (x = adv; x < size; x++) + { + temp = (LONG)powers[x] + remain; + term[x] = (SHORT)(temp / divisor); + remain = (temp - (divisor * (LONG)term[x])) * BASE; + } + remain = 0; + + if (sign > 0) + { + LONG carry, sum; + + carry = 0; + for (x = size - 1; x >=0; x--) + { + sum = (LONG)pi[x] + (LONG)term[x] + carry; + carry = 0; + if (sum >= BASE) + { + carry = 1; + sum -= BASE; + } + pi[x] = (SHORT)sum; + } + } + else + { + LONG borrow, sum; + + borrow = 0; + for (x = size - 1; x >= 0; x--) + { + sum = (LONG)pi[x] - (LONG)term[x] - borrow; + borrow = 0; + if (sum < 0) + { + borrow = 1; + sum += BASE; + } + pi[x] = (SHORT)sum; + } + } + + sign = -sign; + divisor += 2; + NotZero = 0; + for (x = adv; x < size; x++) + { + if (powers[x]) + { + NotZero = 1; + break; + } + } + + if (NotZero) + { + while (powers[adv] == 0) + adv++; + } + /* We can skip ones that are already 0 */ + } +} + +static void usage(const char *prg, FILE *out) +{ + fprintf(out, "usage: %s [options]\n", prg); + fprintf(out, " options are:\n"); + fprintf(out, " '-c count' digits to compute. Default is %ld, should not be 0.\n", size); + fprintf(out, " '-q' be quiet, do not emit pi\n"); + fprintf(out, " '-v' print program version and exit\n"); + fprintf(out, " '-h' print this help and exit\n"); +} + +int main(int argc, char *argv[]) +{ + INDEXER x; + int quiet = 0, c; + struct timeval start, stop, diff; + + /* handle command line options first */ + while (1) { + c = getopt(argc, argv, "c:qhv"); + if (c == -1) + break; + + switch (c) { + case 'c': + size = atoi(optarg); /* digits to compute */ + break; + case 'q': + quiet = 1; + break; + case 'h': + usage(argv[0], stdout); + exit(EXIT_SUCCESS); + case 'v': + printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION); + exit(EXIT_SUCCESS); + } + } + + if (! size) { + usage(argv[0], stderr); + exit(EXIT_FAILURE); + } + + size = ((size + BASEDIGITS - 1) / BASEDIGITS) + 1; + + pi = malloc(sizeof(SHORT) * size); + powers = malloc(sizeof(SHORT) * size); + term = malloc(sizeof(SHORT) * size); + + if ((pi == NULL) || (powers == NULL) || (term == NULL)) { + fprintf(stderr, "Unable to allocate enough memory.\n"); + exit(EXIT_FAILURE); + } + + for (x = 0; x < size; x++) + pi[x] = 0; + + gettimeofday(&start, NULL); + +#if defined ARC3 + arctan(8, 3, 1); + arctan(4, 7, 1); +#elif defined ARC5 + arctan(16, 5, 1); + arctan(4, 70, -1); + arctan(4, 99, 1); +#elif defined ARC4 + arctan(12, 4, 1); + arctan(4, 20, 1); + arctan(4, 1985, 1); +#elif defined ARC10 + arctan(32, 10, 1); + arctan(4, 239, -1); + arctan(16, 515, -1); +#else + /* Machin formula */ + arctan(16, 5, 1); + arctan(4, 239, -1); +#endif + + gettimeofday(&stop, NULL); + if (!quiet) + Print(pi); + + timersub(&stop, &start, &diff); + printf("\nTime (s): %ld.%ld\n", diff.tv_sec, diff.tv_usec); + + return EXIT_SUCCESS; +} diff --git a/src/timeout.c b/src/timeout.c new file mode 100644 index 0000000..7b784c5 --- /dev/null +++ b/src/timeout.c @@ -0,0 +1,188 @@ +/* + *LICENSE + * The IBM PUBLIC LICENSE must be distributed with this + * software. + * HISTORY + * This program was first released as part of SATAN. + * AUTHOR(S) + * Wietse Venema + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +/* System libraries. */ + +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <pthread.h> +#include <string.h> +#include <sched.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> + +static int kill_signal = SIGKILL; +static const char *commandname; +/* the child we control */ +static pid_t child_pid; + +static void usage(const char *prg, FILE *out) +{ + fprintf(out, "usage: %s [options] -t time \"command...\"\n", prg); + fprintf(out, " 'time' in seconds (default), or seconds/minutes/hours/days with the extensions 's|m|h|d'\n"); + fprintf(out, " options are:\n"); + fprintf(out, " '-s signal' to send to the controlled application when the timeout is reached\n"); + fprintf(out, " - default is SIGKILL\n"); + fprintf(out, " '-v' print program version and exit\n"); + fprintf(out, " '-h' print this help and exit\n"); +} + +/* + * kill all children in the case we are receiving a signal + */ +static void terminate(int sig) +{ + signal(kill_signal, SIG_DFL); /* maybe 'sig' instead of 'kill_signal' ? */ + /* kill the whole process group */ + kill(-child_pid, kill_signal); +} + +int main(int argc, char *argv[]) +{ + int time_to_run = -1, status, current_sched, c; + pid_t pid; + struct sched_param schedp; + char modifier = 's'; /* seconds are the default */ + + if (argc == 1) { + usage(argv[0], stderr); + exit(1); + } + + /* handle command line options first */ + while (1) { + c = getopt(argc, argv, "s:t:hv"); + if (c == -1) + break; + + switch (c) { + case 't': + status = sscanf(optarg, "%d%c", &time_to_run, &modifier); + if (status == 0) { + fprintf(stderr, "Error: Need proper time input.\n"); + usage(argv[0], stderr); + exit(1); + } + switch (modifier) { + case 's': + break; /* use value as given */ + case 'm': + time_to_run *= 60; + break; + case 'h': + time_to_run *= (60 * 60); + break; + case 'd': + time_to_run *= (60 * 60 * 24); + break; + default: + fprintf(stderr, "Invalid time modifier, try: s|m|h|d\n"); + exit(1); + } + break; + case 's': + kill_signal = atoi(optarg); + break; + case 'h': + usage(argv[0], stdout); + exit(0); + case 'v': + printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION); + exit(0); + } + } + + if (optind < argc) + commandname = argv[optind]; + + if (time_to_run == -1) { + fprintf(stderr, "No timeout value given\n"); + usage(argv[0], stderr); + exit(1); + } + + current_sched = sched_getscheduler(0); + /* + * To avoid a race, we rise our priority *right now*. + * Omit error handling. This program will be run as root. + */ + memset(&schedp, 0, sizeof(schedp)); + schedp.sched_priority = sched_get_priority_max(SCHED_FIFO); /* highest! */ + sched_setscheduler(0, SCHED_FIFO, &schedp); + + switch (child_pid = fork()) { + case -1: /* error */ + perror("timeout: fork"); + exit(50); + + case 00: /* run controlled command */ + /* + * Lower priority to a regular value + */ + memset(&schedp, 0, sizeof(schedp)); + schedp.sched_priority = sched_get_priority_min(current_sched); /* standard */ + sched_setscheduler(0, current_sched, &schedp); + /* + * Become a separate process group leader. This will ensure + * the parent can kill all members of this process group + * and not itself by accident. + */ + pid = setsid(); /* we are now the leader of a process group */ + if (pid == (pid_t)-1) + perror("Becoming group leader"); + + execvp(argv[optind], &argv[optind]); + perror(commandname); + exit(60); + + default: /* become watchdog */ + /* + * we now should be the process with the strongest + * priority in the system. Lets keep an eye on our + * child + */ + (void) signal(SIGHUP, terminate); + (void) signal(SIGINT, terminate); + (void) signal(SIGQUIT, terminate); + (void) signal(SIGTERM, terminate); + (void) signal(SIGALRM, terminate); + alarm(time_to_run); + /* + * Wait until our child terminates + */ + while ((pid = wait(&status)) != -1 && pid != child_pid) + /* void */ ; + + if (pid != child_pid) + return 70; /* something really strange happens */ + + if (WIFEXITED(status)) { + /* + * Does our child finds a regular end? + */ + return WEXITSTATUS(status); /* return its value */ + } + + if (WIFSIGNALED(status)) { + /* + * Terminated by a signal? + */ + return 80 + WTERMSIG(status); + } + } + + return 71; /* other strange things are happened */ +} diff --git a/wizzard.sh b/wizzard.sh new file mode 100755 index 0000000..a6862bd --- /dev/null +++ b/wizzard.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +if [ -f wizzard.sh ]; then + echo "error: run wizzard.sh from the directory you want to autotoolize" + exit 1 +fi + +SKELDIR=$(cd $(dirname $0) && pwd) +HERE=$(pwd) +echo -n "project name: " +read NAME +NAME_UP=$(echo $NAME | tr '[a-z]' '[A-Z]') + +tar -C "${SKELDIR}" -c . --exclude .svn | tar -C "${HERE}" -xf - + +mv "config/@name@.pc.in" "config/${NAME}.pc.in" +mv "src/lib@name@.c" "src/lib${NAME}.c" +mv "src/@name@.c" "src/${NAME}.c" +mv "include/@name@.h" "include/${NAME}.h" +mv "include/@name@stuff.h" "include/${NAME}stuff.h" + +for i in \ + configure.ac \ + config/GNUmakefile.am \ + config/${NAME}.pc.in \ + include/GNUmakefile.am \ + src/GNUmakefile.am \ + tests/GNUmakefile.am \ + include/${NAME}.h \ + include/${NAME}stuff.h \ +; do + sed -i -e "s/\@name\@/${NAME}/g" $i + sed -i -e "s/\@NAME\@/${NAME_UP}/g" $i +done + |