1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <inttypes.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <threads.h>
10 #include <unistd.h>
11
12 #include <zircon/compiler.h>
13 #include <zircon/syscalls.h>
14 #include <unittest/unittest.h>
15
16 #define THREAD_COUNT 8
17 #define ITER 1000000
18
19 /* expected double bit pattern for each thread */
20 static const uint64_t expected[THREAD_COUNT] = {
21 0x4284755ed4188b3e,
22 0x4284755ed6cb84c0,
23 0x4284755ed97e7dd3,
24 0x4284755edc317770,
25 0x4284755edee471b9,
26 0x4284755ee1976c19,
27 0x4284755ee44a648b,
28 0x4284755ee6fd5fa7,
29 };
30
31 /* optimize this function to cause it to try to use a lot of registers */
32 __OPTIMIZE("O3")
float_thread(void * arg)33 static int float_thread(void* arg) {
34 double* val = arg;
35 unsigned int i, j;
36 double a[16];
37
38 unittest_printf("float_thread arg %f, running %u iterations\n", *val, ITER);
39 usleep(500000);
40
41 /* do a bunch of work with floating point to test context switching */
42 a[0] = *val;
43 for (i = 1; i < countof(a); i++) {
44 a[i] = a[i - 1] * 1.01;
45 }
46
47 for (i = 0; i < ITER; i++) {
48 a[0] += i;
49 for (j = 1; j < countof(a); j++) {
50 a[j] += a[j - 1] * 0.00001;
51 }
52 }
53
54 *val = a[countof(a) - 1];
55 return 0;
56 }
57
fpu_test(void)58 bool fpu_test(void) {
59 BEGIN_TEST;
60
61 unittest_printf("welcome to floating point test\n");
62
63 /* test lazy fpu load on separate thread */
64 thrd_t t[THREAD_COUNT];
65 double val[countof(t)];
66 char name[ZX_MAX_NAME_LEN];
67
68 unittest_printf("creating %zu floating point threads\n", countof(t));
69 for (unsigned int i = 0; i < countof(t); i++) {
70 val[i] = i;
71 snprintf(name, sizeof(name), "fpu thread %u", i);
72 thrd_create_with_name(&t[i], float_thread, &val[i], name);
73 }
74
75 for (unsigned int i = 0; i < countof(t); i++) {
76 thrd_join(t[i], NULL);
77 void* v = &val[i];
78 uint64_t int64_val = *(uint64_t*)v;
79
80 unittest_printf("float thread %u returns val %f %#"
81 PRIx64 ", expected %#" PRIx64 "\n",
82 i, val[i], int64_val, expected[i]);
83 EXPECT_EQ(int64_val, expected[i], "Value does not match as expected");
84 }
85
86 unittest_printf("floating point test done\n");
87 END_TEST;
88 }
89
90 BEGIN_TEST_CASE(fpu_tests)
91 RUN_TEST(fpu_test);
END_TEST_CASE(fpu_tests)92 END_TEST_CASE(fpu_tests)
93
94 int main(int argc, char** argv) {
95 bool success = unittest_run_all_tests(argc, argv);
96 return success ? 0 : -1;
97 }
98