/* * Copyright (c) 2005 Jakub Vana * Copyright (c) 2005 Jakub Jermar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if (defined(ia32) || defined(amd64) || defined(ia64) || defined(ia32xen)) #include #include #include #include #include #include #include #define THREADS 150 #define ATTEMPTS 100 #define E_10e8 271828182 #define PI_10e8 314159265 #ifdef KERN_ia32_ARCH_H_ static inline double sqrt(double x) { double v; asm ( "fsqrt\n" : "=t" (v) : "0" (x) ); return v; } #endif #ifdef KERN_amd64_ARCH_H_ static inline double sqrt(double x) { double v; asm ( "fsqrt\n" : "=t" (v) : "0" (x) ); return v; } #endif #ifdef KERN_ia64_ARCH_H_ #undef PI_10e8 #define PI_10e8 3141592 static inline long double sqrt(long double a) { long double x = 1; long double lx = 0; if (a < 0.00000000000000001) return 0; while(x != lx) { lx = x; x = (x + (a / x)) / 2; } return x; } #endif static atomic_t threads_ok; static atomic_t threads_fault; static waitq_t can_start; static bool sh_quiet; static void e(void *data) { int i; double e, d, le, f; thread_detach(THREAD); waitq_sleep(&can_start); for (i = 0; itid, (unative_t) (100000000 * e), (unative_t) E_10e8); atomic_inc(&threads_fault); break; } } atomic_inc(&threads_ok); } static void pi(void *data) { int i; double lpi, pi; double n, ab, ad; thread_detach(THREAD); waitq_sleep(&can_start); for (i = 0; i < ATTEMPTS; i++) { lpi = -1; pi = 0; for (n = 2, ab = sqrt(2); lpi != pi; n *= 2, ab = ad) { double sc, cd; sc = sqrt(1 - (ab * ab / 4)); cd = 1 - sc; ad = sqrt(ab * ab / 4 + cd * cd); lpi = pi; pi = 2 * n * ad; } #ifdef KERN_ia64_ARCH_H_ if ((int) (1000000 * pi) != PI_10e8) { if (!sh_quiet) printf("tid%llu: pi*10e8=%zd should be %zd\n", THREAD->tid, (unative_t) (1000000 * pi), (unative_t) (PI_10e8 / 100)); atomic_inc(&threads_fault); break; } #else if ((int) (100000000 * pi) != PI_10e8) { if (!sh_quiet) printf("tid%llu: pi*10e8=%zd should be %zd\n", THREAD->tid, (unative_t) (100000000 * pi), (unative_t) PI_10e8); atomic_inc(&threads_fault); break; } #endif } atomic_inc(&threads_ok); } char * test_fpu1(bool quiet) { unsigned int i, total = 0; sh_quiet = quiet; waitq_initialize(&can_start); atomic_set(&threads_ok, 0); atomic_set(&threads_fault, 0); if (!quiet) printf("Creating %d threads... ", 2 * THREADS); for (i = 0; i < THREADS; i++) { thread_t *t; if (!(t = thread_create(e, NULL, TASK, 0, "e", false))) { if (!quiet) printf("could not create thread %d\n", 2 * i); break; } thread_ready(t); total++; if (!(t = thread_create(pi, NULL, TASK, 0, "pi", false))) { if (!quiet) printf("could not create thread %d\n", 2 * i + 1); break; } thread_ready(t); total++; } if (!quiet) printf("ok\n"); thread_sleep(1); waitq_wakeup(&can_start, WAKEUP_ALL); while (atomic_get(&threads_ok) != total) { if (!quiet) printf("Threads left: %d\n", total - atomic_get(&threads_ok)); thread_sleep(1); } if (atomic_get(&threads_fault) == 0) return NULL; return "Test failed"; } #endif