1 /*
2 * Copyright (c) 2019 Synopsys, Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <stdio.h>
9
10 /* Amount of execution threads to create and run */
11 #define THREADS_NUM 16
12
13 /*
14 * Amount of digits of Pi to calculate, must be a multiple of 4,
15 * as used algorithm spits 4 digits on every iteration.
16 */
17 #define DIGITS_NUM 240
18
19 #define LENGTH ((DIGITS_NUM / 4) * 14)
20 #define STACK_SIZE ((LENGTH * sizeof(int) + 1280))
21
22 #ifdef CONFIG_SMP
23 #define CORES_NUM arch_num_cpus()
24 #else
25 #define CORES_NUM 1
26 #endif
27
28 static K_THREAD_STACK_ARRAY_DEFINE(tstack, THREADS_NUM, STACK_SIZE);
29 static struct k_thread tthread[THREADS_NUM];
30 static char th_buffer[THREADS_NUM][DIGITS_NUM + 1];
31 static atomic_t th_counter = THREADS_NUM;
32
test_thread(void * arg1,void * arg2,void * arg3)33 void test_thread(void *arg1, void *arg2, void *arg3)
34 {
35 atomic_t *counter = (atomic_t *)arg1;
36 char *buffer = (char *)arg2;
37
38 ARG_UNUSED(arg3);
39
40 /*
41 * Adapted and improved (for random number of digits) version of Pi
42 * calculation program initially proposed by Dik T. Winter as:
43 * -------------------------------->8--------------------------------
44 * int a=10000,b,c=2800,d,e,f[2801],g;main(){for(;b-c;)f[b++]=a/5;
45 * for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a)for(b=c;d+=f[b]*a,
46 * f[b]=d%--g,d/=g--,--b;d*=b);}
47 * -------------------------------->8--------------------------------
48 */
49 #define NEW_BASE 10000
50 #define ARRAY_INIT 2000
51
52 int array[LENGTH + 1] = {};
53 int carry = 0;
54 int i, j;
55
56 for (i = 0; i < LENGTH; i++) {
57 array[i] = ARRAY_INIT;
58 }
59
60 for (i = LENGTH; i > 0; i -= 14) {
61 int sum = 0, value;
62
63 for (j = i; j > 0; --j) {
64 sum = sum * j + NEW_BASE * array[j];
65 array[j] = sum % (j * 2 - 1);
66 sum /= j * 2 - 1;
67 }
68
69 value = carry + sum / NEW_BASE;
70 carry = sum % NEW_BASE;
71
72 /* Convert 4-digit int to string */
73 sprintf(buffer, "%.4d", value);
74 buffer += 4;
75 }
76
77 atomic_dec(counter);
78 }
79
main(void)80 int main(void)
81 {
82 uint32_t start_time, stop_time, cycles_spent, nanoseconds_spent;
83 int i;
84
85 printk("Calculate first %d digits of Pi independently by %d threads.\n",
86 DIGITS_NUM, THREADS_NUM);
87
88 /* Capture initial time stamp */
89 start_time = k_cycle_get_32();
90
91 for (i = 0; i < THREADS_NUM; i++) {
92 k_thread_create(&tthread[i], tstack[i], STACK_SIZE,
93 test_thread,
94 (void *)&th_counter, (void *)th_buffer[i], NULL,
95 K_PRIO_COOP(10), 0, K_NO_WAIT);
96 }
97
98 /* Wait for all workers to finish their calculations */
99 while (th_counter) {
100 k_sleep(K_MSEC(1));
101 }
102
103 /* Capture final time stamp */
104 stop_time = k_cycle_get_32();
105
106 cycles_spent = stop_time - start_time;
107 nanoseconds_spent = (uint32_t)k_cyc_to_ns_floor64(cycles_spent);
108
109 for (i = 0; i < THREADS_NUM; i++) {
110 printk("Pi value calculated by thread #%d: %s\n", i, th_buffer[i]);
111 }
112
113 printk("All %d threads executed by %d cores in %d msec\n", THREADS_NUM,
114 CORES_NUM, nanoseconds_spent / 1000 / 1000);
115 return 0;
116 }
117