/* fptst.c: i387 benchmark/test program for Linux * Build this program with optimization (-O2 may be faster than -O3) * * v0.11 should work on a wider variety of glibc versions (tested: 2.3.2, 2.3.3) * (See below...) * v0.12 fixed bug in setaffinity: CPU set was empty * * Comments welcome. * Author: Chuck Ebbert <[EMAIL PROTECTED]> */
/* Uncomment this if you get compile errors with the setaffinity function */ /* #define SETAFFINITY_TAKES_2_ARGS */ #define FPTST_VERSION "0.12" #define _GNU_SOURCE #include <sys/types.h> #include <sys/wait.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <signal.h> #include <errno.h> #include <sched.h> #define COND_YIELD(iters, ctr) \ if ((iters) > 0 && ++(ctr) > (iters)) { \ (ctr) = 0; \ sched_yield(); \ } #define RDTSCLL(r) __asm__ __volatile__("rdtsc" : "=A" (r)) #ifdef SETAFFINITY_TAKES_2_ARGS #define setaffinity(pid, mask) sched_setaffinity((pid), &(mask)) #else #define setaffinity(pid, mask) sched_setaffinity((pid), sizeof(mask), &(mask)) #endif long double c_res, p_res; long long i, c_iters, p_iters = 0; unsigned long long tsc1, tsc2; cpu_set_t cpuset; int fp = 0, in = 0, yi = 0; int p_ctr = 0, c_ctr = 0, get; volatile int lo = 1; static void handler(int sig) { lo = 0; /* child exited -- stop looping */ } struct sigaction sa = { .sa_handler = handler, }; void usage(char *prog) { printf("\n i387 floating point benchmark/test program v" FPTST_VERSION); printf("\n\n Usage:\n"); printf("\t%s [-f] [-i] [-a] [-y count] loops\n\n", prog); printf("\t-f : loop in parent process waiting for child to exit\n"); printf("\t-i : do integer math while looping instead of FP math\n"); printf("\t (-f and -i: do one FP operation, then use integer math)\n"); printf("\t-a : run parent and child on single CPU (requires SMP)\n"); printf("\t-y : yield CPU every 'count' loops in parent and child\n\n"); exit(1); } static void do_parent() { if (fp) __asm__ ("fld1 ; fldz"); while (lo) { if (fp & !in) __asm__ ("fadd %st(1), %st(0)"); else p_iters++; COND_YIELD(yi, p_ctr); } if (fp) __asm__ ("fxch ; fstpt p_res ; fstpt p_res"); if (fp & !in) p_iters = (long long)p_res; printf("Parent did: %14lld loops\n", p_iters); } static void do_child() { RDTSCLL(tsc1); __asm__ ("fld1 ; fldz"); for (i = 0; i < c_iters; i++) { __asm__ ("fadd %st(1), %st(0)"); COND_YIELD(yi, c_ctr); } __asm__ ("fxch ; fstpt c_res ; fstpt c_res"); RDTSCLL(tsc2); if (c_res != (long double)c_iters) printf("FP error! Result was %Lg; expected %lld\n", c_res, c_iters); printf("CPU clocks: %14llu\n", tsc2 - tsc1); } int main(int argc, char * const argv[]) { do { switch (get = getopt(argc, argv, "fiay:")) { case 'f': fp = 1; break; case 'i': in = 1; break; case 'a': memset(&cpuset, 0, sizeof(cpuset)); CPU_SET(1, &cpuset); if (setaffinity(0, cpuset)) { perror("While setting CPU affinity"); get = '?'; } break; case 'y': yi = atoi(optarg); if (yi <= 0) { printf("-y: count must be greater than zero\n"); get = '?'; } break; default: break; } } while (get != -1 && get != '?'); if (get == '?' || optind >= argc) usage(argv[0]); c_iters = atoll(argv[optind]); if (fp | in) sigaction(SIGCHLD, &sa, NULL); if (fork()) if (fp | in) do_parent(); else wait(NULL); else do_child(); return 0; } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/